feat(shell-surface-pressure-load): step 5 - integrate-nonlinear-follower-pressure
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include "fesa/analysis/newton_iteration_log.h"
|
||||
#include "fesa/analysis/nonlinear_static_control.h"
|
||||
#include "fesa/assembly/parallel_for.h"
|
||||
#include "fesa/assembly/surface_pressure_assembler.h"
|
||||
#include "fesa/constraints/essential_constraint_policy.h"
|
||||
#include "fesa/elements/finite_rotation.h"
|
||||
#include "fesa/elements/mitc4_shell.h"
|
||||
@@ -453,6 +454,76 @@ Result<SparseMatrix> Difference(const SparseMatrix& internal,
|
||||
dofs.GetSparsePattern());
|
||||
}
|
||||
|
||||
/// @brief Adds fixed and follower external candidates in stable CSR order.
|
||||
Result<GlobalFixedLoadContribution> CombineExternalContributions(
|
||||
const GlobalFixedLoadContribution& fixed,
|
||||
const SurfacePressureAssemblyCandidate& pressure, const DofManager& dofs) {
|
||||
if (fixed.generalized_external_force.Size() !=
|
||||
pressure.full_external_force.Size() ||
|
||||
fixed.generalized_external_tangent.Rows() !=
|
||||
pressure.full_external_tangent.Rows() ||
|
||||
fixed.generalized_external_tangent.Columns() !=
|
||||
pressure.full_external_tangent.Columns() ||
|
||||
fixed.generalized_external_tangent.RowOffsets() !=
|
||||
pressure.full_external_tangent.RowOffsets() ||
|
||||
fixed.generalized_external_tangent.ColumnIndices() !=
|
||||
pressure.full_external_tangent.ColumnIndices()) {
|
||||
return Result<GlobalFixedLoadContribution>::Failure(ProcedureFailure(
|
||||
FailureCategory::kSolver, "nonfinite-newton-data", {},
|
||||
"NONLINEAR_STATIC_PROCEDURE", {},
|
||||
"Nonlinear fixed and pressure external candidates must share the "
|
||||
"stable full-space dimension and pattern."));
|
||||
}
|
||||
|
||||
Vector force{fixed.generalized_external_force.Size()};
|
||||
for (std::size_t index = 0U; index < force.Size(); ++index) {
|
||||
force[index] = fixed.generalized_external_force[index] +
|
||||
pressure.full_external_force[index];
|
||||
if (!std::isfinite(force[index])) {
|
||||
return Result<GlobalFixedLoadContribution>::Failure(ProcedureFailure(
|
||||
FailureCategory::kSolver, "nonfinite-newton-data", {},
|
||||
"NONLINEAR_STATIC_PROCEDURE", std::to_string(index),
|
||||
"Nonlinear fixed and pressure force composition is nonfinite."));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CooContribution> contributions;
|
||||
contributions.reserve(fixed.generalized_external_tangent.Values().size());
|
||||
for (std::size_t row = 0U; row < fixed.generalized_external_tangent.Rows();
|
||||
++row) {
|
||||
for (std::size_t offset =
|
||||
fixed.generalized_external_tangent.RowOffsets()[row];
|
||||
offset < fixed.generalized_external_tangent.RowOffsets()[row + 1U];
|
||||
++offset) {
|
||||
const double tangent =
|
||||
fixed.generalized_external_tangent.Values()[offset] +
|
||||
pressure.full_external_tangent.Values()[offset];
|
||||
if (!std::isfinite(tangent)) {
|
||||
return Result<GlobalFixedLoadContribution>::Failure(ProcedureFailure(
|
||||
FailureCategory::kSolver, "nonfinite-newton-data", {},
|
||||
"NONLINEAR_STATIC_PROCEDURE", std::to_string(row),
|
||||
"Nonlinear fixed and pressure tangent composition is nonfinite."));
|
||||
}
|
||||
contributions.push_back(
|
||||
{row, fixed.generalized_external_tangent.ColumnIndices()[offset],
|
||||
tangent, row, offset});
|
||||
}
|
||||
}
|
||||
Result<SparseMatrix> tangent =
|
||||
SparseMatrix::FromCoo(fixed.generalized_external_tangent.Rows(),
|
||||
fixed.generalized_external_tangent.Columns(),
|
||||
std::move(contributions), dofs.GetSparsePattern());
|
||||
if (!tangent.HasValue()) {
|
||||
return Result<GlobalFixedLoadContribution>::Failure(tangent.GetStatus());
|
||||
}
|
||||
|
||||
std::vector<Diagnostic> diagnostics = fixed.diagnostics;
|
||||
diagnostics.insert(diagnostics.end(), pressure.diagnostics.begin(),
|
||||
pressure.diagnostics.end());
|
||||
return Result<GlobalFixedLoadContribution>::Success(
|
||||
{std::move(force), std::move(tangent.Value()), std::move(diagnostics)});
|
||||
}
|
||||
|
||||
Vector SelectFreeComponents(const Vector& full, const DofManager& dofs,
|
||||
const bool rotations) {
|
||||
std::size_t count = 0U;
|
||||
@@ -670,6 +741,11 @@ NonlinearStaticProcedureExecutor::Execute(
|
||||
if (!dofs.HasValue()) {
|
||||
return Result<NonlinearStaticExecutionResult>::Failure(dofs.GetStatus());
|
||||
}
|
||||
Result<AnalysisModel> analysis_model = AnalysisModel::Create(domain);
|
||||
if (!analysis_model.HasValue()) {
|
||||
return Result<NonlinearStaticExecutionResult>::Failure(
|
||||
analysis_model.GetStatus());
|
||||
}
|
||||
Result<NonlinearStateBaselineInput> baseline = BuildBaseline(domain);
|
||||
if (!baseline.HasValue()) {
|
||||
return Result<NonlinearStaticExecutionResult>::Failure(
|
||||
@@ -732,14 +808,32 @@ NonlinearStaticProcedureExecutor::Execute(
|
||||
}
|
||||
record.last_completed_stage = NewtonIterationStage::kInternalAssembled;
|
||||
|
||||
Result<GlobalFixedLoadContribution> external =
|
||||
Result<GlobalFixedLoadContribution> fixed =
|
||||
AssembleGlobalFixedLoadContribution(
|
||||
domain, dofs.Value(), trial.Value().generalized_coordinates,
|
||||
increment.load_factor);
|
||||
if (!fixed.HasValue()) {
|
||||
return Result<NonlinearStaticExecutionResult>::Failure(
|
||||
RecordFailure(log, &record, fixed.GetStatus(),
|
||||
NewtonIterationStage::kExternalAssembled));
|
||||
}
|
||||
Result<SurfacePressureAssemblyCandidate> pressure =
|
||||
AssembleSurfacePressure(
|
||||
analysis_model.Value(), dofs.Value(),
|
||||
trial.Value().generalized_coordinates, increment.load_factor,
|
||||
SurfacePressureConfiguration::kCurrent, parallel_for_);
|
||||
if (!pressure.HasValue()) {
|
||||
return Result<NonlinearStaticExecutionResult>::Failure(
|
||||
RecordFailure(log, &record, pressure.GetStatus(),
|
||||
NewtonIterationStage::kExternalAssembled));
|
||||
}
|
||||
Result<GlobalFixedLoadContribution> external =
|
||||
CombineExternalContributions(fixed.Value(), pressure.Value(),
|
||||
dofs.Value());
|
||||
if (!external.HasValue()) {
|
||||
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
|
||||
log, &record, external.GetStatus(),
|
||||
NewtonIterationStage::kExternalAssembled));
|
||||
return Result<NonlinearStaticExecutionResult>::Failure(
|
||||
RecordFailure(log, &record, external.GetStatus(),
|
||||
NewtonIterationStage::kExternalAssembled));
|
||||
}
|
||||
record.last_completed_stage = NewtonIterationStage::kExternalAssembled;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user