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
+15 -168
View File
@@ -2,50 +2,12 @@
#include <utility>
#include "fesa/assembly/load_assembler.h"
#include "fesa/assembly/parallel_for.h"
#include "fesa/assembly/sparse_assembler.h"
#include "fesa/elements/element_factory.h"
#include "fesa/io/abaqus/domain_mapper.h"
#include "fesa/io/abaqus/input_reader.h"
#include "fesa/results/result_recovery.h"
#include "fesa/analysis/linear_static_procedure.h"
#include "fesa/analysis/prepared_analysis.h"
#include "fesa/results/results_writer.h"
#include "fesa/solvers/linear/linear_solver.h"
namespace fesa {
Status LinearStaticAnalysis::Run(const AnalysisRequest& request) {
Status status = InitializeCandidate(request);
if (!status.IsOk()) {
return status;
}
status = BuildAnalysisModel();
if (!status.IsOk()) {
return status;
}
status = BuildDofMapAndSparsePattern();
if (!status.IsOk()) {
return status;
}
status = AssembleAndPartitionStiffness();
if (!status.IsOk()) {
return status;
}
status = FactorizeFreeSystem();
if (!status.IsOk()) {
return status;
}
status = AssembleLoadsAndEffectiveRhs();
if (!status.IsOk()) {
return status;
}
status = SubstituteAndReconstruct();
if (!status.IsOk()) {
return status;
}
return RecoverAndWrite();
}
LinearStaticAnalysis::LinearStaticAnalysis(const ParallelFor& parallel_for,
LinearSolver& linear_solver,
ResultsWriter& results_writer)
@@ -53,138 +15,23 @@ LinearStaticAnalysis::LinearStaticAnalysis(const ParallelFor& parallel_for,
linear_solver_{linear_solver},
results_writer_{results_writer} {}
Status LinearStaticAnalysis::InitializeCandidate(
const AnalysisRequest& request) {
// Clear dependent objects in reverse ownership order so a reused analysis
// never exposes a view into a Domain from an earlier run.
effective_rhs_.reset();
partitioned_stiffness_.reset();
full_stiffness_.reset();
state_.reset();
dofs_.reset();
element_view_.clear();
elements_.clear();
model_.reset();
domain_.reset();
diagnostics_.clear();
request_ = request;
const auto parsed = AbaqusInputReader{}.Read(request_.input_path);
if (!parsed.HasValue()) {
return parsed.GetStatus();
}
auto domain = AbaqusDomainMapper{}.Map(parsed.Value());
if (!domain.HasValue()) {
return domain.GetStatus();
Status LinearStaticAnalysis::Run(const AnalysisRequest& request) {
Result<PreparedAnalysisInput> prepared =
PrepareAnalysisInput(request.input_path);
if (!prepared.HasValue()) {
return prepared.GetStatus();
}
domain_ = std::make_unique<Domain>(std::move(domain.Value()));
diagnostics_ = domain_->Warnings();
SortDiagnostics(diagnostics_);
return Status::Ok();
}
Status LinearStaticAnalysis::BuildAnalysisModel() {
auto model = AnalysisModel::Create(*domain_);
if (!model.HasValue()) {
return model.GetStatus();
}
model_ = std::make_unique<AnalysisModel>(std::move(model.Value()));
return Status::Ok();
}
Status LinearStaticAnalysis::BuildDofMapAndSparsePattern() {
std::vector<std::unique_ptr<Element>> elements;
ElementView element_view;
elements.reserve(model_->ActiveElements().size());
element_view.reserve(model_->ActiveElements().size());
const ElementFactory factory;
for (const EntityIndex element_index : model_->ActiveElements()) {
auto element = factory.Create(domain_->Elements()[element_index], *domain_);
if (!element.HasValue()) {
return element.GetStatus();
}
element_view.emplace_back(*element.Value());
elements.push_back(std::move(element.Value()));
LinearStaticProcedureExecutor executor(parallel_for_, linear_solver_);
Result<LinearStaticExecutionResult> execution =
executor.Execute(prepared.Value().domain);
if (!execution.HasValue()) {
return execution.GetStatus();
}
DofManager dofs;
const Status dof_status = dofs.Build(*model_, element_view);
if (!dof_status.IsOk()) {
return dof_status;
}
elements_ = std::move(elements);
element_view_ = std::move(element_view);
dofs_ = std::make_unique<DofManager>(std::move(dofs));
state_ = std::make_unique<AnalysisState>(
AnalysisState::Create(*dofs_, {"Step-1", 0U}));
return Status::Ok();
}
Status LinearStaticAnalysis::AssembleAndPartitionStiffness() {
auto stiffness =
SparseAssembler::Assemble(element_view_, *dofs_, parallel_for_);
if (!stiffness.HasValue()) {
return stiffness.GetStatus();
}
full_stiffness_ =
std::make_unique<SparseMatrix>(std::move(stiffness.Value()));
auto partitioned =
EssentialConstraintPolicy{}.Partition(*full_stiffness_, *dofs_);
if (!partitioned.HasValue()) {
return partitioned.GetStatus();
}
partitioned_stiffness_ =
std::make_unique<PartitionedStiffness>(std::move(partitioned.Value()));
return Status::Ok();
}
Status LinearStaticAnalysis::FactorizeFreeSystem() {
// This call intentionally precedes all load assembly in Run.
return linear_solver_.Factorize(partitioned_stiffness_->k_ff);
}
Status LinearStaticAnalysis::AssembleLoadsAndEffectiveRhs() {
auto full_load = LoadAssembler::AssembleFullNodalLoad(*model_, *dofs_);
if (!full_load.HasValue()) {
return full_load.GetStatus();
}
state_->ExternalForce() = std::move(full_load.Value());
auto rhs = LoadAssembler::EffectiveFreeRhs(state_->ExternalForce(),
partitioned_stiffness_->k_fc,
dofs_->PrescribedValues(), *dofs_);
if (!rhs.HasValue()) {
return rhs.GetStatus();
}
effective_rhs_ = std::make_unique<Vector>(std::move(rhs.Value()));
return Status::Ok();
}
Status LinearStaticAnalysis::SubstituteAndReconstruct() {
Vector free_displacement{dofs_->FreeDofCount()};
const Status solve_status =
linear_solver_.Solve(*effective_rhs_, free_displacement);
if (!solve_status.IsOk()) {
return solve_status;
}
state_->Displacement() = EssentialConstraintPolicy{}.ReconstructFull(
free_displacement, dofs_->PrescribedValues(), *dofs_);
return Status::Ok();
}
Status LinearStaticAnalysis::RecoverAndWrite() {
const Status recovery_status = ResultRecovery::Recover(
*model_, element_view_, *dofs_, *full_stiffness_, state_->Displacement(),
state_->ExternalForce(), *state_);
if (!recovery_status.IsOk()) {
return recovery_status;
}
return results_writer_.Write(request_.output_path, *domain_, *state_,
diagnostics_);
return results_writer_.Write(request.output_path, prepared.Value().domain,
execution.Value().state,
execution.Value().diagnostics);
}
} // namespace fesa