#pragma once #include "fesa/Core/Domain.hpp" #include "fesa/Util/Diagnostics.hpp" #include #include #include namespace fesa { struct AnalysisModel { StepDefinition step; std::vector active_element_ids; std::vector active_boundary_condition_indices; std::vector active_load_indices; std::vector active_shell_section_indices; std::vector active_material_keys; std::vector diagnostics; bool ok() const { return !hasError(diagnostics); } }; inline AnalysisModel buildLinearStaticAnalysisModel(const Domain& domain, LocalIndex step_index = 0) { AnalysisModel model; if (domain.steps.empty()) { model.step = {"Step-1", "linear_static"}; } else { if (step_index < 0 || step_index >= static_cast(domain.steps.size())) { model.diagnostics.push_back(makeDiagnostic(Severity::Error, "FESA-ANALYSIS-STEP-INDEX", "Requested analysis step index is out of range", "analysis model")); model.step = domain.steps.front(); } else { model.step = domain.steps[static_cast(step_index)]; } } if (domain.steps.size() > 1) { model.diagnostics.push_back(makeDiagnostic(Severity::Error, "FESA-ANALYSIS-MULTIPLE-STEPS", "Phase 1 execution supports one active linear static step", "analysis model")); } if (model.step.analysis_type != "linear_static") { model.diagnostics.push_back(makeDiagnostic(Severity::Error, "FESA-ANALYSIS-UNSUPPORTED-STEP", "Only linear static steps are supported in Phase 1", "analysis model")); } for (const auto& [element_id, element] : domain.elements) { (void)element; model.active_element_ids.push_back(element_id); } for (std::size_t i = 0; i < domain.boundary_conditions.size(); ++i) { model.active_boundary_condition_indices.push_back(i); } for (std::size_t i = 0; i < domain.loads.size(); ++i) { model.active_load_indices.push_back(i); } for (std::size_t i = 0; i < domain.shell_sections.size(); ++i) { model.active_shell_section_indices.push_back(i); } for (const auto& [material_key, material] : domain.materials) { (void)material; model.active_material_keys.push_back(material_key); } return model; } } // namespace fesa