#include "fesa/app/fesa_application.h" #include #include #include #include #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/prepared_analysis.h" #include "fesa/analysis/solid_frequency_procedure.h" #include "fesa/analysis/solid_hht_dynamic_procedure.h" #include "fesa/analysis/solid_static_procedure.h" #include "fesa/analysis/transient_heat_procedure.h" #include "fesa/app/output_paths.h" #include "fesa/assembly/parallel_for.h" #include "fesa/core/diagnostic.h" #include "fesa/io/hdf5/dynamic_hdf5_results_writer.h" #include "fesa/io/hdf5/eigen_hdf5_results_writer.h" #include "fesa/io/hdf5/hdf5_results_writer.h" #include "fesa/io/hdf5/nonlinear_hdf5_results_writer.h" #include "fesa/io/hdf5/solid_hdf5_results_writer.h" #include "fesa/io/hdf5/thermal_hdf5_results_writer.h" #include "fesa/solvers/eigen/mkl_feast_eigen_solver.h" #include "fesa/solvers/linear/mkl_pardiso_solver.h" #include "fesa/solvers/linear/mkl_pardiso_tangent_solver.h" namespace fesa { namespace { constexpr int kSuccessExitCode = 0; constexpr int kUsageExitCode = 2; constexpr int kInputExitCode = 3; constexpr int kModelExitCode = 4; constexpr int kSolverExitCode = 5; constexpr int kOutputExitCode = 6; const char* SeverityName(const Severity severity) { return severity == Severity::kWarning ? "warning" : "error"; } void WriteDiagnostics(std::vector diagnostics) { SortDiagnostics(diagnostics); for (const auto& diagnostic : diagnostics) { // Stable field labels and tab separators keep empty source fields // explicit without depending on locale-specific formatting. std::cerr << "severity=" << SeverityName(diagnostic.severity) << '\t' << "code=" << diagnostic.code << '\t' << "file=" << diagnostic.location.file.generic_u8string() << '\t' << "line=" << diagnostic.location.line << '\t' << "keyword=" << diagnostic.keyword << '\t' << "entity_identity=" << diagnostic.entity_identity << '\t' << "message=" << diagnostic.message << '\n'; } } int ExitCodeFor(const Status& status) { switch (status.Category().value_or(FailureCategory::kInput)) { case FailureCategory::kInput: return kInputExitCode; case FailureCategory::kModel: return kModelExitCode; case FailureCategory::kSolver: return kSolverExitCode; case FailureCategory::kOutput: return kOutputExitCode; } return kInputExitCode; } } // namespace int FesaApplication::Run(const std::vector& arguments) { const auto paths = DeriveSingleInputOutputPaths(arguments, std::filesystem::current_path()); if (!paths.HasValue()) { WriteDiagnostics(paths.GetStatus().Diagnostics()); return kUsageExitCode; } auto lease = AcquireOutputWriteLease(paths.Value()); if (!lease.HasValue()) { WriteDiagnostics(lease.GetStatus().Diagnostics()); return kOutputExitCode; } TbbParallelFor parallel_for; const MklFeastEigenSolver eigen_solver; MklPardisoSolver linear_solver; MklPardisoTangentSolver tangent_solver; Hdf5ResultsWriter linear_writer; NonlinearHdf5ResultsWriter nonlinear_writer; EigenHdf5ResultsWriter eigen_writer; DynamicHdf5ResultsWriter dynamic_writer; ThermalHdf5ResultsWriter thermal_writer; SolidHdf5ResultsWriter solid_writer; NewtonIterationLogWriter log; Status status = log.Open(paths.Value().log_path); if (!status.IsOk()) { WriteDiagnostics(status.Diagnostics()); return ExitCodeFor(status); } Result prepared = PrepareAnalysisInput(paths.Value().input_path); if (!prepared.HasValue()) { status = prepared.GetStatus(); } else { auto procedure = CreateAnalysisProcedure( prepared.Value().domain, parallel_for, linear_solver, tangent_solver, eigen_solver, log); Result outcome = procedure.HasValue() ? ExecutePreparedAnalysis(prepared.Value().domain, *procedure.Value()) : Result::Failure(procedure.GetStatus()); if (!outcome.HasValue()) { status = outcome.GetStatus(); } else { const Status close_status = log.Close(); if (!close_status.IsOk()) { WriteDiagnostics(close_status.Diagnostics()); return ExitCodeFor(close_status); } status = FinalizePreparedAnalysisResult( paths.Value(), prepared.Value().domain, outcome.Value(), prepared.Value().diagnostics, linear_writer, nonlinear_writer, eigen_writer, &dynamic_writer, &thermal_writer, &solid_writer); if (status.IsOk()) { if (prepared.Value().domain.IsSolid()) WriteDiagnostics(prepared.Value().diagnostics); return kSuccessExitCode; } WriteDiagnostics(status.Diagnostics()); return ExitCodeFor(status); } } const Status close_status = log.Close(); if (!close_status.IsOk()) { WriteDiagnostics(close_status.Diagnostics()); return ExitCodeFor(close_status); } if (status.IsOk()) { return kSuccessExitCode; } WriteDiagnostics(status.Diagnostics()); return ExitCodeFor(status); } } // namespace fesa