feat(shell-surface-pressure-load): step 4 - integrate-linear-shell-pressure

This commit is contained in:
KOKO\Mimi
2026-09-01 15:03:28 +09:00
parent 6630cb1006
commit 4b6d023680
9 changed files with 1017 additions and 4 deletions
+65 -4
View File
@@ -1,6 +1,8 @@
#include "fesa/analysis/linear_static_procedure.h"
#include <cmath>
#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -8,6 +10,7 @@
#include "fesa/assembly/load_assembler.h"
#include "fesa/assembly/parallel_for.h"
#include "fesa/assembly/sparse_assembler.h"
#include "fesa/assembly/surface_pressure_assembler.h"
#include "fesa/constraints/essential_constraint_policy.h"
#include "fesa/elements/element.h"
#include "fesa/elements/element_factory.h"
@@ -67,12 +70,67 @@ Result<LinearStaticExecutionResult> LinearStaticProcedureExecutor::Execute(
return Result<LinearStaticExecutionResult>::Failure(factorized);
}
Result<Vector> external =
Result<Vector> nodal_external =
LoadAssembler::AssembleFullNodalLoad(model.Value(), dofs);
if (!external.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(external.GetStatus());
if (!nodal_external.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(
nodal_external.GetStatus());
}
state.ExternalForce() = std::move(external.Value());
Vector reference_coordinates{dofs.FullDofCount()};
Result<SurfacePressureAssemblyCandidate> pressure_external =
AssembleSurfacePressure(model.Value(), dofs, reference_coordinates, 1.0,
SurfacePressureConfiguration::kReference,
parallel_for_);
if (!pressure_external.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(
pressure_external.GetStatus());
}
if (pressure_external.Value().full_external_force.Size() !=
nodal_external.Value().Size() ||
pressure_external.Value().full_external_tangent.Rows() !=
dofs.FullDofCount() ||
pressure_external.Value().full_external_tangent.Columns() !=
dofs.FullDofCount()) {
return Result<LinearStaticExecutionResult>::Failure(Status::Failure(
FailureCategory::kModel,
{{Severity::kError,
"invalid-pressure-dimensions",
{domain.SourcePath(), 0U},
"DSLOAD",
domain.SourceContentIdentity(),
"Pressure assembly must return the stable full-DOF dimensions."}}));
}
for (const double value :
pressure_external.Value().full_external_tangent.Values()) {
if (value != 0.0) {
return Result<LinearStaticExecutionResult>::Failure(Status::Failure(
FailureCategory::kModel,
{{Severity::kError,
"nonzero-linear-pressure-tangent",
{domain.SourcePath(), 0U},
"DSLOAD",
domain.SourceContentIdentity(),
"Reference-configuration linear pressure requires zero "
"tangent."}}));
}
}
for (std::size_t index = 0U; index < nodal_external.Value().Size(); ++index) {
const double combined =
nodal_external.Value()[index] +
pressure_external.Value().full_external_force[index];
if (!std::isfinite(combined)) {
return Result<LinearStaticExecutionResult>::Failure(Status::Failure(
FailureCategory::kSolver,
{{Severity::kError,
"nonfinite-load-accumulation",
{domain.SourcePath(), 0U},
"DSLOAD",
std::to_string(index),
"Nodal and surface pressure load accumulation is nonfinite."}}));
}
nodal_external.Value()[index] = combined;
}
state.ExternalForce() = std::move(nodal_external.Value());
Result<Vector> rhs = LoadAssembler::EffectiveFreeRhs(
state.ExternalForce(), partitions.Value().k_fc, dofs.PrescribedValues(),
@@ -97,6 +155,9 @@ Result<LinearStaticExecutionResult> LinearStaticProcedureExecutor::Execute(
}
std::vector<Diagnostic> diagnostics = domain.Warnings();
diagnostics.insert(diagnostics.end(),
pressure_external.Value().diagnostics.begin(),
pressure_external.Value().diagnostics.end());
SortDiagnostics(diagnostics);
return Result<LinearStaticExecutionResult>::Success(
{std::move(state), std::move(diagnostics)});