feat(cpp-object-oriented-modular-refactoring): step 5 - solver-workflow-google-style
This commit is contained in:
@@ -1,170 +1,166 @@
|
||||
#include "fesa/analysis/linear_static_analysis.hpp"
|
||||
|
||||
#include "fesa/assembly/load_assembler.hpp"
|
||||
#include "fesa/assembly/parallel_for.hpp"
|
||||
#include "fesa/assembly/sparse_assembler.hpp"
|
||||
#include "fesa/io/abaqus/domain_mapper.hpp"
|
||||
#include "fesa/io/abaqus/input_reader.hpp"
|
||||
#include "fesa/results/result_recovery.hpp"
|
||||
#include "fesa/results/results_writer.hpp"
|
||||
#include "fesa/solvers/linear/linear_solver.h"
|
||||
#include "fesa/analysis/linear_static_analysis.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "fesa/assembly/load_assembler.h"
|
||||
#include "fesa/assembly/parallel_for.h"
|
||||
#include "fesa/assembly/sparse_assembler.h"
|
||||
#include "fesa/io/abaqus/domain_mapper.hpp"
|
||||
#include "fesa/io/abaqus/input_reader.hpp"
|
||||
#include "fesa/results/result_recovery.h"
|
||||
#include "fesa/results/results_writer.h"
|
||||
#include "fesa/solvers/linear/linear_solver.h"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
Status Analysis::run(const AnalysisRequest& request) {
|
||||
Status status = initialize(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 = factorize();
|
||||
if (!status.IsOk()) {
|
||||
return status;
|
||||
}
|
||||
status = assembleLoadsAndEffectiveRhs();
|
||||
if (!status.IsOk()) {
|
||||
return status;
|
||||
}
|
||||
status = substituteAndReconstruct();
|
||||
if (!status.IsOk()) {
|
||||
return status;
|
||||
}
|
||||
return recoverAndWriteResults();
|
||||
Status Analysis::Run(const AnalysisRequest& request) {
|
||||
Status status = Initialize(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 = Factorize();
|
||||
if (!status.IsOk()) {
|
||||
return status;
|
||||
}
|
||||
status = AssembleLoadsAndEffectiveRhs();
|
||||
if (!status.IsOk()) {
|
||||
return status;
|
||||
}
|
||||
status = SubstituteAndReconstruct();
|
||||
if (!status.IsOk()) {
|
||||
return status;
|
||||
}
|
||||
return RecoverAndWriteResults();
|
||||
}
|
||||
|
||||
LinearStaticAnalysis::LinearStaticAnalysis(
|
||||
const ParallelFor& parallelFor,
|
||||
LinearSolver& linearSolver,
|
||||
ResultsWriter& resultsWriter)
|
||||
: parallelFor_{parallelFor},
|
||||
linearSolver_{linearSolver},
|
||||
resultsWriter_{resultsWriter} {}
|
||||
LinearStaticAnalysis::LinearStaticAnalysis(const ParallelFor& parallel_for,
|
||||
LinearSolver& linear_solver,
|
||||
ResultsWriter& results_writer)
|
||||
: parallel_for_{parallel_for},
|
||||
linear_solver_{linear_solver},
|
||||
results_writer_{results_writer} {}
|
||||
|
||||
Status LinearStaticAnalysis::initialize(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.
|
||||
effectiveRhs_.reset();
|
||||
partitionedStiffness_.reset();
|
||||
fullStiffness_.reset();
|
||||
state_.reset();
|
||||
dofs_.reset();
|
||||
model_.reset();
|
||||
domain_.reset();
|
||||
diagnostics_.clear();
|
||||
request_ = request;
|
||||
Status LinearStaticAnalysis::Initialize(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();
|
||||
model_.reset();
|
||||
domain_.reset();
|
||||
diagnostics_.clear();
|
||||
request_ = request;
|
||||
|
||||
const auto parsed = AbaqusInputReader{}.read(request_.inputPath);
|
||||
if (!parsed.HasValue()) {
|
||||
return parsed.GetStatus();
|
||||
}
|
||||
auto domain = AbaqusDomainMapper{}.map(parsed.Value());
|
||||
if (!domain.HasValue()) {
|
||||
return domain.GetStatus();
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
domain_ = std::make_unique<Domain>(std::move(domain.Value()));
|
||||
diagnostics_ = domain_->Warnings();
|
||||
SortDiagnostics(diagnostics_);
|
||||
return Status::Ok();
|
||||
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::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() {
|
||||
auto dofs = DofManager::create(*model_);
|
||||
if (!dofs.HasValue()) {
|
||||
return dofs.GetStatus();
|
||||
}
|
||||
dofs_ = std::make_unique<DofManager>(std::move(dofs.Value()));
|
||||
state_ = std::make_unique<AnalysisState>(
|
||||
AnalysisState::create(*dofs_, {"Step-1", 0U}));
|
||||
return Status::Ok();
|
||||
Status LinearStaticAnalysis::BuildDofMapAndSparsePattern() {
|
||||
auto dofs = DofManager::Create(*model_);
|
||||
if (!dofs.HasValue()) {
|
||||
return dofs.GetStatus();
|
||||
}
|
||||
dofs_ = std::make_unique<DofManager>(std::move(dofs.Value()));
|
||||
state_ = std::make_unique<AnalysisState>(
|
||||
AnalysisState::Create(*dofs_, {"Step-1", 0U}));
|
||||
return Status::Ok();
|
||||
}
|
||||
|
||||
Status LinearStaticAnalysis::assembleAndPartitionStiffness() {
|
||||
auto stiffness = SparseAssembler::assembleStiffness(
|
||||
*model_, *dofs_, parallelFor_);
|
||||
if (!stiffness.HasValue()) {
|
||||
return stiffness.GetStatus();
|
||||
}
|
||||
fullStiffness_ =
|
||||
std::make_unique<SparseMatrix>(std::move(stiffness.Value()));
|
||||
Status LinearStaticAnalysis::AssembleAndPartitionStiffness() {
|
||||
auto stiffness =
|
||||
SparseAssembler::AssembleStiffness(*model_, *dofs_, parallel_for_);
|
||||
if (!stiffness.HasValue()) {
|
||||
return stiffness.GetStatus();
|
||||
}
|
||||
full_stiffness_ =
|
||||
std::make_unique<SparseMatrix>(std::move(stiffness.Value()));
|
||||
|
||||
auto partitioned = EssentialConstraints::partition(
|
||||
*fullStiffness_, *dofs_);
|
||||
if (!partitioned.HasValue()) {
|
||||
return partitioned.GetStatus();
|
||||
}
|
||||
partitionedStiffness_ = std::make_unique<PartitionedStiffness>(
|
||||
std::move(partitioned.Value()));
|
||||
return Status::Ok();
|
||||
auto partitioned = EssentialConstraints::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::factorize() {
|
||||
// This call intentionally precedes all load assembly in Analysis::run.
|
||||
return linearSolver_.Factorize(partitionedStiffness_->kff);
|
||||
Status LinearStaticAnalysis::Factorize() {
|
||||
// This call intentionally precedes all load assembly in Analysis::Run.
|
||||
return linear_solver_.Factorize(partitioned_stiffness_->kff);
|
||||
}
|
||||
|
||||
Status LinearStaticAnalysis::assembleLoadsAndEffectiveRhs() {
|
||||
auto fullLoad = LoadAssembler::assembleFullNodalLoad(*model_, *dofs_);
|
||||
if (!fullLoad.HasValue()) {
|
||||
return fullLoad.GetStatus();
|
||||
}
|
||||
state_->externalForce() = std::move(fullLoad.Value());
|
||||
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(),
|
||||
partitionedStiffness_->kfc,
|
||||
dofs_->prescribedValues(),
|
||||
*dofs_);
|
||||
if (!rhs.HasValue()) {
|
||||
return rhs.GetStatus();
|
||||
}
|
||||
effectiveRhs_ = std::make_unique<Vector>(std::move(rhs.Value()));
|
||||
return Status::Ok();
|
||||
auto rhs = LoadAssembler::EffectiveFreeRhs(state_->ExternalForce(),
|
||||
partitioned_stiffness_->kfc,
|
||||
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 freeDisplacement{dofs_->freeDofCount()};
|
||||
const Status solveStatus =
|
||||
linearSolver_.Solve(*effectiveRhs_, freeDisplacement);
|
||||
if (!solveStatus.IsOk()) {
|
||||
return solveStatus;
|
||||
}
|
||||
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() = EssentialConstraints::reconstructFull(
|
||||
freeDisplacement, dofs_->prescribedValues(), *dofs_);
|
||||
return Status::Ok();
|
||||
state_->Displacement() = EssentialConstraints::ReconstructFull(
|
||||
free_displacement, dofs_->PrescribedValues(), *dofs_);
|
||||
return Status::Ok();
|
||||
}
|
||||
|
||||
Status LinearStaticAnalysis::recoverAndWriteResults() {
|
||||
const Status recoveryStatus = ResultRecovery::recover(
|
||||
*model_, *dofs_, *fullStiffness_, *state_);
|
||||
if (!recoveryStatus.IsOk()) {
|
||||
return recoveryStatus;
|
||||
}
|
||||
return resultsWriter_.write(
|
||||
request_.outputPath, *domain_, *state_, diagnostics_);
|
||||
Status LinearStaticAnalysis::RecoverAndWriteResults() {
|
||||
const Status recovery_status =
|
||||
ResultRecovery::Recover(*model_, *dofs_, *full_stiffness_, *state_);
|
||||
if (!recovery_status.IsOk()) {
|
||||
return recovery_status;
|
||||
}
|
||||
return results_writer_.Write(request_.output_path, *domain_, *state_,
|
||||
diagnostics_);
|
||||
}
|
||||
|
||||
} // namespace fesa
|
||||
} // namespace fesa
|
||||
|
||||
Reference in New Issue
Block a user