#include "fesa/analysis/prepared_analysis.h" #include #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 PrepareAnalysisInput( const std::filesystem::path& input_path) { const Result syntax = AbaqusInputReader{}.Read(input_path); if (!syntax.HasValue()) { return Result::Failure(syntax.GetStatus()); } Result mapped = AbaqusDomainMapper{}.Map(syntax.Value()); if (!mapped.HasValue()) { return Result::Failure(mapped.GetStatus()); } PreparedAnalysisInput prepared{std::move(mapped.Value()), {}}; prepared.diagnostics = prepared.domain.Warnings(); SortDiagnostics(prepared.diagnostics); return Result::Success(std::move(prepared)); } Result 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::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::Failure(thermal.GetStatus()); } return Result::Success( PreparedAnalysisOutcome{std::move(thermal.Value())}); } if (domain.Steps().Size() != 1U) { return Result::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::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::Failure(model.GetStatus()); auto dofs = DofManager::Create(model.Value()); if (!dofs.HasValue()) return Result::Failure(dofs.GetStatus()); auto state = SolidDynamicAnalysisState::Create(domain, dofs.Value()); if (!state.HasValue()) return Result::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::Failure(written); } if (!execution.IsOk()) return Result::Failure(execution); return Result::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::Failure(result.GetStatus()); return Result::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::Failure(written); } if (!execution.IsOk()) return Result::Failure(execution); return Result::Success(PreparedAnalysisOutcome{ SolidStaticExecutionResult{std::move(state), domain.Warnings()}}); } if (domain.Dynamic() != nullptr) { if (dynamic_executor == nullptr) return Result::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::Failure(dynamic.GetStatus()); return Result::Success( PreparedAnalysisOutcome{std::move(dynamic.Value())}); } if (domain.Steps()[0U].IsFrequency()) { auto eigen = frequency_executor.Execute(domain); if (!eigen.HasValue()) { return Result::Failure(eigen.GetStatus()); } return Result::Success( PreparedAnalysisOutcome{std::move(eigen.Value())}); } if (domain.Steps()[0U].IsNonlinearStatic()) { Result nonlinear = nonlinear_executor.Execute(domain, log); if (!nonlinear.HasValue()) { return Result::Failure(nonlinear.GetStatus()); } return Result::Success( PreparedAnalysisOutcome{std::move(nonlinear.Value())}); } Result linear = linear_executor.Execute(domain); if (!linear.HasValue()) { return Result::Failure(linear.GetStatus()); } return Result::Success( PreparedAnalysisOutcome{std::move(linear.Value())}); } Status FinalizePreparedAnalysisResult( const DerivedOutputPaths& paths, const Domain& domain, const PreparedAnalysisOutcome& outcome, const std::vector& diagnostics, ResultsWriter& linear_writer, NonlinearResultsWriter& nonlinear_writer, EigenResultsWriter& eigen_writer, DynamicResultsWriter* dynamic_writer, ThermalResultsWriter* thermal_writer, SolidResultsWriter* solid_writer) { if (std::holds_alternative(outcome) || std::holds_alternative(outcome) || std::holds_alternative(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(&outcome)) return solid_writer->Write(paths.results_path, domain, result->state, diagnostics); if (const auto* result = std::get_if(&outcome)) return solid_writer->Write(paths.results_path, domain, *result, diagnostics); return solid_writer->Write( paths.results_path, domain, std::get(outcome).state, diagnostics); } if (std::holds_alternative(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(outcome).state, diagnostics); } if (std::holds_alternative(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(outcome).state, diagnostics); } if (std::holds_alternative(outcome)) { return eigen_writer.Write(paths.results_path, domain, std::get(outcome), diagnostics); } if (std::holds_alternative(outcome)) { return linear_writer.Write( paths.results_path, domain, std::get(outcome).state, diagnostics); } return nonlinear_writer.Write( paths.results_path, domain, std::get(outcome).state, diagnostics); } } // namespace fesa