feat(nonlinear-static-newton-raphson): step 10 - prepared-analysis-flow-and-full-procedure

This commit is contained in:
KOKO\Mimi
2026-08-24 15:49:08 +09:00
parent 3a443e08af
commit f0f38b9803
16 changed files with 1373 additions and 223 deletions
@@ -0,0 +1,105 @@
#include "fesa/analysis/linear_static_procedure.h"
#include <memory>
#include <utility>
#include <vector>
#include "fesa/analysis/analysis_model.h"
#include "fesa/assembly/load_assembler.h"
#include "fesa/assembly/parallel_for.h"
#include "fesa/assembly/sparse_assembler.h"
#include "fesa/constraints/essential_constraint_policy.h"
#include "fesa/elements/element.h"
#include "fesa/elements/element_factory.h"
#include "fesa/fem/dof_manager.h"
#include "fesa/results/result_recovery.h"
#include "fesa/solvers/linear/linear_solver.h"
namespace fesa {
LinearStaticProcedureExecutor::LinearStaticProcedureExecutor(
const ParallelFor& parallel_for, LinearSolver& linear_solver)
: parallel_for_(parallel_for), linear_solver_(linear_solver) {}
Result<LinearStaticExecutionResult> LinearStaticProcedureExecutor::Execute(
const Domain& domain) const {
Result<AnalysisModel> model = AnalysisModel::Create(domain);
if (!model.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(model.GetStatus());
}
std::vector<std::unique_ptr<Element>> elements;
ElementView element_view;
elements.reserve(model.Value().ActiveElements().size());
element_view.reserve(model.Value().ActiveElements().size());
const ElementFactory factory;
for (const EntityIndex element_index : model.Value().ActiveElements()) {
Result<std::unique_ptr<Element>> element =
factory.Create(domain.Elements()[element_index], domain);
if (!element.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(element.GetStatus());
}
element_view.emplace_back(*element.Value());
elements.push_back(std::move(element.Value()));
}
DofManager dofs;
const Status dof_status = dofs.Build(model.Value(), element_view);
if (!dof_status.IsOk()) {
return Result<LinearStaticExecutionResult>::Failure(dof_status);
}
AnalysisState state = AnalysisState::Create(dofs, {"Step-1", 0U});
Result<SparseMatrix> stiffness =
SparseAssembler::Assemble(element_view, dofs, parallel_for_);
if (!stiffness.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(stiffness.GetStatus());
}
Result<PartitionedStiffness> partitions =
EssentialConstraintPolicy{}.Partition(stiffness.Value(), dofs);
if (!partitions.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(partitions.GetStatus());
}
const Status factorized = linear_solver_.Factorize(partitions.Value().k_ff);
if (!factorized.IsOk()) {
return Result<LinearStaticExecutionResult>::Failure(factorized);
}
Result<Vector> external =
LoadAssembler::AssembleFullNodalLoad(model.Value(), dofs);
if (!external.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(external.GetStatus());
}
state.ExternalForce() = std::move(external.Value());
Result<Vector> rhs = LoadAssembler::EffectiveFreeRhs(
state.ExternalForce(), partitions.Value().k_fc, dofs.PrescribedValues(),
dofs);
if (!rhs.HasValue()) {
return Result<LinearStaticExecutionResult>::Failure(rhs.GetStatus());
}
Vector free_displacement{dofs.FreeDofCount()};
const Status solved = linear_solver_.Solve(rhs.Value(), free_displacement);
if (!solved.IsOk()) {
return Result<LinearStaticExecutionResult>::Failure(solved);
}
state.Displacement() = EssentialConstraintPolicy{}.ReconstructFull(
free_displacement, dofs.PrescribedValues(), dofs);
const Status recovered = ResultRecovery::Recover(
model.Value(), element_view, dofs, stiffness.Value(),
state.Displacement(), state.ExternalForce(), state);
if (!recovered.IsOk()) {
return Result<LinearStaticExecutionResult>::Failure(recovered);
}
std::vector<Diagnostic> diagnostics = domain.Warnings();
SortDiagnostics(diagnostics);
return Result<LinearStaticExecutionResult>::Success(
{std::move(state), std::move(diagnostics)});
}
} // namespace fesa