#include "results/analysis_state_commit.h" #include #include namespace fesa::results_internal { Status CommitRecoveryCandidate(RecoveryCandidate candidate, AnalysisState& state) { const std::size_t full_count = state.Displacement().Size(); if (candidate.displacement.Size() != full_count || candidate.external_force.Size() != full_count || candidate.internal_force.Size() != full_count || candidate.residual.Size() != full_count || candidate.reaction.Size() != full_count) { return RecoveryFailure( "invalid-recovery-dimensions", {}, state.Identity().step_name, "Recovery candidate vectors must match the AnalysisState dimension."); } if (!IsFiniteVector(candidate.displacement) || !IsFiniteVector(candidate.external_force) || !IsFiniteVector(candidate.internal_force) || !IsFiniteVector(candidate.residual) || !IsFiniteVector(candidate.reaction)) { return RecoveryFailure( "nonfinite-recovery-value", {}, state.Identity().step_name, "Recovery candidate vectors must contain only finite values."); } const bool has_any_beam_rows = !candidate.endpoint_rows.empty() || !candidate.gauss_rows.empty() || !candidate.stress_rows.empty(); const bool has_complete_beam_rows = !candidate.endpoint_rows.empty() && !candidate.gauss_rows.empty() && !candidate.stress_rows.empty(); if (candidate.has_beam_results != has_complete_beam_rows || (has_any_beam_rows && !has_complete_beam_rows)) { return RecoveryFailure( "invalid-recovery-result-family", {}, state.Identity().step_name, "Beam recovery flags require endpoint, Gauss, and stress rows as one " "complete result family."); } const std::array zero_equilibrium{}; const std::array zero_metrics{}; const bool has_any_shell_results = !candidate.expected_shell_elements.empty() || !candidate.shell.rows.empty() || candidate.shell.physical_strain_energy != 0.0 || candidate.shell.equilibrium != zero_equilibrium || candidate.shell.verification_metrics != zero_metrics || candidate.shell.mitc4_drilling.has_value(); const bool has_complete_shell_inventory = !candidate.expected_shell_elements.empty() && !candidate.shell.rows.empty(); if (candidate.has_shell_results != has_complete_shell_inventory || (has_any_shell_results && !has_complete_shell_inventory)) { return RecoveryFailure( "invalid-recovery-result-family", {}, state.Identity().step_name, "Shell recovery flags require expected elements and physical rows as " "one complete result family."); } if (candidate.has_beam_results && candidate.has_shell_results) { return RecoveryFailure( "unsupported-mixed-element-model", {}, "mixed-runtime-results", "Result recovery does not support mixed beam and shell models."); } AnalysisState candidate_state = state; candidate_state.Displacement() = std::move(candidate.displacement); candidate_state.ExternalForce() = std::move(candidate.external_force); candidate_state.InternalForce() = std::move(candidate.internal_force); candidate_state.Residual() = std::move(candidate.residual); candidate_state.Reaction() = std::move(candidate.reaction); candidate_state.EndpointResults() = std::move(candidate.endpoint_rows); candidate_state.GaussResults() = std::move(candidate.gauss_rows); candidate_state.StressResults() = std::move(candidate.stress_rows); const Status shell_commit_status = candidate_state.CommitShellResults( candidate.expected_shell_elements, std::move(candidate.shell)); if (!shell_commit_status.IsOk()) { return shell_commit_status; } state = std::move(candidate_state); return Status::Ok(); } } // namespace fesa::results_internal