#include "results/beam_result_recovery.h" #include #include #include #include #include namespace fesa::results_internal { Status BeamResultRecovery(const SourceLocation& location, const SourceEntityId& source_id, const EntityIndex expected_element, const std::array& expected_nodes, const BeamElementResultRows& rows, RecoveryCandidate& candidate) { if (rows.endpoint_rows.size() != expected_nodes.size()) { return RecoveryFailure( "invalid-element-result-identity", location, source_id.source_label_text, "Beam endpoint rows must preserve endpoint 0 and 1 source order."); } for (std::size_t endpoint = 0U; endpoint < expected_nodes.size(); ++endpoint) { const auto& row = rows.endpoint_rows[endpoint]; if (row.element != expected_element || row.endpoint != static_cast(endpoint) || !SameSourceIdentity(row.node, expected_nodes[endpoint])) { return RecoveryFailure( "invalid-element-result-identity", location, source_id.source_label_text, "Beam endpoint rows must preserve active element, endpoint, and " "source-node order."); } if (!IsFiniteArray(row.end_action) || !IsFiniteArray(row.section_resultant)) { return RecoveryFailure( "nonfinite-recovery-value", location, source_id.source_label_text, "Beam endpoint actions and section resultants must remain finite."); } } constexpr std::array expected_gauss_points{1, 2}; if (rows.gauss_rows.size() != expected_gauss_points.size()) { return RecoveryFailure( "invalid-element-result-identity", location, source_id.source_label_text, "Beam Gauss rows must preserve GP1 and GP2 source order."); } for (std::size_t point = 0U; point < expected_gauss_points.size(); ++point) { const auto& row = rows.gauss_rows[point]; if (row.element != expected_element || row.gauss_point != expected_gauss_points[point]) { return RecoveryFailure( "invalid-element-result-identity", location, source_id.source_label_text, "Beam Gauss rows must preserve active element and GP1 through GP2 " "order."); } if (!IsFiniteArray(row.generalized_strain) || !IsFiniteArray(row.generalized_resultant)) { return RecoveryFailure( "nonfinite-recovery-value", location, source_id.source_label_text, "Beam generalized recovery values must remain finite."); } } if (rows.stress_rows.empty() || rows.stress_rows.front().gauss_point != 1 || rows.stress_rows.back().gauss_point != 2) { return RecoveryFailure( "invalid-element-result-identity", location, source_id.source_label_text, "Beam stress rows must preserve GP and section-point source order."); } for (std::size_t order = 0U; order < rows.stress_rows.size(); ++order) { const auto& row = rows.stress_rows[order]; if (row.element != expected_element || row.gauss_point < 1 || row.gauss_point > 2 || (order != 0U && std::tie(rows.stress_rows[order - 1U].gauss_point, rows.stress_rows[order - 1U].section_point) >= std::tie(row.gauss_point, row.section_point))) { return RecoveryFailure( "invalid-element-result-identity", location, source_id.source_label_text, "Beam stress rows must preserve active element, GP, and " "section-point order."); } if (!std::isfinite(row.x1) || !std::isfinite(row.x2) || !std::isfinite(row.s11)) { return RecoveryFailure( "nonfinite-recovery-value", location, source_id.source_label_text, "Beam section-point stress values must remain finite."); } } candidate.has_beam_results = true; candidate.endpoint_rows.insert(candidate.endpoint_rows.end(), rows.endpoint_rows.begin(), rows.endpoint_rows.end()); candidate.gauss_rows.insert(candidate.gauss_rows.end(), rows.gauss_rows.begin(), rows.gauss_rows.end()); candidate.stress_rows.insert(candidate.stress_rows.end(), rows.stress_rows.begin(), rows.stress_rows.end()); return Status::Ok(); } } // namespace fesa::results_internal