feat(cpp-object-oriented-modular-refactoring): step 20 - analysis-hierarchy

This commit is contained in:
KOKO\Mimi
2026-08-16 11:33:08 +09:00
parent 95c186b812
commit be35d00f49
8 changed files with 214 additions and 148 deletions
+38 -15
View File
@@ -5,6 +5,7 @@
#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"
@@ -13,8 +14,8 @@
namespace fesa {
Status Analysis::Run(const AnalysisRequest& request) {
Status status = Initialize(request);
Status LinearStaticAnalysis::Run(const AnalysisRequest& request) {
Status status = InitializeCandidate(request);
if (!status.IsOk()) {
return status;
}
@@ -30,7 +31,7 @@ Status Analysis::Run(const AnalysisRequest& request) {
if (!status.IsOk()) {
return status;
}
status = Factorize();
status = FactorizeFreeSystem();
if (!status.IsOk()) {
return status;
}
@@ -42,7 +43,7 @@ Status Analysis::Run(const AnalysisRequest& request) {
if (!status.IsOk()) {
return status;
}
return RecoverAndWriteResults();
return RecoverAndWrite();
}
LinearStaticAnalysis::LinearStaticAnalysis(const ParallelFor& parallel_for,
@@ -52,7 +53,8 @@ LinearStaticAnalysis::LinearStaticAnalysis(const ParallelFor& parallel_for,
linear_solver_{linear_solver},
results_writer_{results_writer} {}
Status LinearStaticAnalysis::Initialize(const AnalysisRequest& request) {
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();
@@ -60,6 +62,8 @@ Status LinearStaticAnalysis::Initialize(const AnalysisRequest& request) {
full_stiffness_.reset();
state_.reset();
dofs_.reset();
element_view_.clear();
elements_.clear();
model_.reset();
domain_.reset();
diagnostics_.clear();
@@ -90,11 +94,29 @@ Status LinearStaticAnalysis::BuildAnalysisModel() {
}
Status LinearStaticAnalysis::BuildDofMapAndSparsePattern() {
auto dofs = DofManager::Create(*model_);
if (!dofs.HasValue()) {
return dofs.GetStatus();
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()));
}
dofs_ = std::make_unique<DofManager>(std::move(dofs.Value()));
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();
@@ -102,7 +124,7 @@ Status LinearStaticAnalysis::BuildDofMapAndSparsePattern() {
Status LinearStaticAnalysis::AssembleAndPartitionStiffness() {
auto stiffness =
SparseAssembler::AssembleStiffness(*model_, *dofs_, parallel_for_);
SparseAssembler::Assemble(element_view_, *dofs_, parallel_for_);
if (!stiffness.HasValue()) {
return stiffness.GetStatus();
}
@@ -119,8 +141,8 @@ Status LinearStaticAnalysis::AssembleAndPartitionStiffness() {
return Status::Ok();
}
Status LinearStaticAnalysis::Factorize() {
// This call intentionally precedes all load assembly in Analysis::Run.
Status LinearStaticAnalysis::FactorizeFreeSystem() {
// This call intentionally precedes all load assembly in Run.
return linear_solver_.Factorize(partitioned_stiffness_->k_ff);
}
@@ -154,9 +176,10 @@ Status LinearStaticAnalysis::SubstituteAndReconstruct() {
return Status::Ok();
}
Status LinearStaticAnalysis::RecoverAndWriteResults() {
const Status recovery_status =
ResultRecovery::Recover(*model_, *dofs_, *full_stiffness_, *state_);
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;
}
+5 -2
View File
@@ -2,9 +2,11 @@
#include <filesystem>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "fesa/analysis/analysis.h"
#include "fesa/analysis/linear_static_analysis.h"
#include "fesa/assembly/parallel_for.h"
#include "fesa/core/diagnostic.h"
@@ -91,8 +93,9 @@ int FesaApplication::Run(const std::vector<std::string>& arguments) {
TbbParallelFor parallel_for;
MklPardisoSolver linear_solver;
Hdf5ResultsWriter results_writer;
LinearStaticAnalysis analysis{parallel_for, linear_solver, results_writer};
const Status status = analysis.Run(request);
std::unique_ptr<Analysis> analysis = std::make_unique<LinearStaticAnalysis>(
parallel_for, linear_solver, results_writer);
const Status status = analysis->Run(request);
if (status.IsOk()) {
return kSuccessExitCode;
}
@@ -57,13 +57,6 @@ Result<SparseMatrix> ExtractBlock(const SparseMatrix& full,
std::move(contributions), pattern);
}
void RequireDofOrder(const DofManager& dof_manager) {
if (!dof_manager.ValidateInvariants().IsOk()) {
throw std::invalid_argument{
"DofManager constraint dimensions or order are invalid."};
}
}
} // namespace
Result<PartitionedStiffness> EssentialConstraintPolicy::Partition(
@@ -114,7 +107,6 @@ Result<PartitionedStiffness> EssentialConstraintPolicy::Partition(
Vector EssentialConstraintPolicy::GatherFree(
const Vector& full_values, const DofManager& dof_manager) const {
RequireDofOrder(dof_manager);
if (full_values.Size() != dof_manager.FullDofCount()) {
throw std::invalid_argument{
"Full vector size must match the DofManager full dimension."};
@@ -129,7 +121,6 @@ Vector EssentialConstraintPolicy::GatherFree(
Vector EssentialConstraintPolicy::GatherConstrained(
const Vector& full_values, const DofManager& dof_manager) const {
RequireDofOrder(dof_manager);
if (full_values.Size() != dof_manager.FullDofCount()) {
throw std::invalid_argument{
"Full vector size must match the DofManager full dimension."};
@@ -145,7 +136,6 @@ Vector EssentialConstraintPolicy::GatherConstrained(
Vector EssentialConstraintPolicy::ReconstructFull(
const Vector& free_values, const Vector& constrained_values,
const DofManager& dof_manager) const {
RequireDofOrder(dof_manager);
if (free_values.Size() != dof_manager.FreeDofCount() ||
constrained_values.Size() != dof_manager.ConstrainedDofCount()) {
throw std::invalid_argument{