refactor: extract assembly analysis workflow
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/Analysis/LinearStaticAnalysis.hpp"
|
||||
#include "fesa/ModuleInfo.hpp"
|
||||
|
||||
namespace fesa::module {
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include "fesa/Assembly/Assembly.hpp"
|
||||
#include "fesa/Core/Core.hpp"
|
||||
#include "fesa/IO/IO.hpp"
|
||||
#include "fesa/Math/Math.hpp"
|
||||
#include "fesa/Results/Results.hpp"
|
||||
#include "fesa/Util/Diagnostics.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fesa {
|
||||
|
||||
struct AnalysisResult {
|
||||
AnalysisModel model;
|
||||
AnalysisState state;
|
||||
ResultFile result_file;
|
||||
std::vector<Diagnostic> diagnostics;
|
||||
|
||||
bool ok() const {
|
||||
return !hasError(diagnostics);
|
||||
}
|
||||
};
|
||||
|
||||
class Analysis {
|
||||
public:
|
||||
virtual ~Analysis() = default;
|
||||
|
||||
AnalysisResult run(const Domain& domain) const {
|
||||
AnalysisResult result;
|
||||
initialize(domain, result);
|
||||
if (hasError(result.diagnostics)) {
|
||||
return result;
|
||||
}
|
||||
solve(domain, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void initialize(const Domain& domain, AnalysisResult& result) const {
|
||||
auto diagnostics = validateDomain(domain);
|
||||
result.diagnostics.insert(result.diagnostics.end(), diagnostics.begin(), diagnostics.end());
|
||||
}
|
||||
|
||||
virtual void solve(const Domain& domain, AnalysisResult& result) const = 0;
|
||||
};
|
||||
|
||||
class LinearStaticAnalysis final : public Analysis {
|
||||
public:
|
||||
explicit LinearStaticAnalysis(const LinearSolver* solver = nullptr) : solver_(solver) {}
|
||||
|
||||
protected:
|
||||
void solve(const Domain& domain, AnalysisResult& result) const override {
|
||||
result.model = buildLinearStaticAnalysisModel(domain);
|
||||
result.diagnostics.insert(result.diagnostics.end(), result.model.diagnostics.begin(), result.model.diagnostics.end());
|
||||
if (hasError(result.diagnostics)) {
|
||||
return;
|
||||
}
|
||||
DofManager dofs(domain);
|
||||
if (dofs.freeDofCount() == 0) {
|
||||
result.diagnostics.push_back(makeDiagnostic(Severity::Error, "FESA-SINGULAR-NO-FREE-DOFS",
|
||||
"No free DOFs exist after applying constraints", "dof"));
|
||||
return;
|
||||
}
|
||||
AssemblyResult assembly = assembleSystem(domain, dofs);
|
||||
result.diagnostics.insert(result.diagnostics.end(), assembly.diagnostics.begin(), assembly.diagnostics.end());
|
||||
if (hasError(result.diagnostics)) {
|
||||
return;
|
||||
}
|
||||
const auto reduced = projectToReducedSystem(assembly, dofs);
|
||||
result.diagnostics.insert(result.diagnostics.end(), reduced.diagnostics.begin(), reduced.diagnostics.end());
|
||||
if (hasError(result.diagnostics)) {
|
||||
return;
|
||||
}
|
||||
const LinearSolver& active_solver = solver_ == nullptr ? defaultSolver() : *solver_;
|
||||
SolveResult solved = active_solver.solve(reduced.k, reduced.f);
|
||||
result.diagnostics.insert(result.diagnostics.end(), solved.diagnostics.begin(), solved.diagnostics.end());
|
||||
if (!solved.ok()) {
|
||||
return;
|
||||
}
|
||||
if (static_cast<LocalIndex>(solved.x.size()) != dofs.freeDofCount()) {
|
||||
result.diagnostics.push_back(makeDiagnostic(Severity::Error, "FESA-SOLVER-SIZE",
|
||||
"Linear solver returned a vector with the wrong size", "solver"));
|
||||
return;
|
||||
}
|
||||
result.state.u_full = dofs.reconstructFullVector(solved.x);
|
||||
result.state.f_external_full = assembly.f_full;
|
||||
result.state.f_internal_full = assembly.k_full.multiply(result.state.u_full);
|
||||
result.state.reaction_full = recoverFullReaction(assembly.k_full, result.state.u_full, result.state.f_external_full);
|
||||
result.state.converged = true;
|
||||
InMemoryResultsWriter writer;
|
||||
writer.writeLinearStatic(domain, result.model, dofs, result.state.u_full, result.state.reaction_full);
|
||||
result.result_file = writer.result();
|
||||
}
|
||||
|
||||
private:
|
||||
static const LinearSolver& defaultSolver() {
|
||||
static const GaussianEliminationSolver solver;
|
||||
return solver;
|
||||
}
|
||||
|
||||
const LinearSolver* solver_ = nullptr;
|
||||
};
|
||||
|
||||
inline AnalysisResult runLinearStaticInputString(const std::string& text,
|
||||
const std::string& source_name = "<memory>",
|
||||
const LinearSolver* solver = nullptr) {
|
||||
AbaqusInputParser parser;
|
||||
const auto parsed = parser.parseString(text, source_name);
|
||||
if (!parsed.ok()) {
|
||||
AnalysisResult result;
|
||||
result.diagnostics = parsed.diagnostics;
|
||||
return result;
|
||||
}
|
||||
LinearStaticAnalysis analysis(solver);
|
||||
return analysis.run(parsed.domain);
|
||||
}
|
||||
|
||||
} // namespace fesa
|
||||
Reference in New Issue
Block a user