#include "fesa/app/fesa_application.h" #include #include #include #include #include #include "fesa/analysis/analysis.h" #include "fesa/analysis/linear_static_analysis.h" #include "fesa/app/output_paths.h" #include "fesa/assembly/parallel_for.h" #include "fesa/core/diagnostic.h" #include "fesa/io/hdf5/hdf5_results_writer.h" #include "fesa/solvers/linear/mkl_pardiso_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; } AnalysisRequest request; request.input_path = paths.Value().input_path; request.output_path = paths.Value().results_path; request.log_path = paths.Value().log_path; TbbParallelFor parallel_for; MklPardisoSolver linear_solver; Hdf5ResultsWriter results_writer; std::unique_ptr analysis = std::make_unique( parallel_for, linear_solver, results_writer); const Status status = analysis->Run(request); if (status.IsOk()) { return kSuccessExitCode; } WriteDiagnostics(status.Diagnostics()); return ExitCodeFor(status); } } // namespace fesa