Files
FESADev/src/fesa/results/analysis_state_commit.cpp
T

88 lines
3.9 KiB
C++

#include "results/analysis_state_commit.h"
#include <array>
#include <utility>
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<double, 6> zero_equilibrium{};
const std::array<double, 3> 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