Files
FESADev/src/fesa/analysis/prepared_analysis.cpp
T

253 lines
11 KiB
C++

#include "fesa/analysis/prepared_analysis.h"
#include <utility>
#include "fesa/analysis/analysis_model.h"
#include "fesa/analysis/hht_dynamic_procedure.h"
#include "fesa/analysis/linear_frequency_procedure.h"
#include "fesa/analysis/linear_static_procedure.h"
#include "fesa/analysis/newton_iteration_log.h"
#include "fesa/analysis/nonlinear_static_procedure.h"
#include "fesa/analysis/solid_frequency_procedure.h"
#include "fesa/app/output_paths.h"
#include "fesa/io/abaqus/domain_mapper.h"
#include "fesa/io/abaqus/input_reader.h"
#include "fesa/results/dynamic_results_writer.h"
#include "fesa/results/eigen_results_writer.h"
#include "fesa/results/nonlinear_results_writer.h"
#include "fesa/results/results_writer.h"
#include "fesa/results/solid_results_writer.h"
#include "fesa/results/thermal_results_writer.h"
namespace fesa {
Result<PreparedAnalysisInput> PrepareAnalysisInput(
const std::filesystem::path& input_path) {
const Result<ParsedInput> syntax = AbaqusInputReader{}.Read(input_path);
if (!syntax.HasValue()) {
return Result<PreparedAnalysisInput>::Failure(syntax.GetStatus());
}
Result<Domain> mapped = AbaqusDomainMapper{}.Map(syntax.Value());
if (!mapped.HasValue()) {
return Result<PreparedAnalysisInput>::Failure(mapped.GetStatus());
}
PreparedAnalysisInput prepared{std::move(mapped.Value()), {}};
prepared.diagnostics = prepared.domain.Warnings();
SortDiagnostics(prepared.diagnostics);
return Result<PreparedAnalysisInput>::Success(std::move(prepared));
}
Result<PreparedAnalysisOutcome> ExecutePreparedAnalysis(
const Domain& domain, LinearStaticProcedureExecutor& linear_executor,
NonlinearStaticProcedureExecutor& nonlinear_executor,
const LinearFrequencyProcedureExecutor& frequency_executor,
NewtonIterationLogWriter& log,
const HhtDynamicProcedureExecutor* dynamic_executor,
const TransientHeatProcedureExecutor* thermal_executor,
const SolidStaticProcedureExecutor* solid_static_executor,
const SolidFrequencyProcedureExecutor* solid_frequency_executor,
const SolidHhtDynamicProcedureExecutor* solid_dynamic_executor) {
if (domain.ThermalStep() != nullptr) {
if (thermal_executor == nullptr) {
return Result<PreparedAnalysisOutcome>::Failure(
Status::Failure(FailureCategory::kSolver,
{{Severity::kError,
"missing-thermal-executor",
{},
"HEAT TRANSFER",
{},
"Thermal execution adapter is required."}}));
}
auto thermal = thermal_executor->Execute(domain);
if (!thermal.HasValue()) {
return Result<PreparedAnalysisOutcome>::Failure(thermal.GetStatus());
}
return Result<PreparedAnalysisOutcome>::Success(
PreparedAnalysisOutcome{std::move(thermal.Value())});
}
if (domain.Steps().Size() != 1U) {
return Result<PreparedAnalysisOutcome>::Failure(Status::Failure(
FailureCategory::kInput,
{{Severity::kError,
"invalid-analysis-step-count",
{},
"*STEP",
{},
"Prepared analysis requires exactly one analysis step."}}));
}
if (domain.IsSolid()) {
const auto missing = []() {
return Result<PreparedAnalysisOutcome>::Failure(Status::Failure(
FailureCategory::kSolver,
{{Severity::kError,
"missing-solid-executor",
{},
"",
{},
"The selected Solid execution adapter is required."}}));
};
if (domain.Dynamic() != nullptr) {
if (solid_dynamic_executor == nullptr) return missing();
auto model = AnalysisModel::Create(domain);
if (!model.HasValue())
return Result<PreparedAnalysisOutcome>::Failure(model.GetStatus());
auto dofs = DofManager::Create(model.Value());
if (!dofs.HasValue())
return Result<PreparedAnalysisOutcome>::Failure(dofs.GetStatus());
auto state = SolidDynamicAnalysisState::Create(domain, dofs.Value());
if (!state.HasValue())
return Result<PreparedAnalysisOutcome>::Failure(state.GetStatus());
const Status execution =
solid_dynamic_executor->ExecuteInto(domain, state.Value());
for (const auto& record : state.Value().IterationRecords()) {
const Status written = log.Write(record);
if (!written.IsOk())
return Result<PreparedAnalysisOutcome>::Failure(written);
}
if (!execution.IsOk())
return Result<PreparedAnalysisOutcome>::Failure(execution);
return Result<PreparedAnalysisOutcome>::Success(
PreparedAnalysisOutcome{SolidDynamicExecutionResult{
std::move(dofs.Value()), std::move(state.Value())}});
}
if (domain.Steps()[0U].IsFrequency()) {
if (solid_frequency_executor == nullptr) return missing();
auto result = solid_frequency_executor->Execute(domain);
if (!result.HasValue())
return Result<PreparedAnalysisOutcome>::Failure(result.GetStatus());
return Result<PreparedAnalysisOutcome>::Success(
PreparedAnalysisOutcome{std::move(result.Value())});
}
if (solid_static_executor == nullptr) return missing();
SolidStaticState state;
const Status execution = solid_static_executor->ExecuteInto(domain, state);
for (const auto& record : state.IterationRecords()) {
const Status written = log.Write(record, domain.Steps()[0U].Name());
if (!written.IsOk())
return Result<PreparedAnalysisOutcome>::Failure(written);
}
if (!execution.IsOk())
return Result<PreparedAnalysisOutcome>::Failure(execution);
return Result<PreparedAnalysisOutcome>::Success(PreparedAnalysisOutcome{
SolidStaticExecutionResult{std::move(state), domain.Warnings()}});
}
if (domain.Dynamic() != nullptr) {
if (dynamic_executor == nullptr)
return Result<PreparedAnalysisOutcome>::Failure(
Status::Failure(FailureCategory::kSolver,
{{Severity::kError,
"missing-dynamic-executor",
{},
"DYNAMIC",
{},
"Dynamic execution adapter is required."}}));
auto dynamic = dynamic_executor->Execute(domain, log);
if (!dynamic.HasValue())
return Result<PreparedAnalysisOutcome>::Failure(dynamic.GetStatus());
return Result<PreparedAnalysisOutcome>::Success(
PreparedAnalysisOutcome{std::move(dynamic.Value())});
}
if (domain.Steps()[0U].IsFrequency()) {
auto eigen = frequency_executor.Execute(domain);
if (!eigen.HasValue()) {
return Result<PreparedAnalysisOutcome>::Failure(eigen.GetStatus());
}
return Result<PreparedAnalysisOutcome>::Success(
PreparedAnalysisOutcome{std::move(eigen.Value())});
}
if (domain.Steps()[0U].IsNonlinearStatic()) {
Result<NonlinearStaticExecutionResult> nonlinear =
nonlinear_executor.Execute(domain, log);
if (!nonlinear.HasValue()) {
return Result<PreparedAnalysisOutcome>::Failure(nonlinear.GetStatus());
}
return Result<PreparedAnalysisOutcome>::Success(
PreparedAnalysisOutcome{std::move(nonlinear.Value())});
}
Result<LinearStaticExecutionResult> linear = linear_executor.Execute(domain);
if (!linear.HasValue()) {
return Result<PreparedAnalysisOutcome>::Failure(linear.GetStatus());
}
return Result<PreparedAnalysisOutcome>::Success(
PreparedAnalysisOutcome{std::move(linear.Value())});
}
Status FinalizePreparedAnalysisResult(
const DerivedOutputPaths& paths, const Domain& domain,
const PreparedAnalysisOutcome& outcome,
const std::vector<Diagnostic>& diagnostics, ResultsWriter& linear_writer,
NonlinearResultsWriter& nonlinear_writer, EigenResultsWriter& eigen_writer,
DynamicResultsWriter* dynamic_writer, ThermalResultsWriter* thermal_writer,
SolidResultsWriter* solid_writer) {
if (std::holds_alternative<SolidStaticExecutionResult>(outcome) ||
std::holds_alternative<SolidFrequencyState>(outcome) ||
std::holds_alternative<SolidDynamicExecutionResult>(outcome)) {
if (solid_writer == nullptr)
return Status::Failure(FailureCategory::kOutput,
{{Severity::kError,
"missing-solid-writer",
{},
"",
{},
"Solid result writer is required."}});
if (const auto* result = std::get_if<SolidStaticExecutionResult>(&outcome))
return solid_writer->Write(paths.results_path, domain, result->state,
diagnostics);
if (const auto* result = std::get_if<SolidFrequencyState>(&outcome))
return solid_writer->Write(paths.results_path, domain, *result,
diagnostics);
return solid_writer->Write(
paths.results_path, domain,
std::get<SolidDynamicExecutionResult>(outcome).state, diagnostics);
}
if (std::holds_alternative<ThermalExecutionResult>(outcome)) {
if (thermal_writer == nullptr) {
return Status::Failure(FailureCategory::kOutput,
{{Severity::kError,
"missing-thermal-writer",
{},
"HEAT TRANSFER",
{},
"Thermal result writer is required."}});
}
return thermal_writer->Write(
paths.results_path, domain,
std::get<ThermalExecutionResult>(outcome).state, diagnostics);
}
if (std::holds_alternative<DynamicExecutionResult>(outcome)) {
if (dynamic_writer == nullptr)
return Status::Failure(FailureCategory::kOutput,
{{Severity::kError,
"missing-dynamic-writer",
{},
"DYNAMIC",
{},
"Dynamic result writer is required."}});
return dynamic_writer->Write(
paths.results_path, domain,
std::get<DynamicExecutionResult>(outcome).state, diagnostics);
}
if (std::holds_alternative<EigenAnalysisState>(outcome)) {
return eigen_writer.Write(paths.results_path, domain,
std::get<EigenAnalysisState>(outcome),
diagnostics);
}
if (std::holds_alternative<LinearStaticExecutionResult>(outcome)) {
return linear_writer.Write(
paths.results_path, domain,
std::get<LinearStaticExecutionResult>(outcome).state, diagnostics);
}
return nonlinear_writer.Write(
paths.results_path, domain,
std::get<NonlinearStaticExecutionResult>(outcome).state, diagnostics);
}
} // namespace fesa