feat(result-contract-completion): step 1 — complete-result-contract

This commit is contained in:
KOKO\Mimi
2026-08-02 01:28:37 +09:00
parent 218cfa9d50
commit e0a6a6fa70
8 changed files with 454 additions and 5 deletions
+86
View File
@@ -43,6 +43,12 @@ void validate_nodal_frame(
"Nodal IDs, displacement, and reaction fields must have "
"matching sizes.");
}
if (nodal.origins.size() != nodal.node_ids.size()) {
add_error(
diagnostics,
"results.nodal_origin_size_mismatch",
"Nodal IDs and origins must have matching sizes.");
}
std::set<std::int64_t> node_ids;
for (const NodeId node_id : nodal.node_ids) {
@@ -74,6 +80,84 @@ void validate_nodal_frame(
}
}
void validate_beam_section_result(
const BeamSectionResult& result,
std::vector<Diagnostic>& diagnostics) {
if (
!std::isfinite(result.xi) ||
!is_finite(result.section_strain) ||
!is_finite(result.section_force) ||
!std::isfinite(result.centroid_sigma_xx) ||
!std::ranges::all_of(
result.sigma_xx,
[](const double value) { return std::isfinite(value); })) {
add_error(
diagnostics,
"results.nonfinite_value",
"Beam section result contains a nonfinite value.");
}
}
void validate_element_frame(
const ElementFrame& element,
const NodalFrame& nodal,
std::vector<Diagnostic>& diagnostics) {
std::set<std::int64_t> nodal_ids;
for (const NodeId node_id : nodal.node_ids) {
nodal_ids.insert(node_id.value());
}
std::set<std::int64_t> element_ids;
for (const BeamElementFrame& beam : element.beams) {
if (!element_ids.insert(beam.element.value()).second) {
add_error(
diagnostics,
"results.duplicate_element_id",
"Element frame contains duplicate element ID " +
std::to_string(beam.element.value()) + ".");
}
if (
!is_finite(beam.local_frame.ex) ||
!is_finite(beam.local_frame.ey) ||
!is_finite(beam.local_frame.ez)) {
add_error(
diagnostics,
"results.nonfinite_value",
"Beam local frame contains a nonfinite component.");
}
const BeamSectionResult& first = beam.end_results[0];
const BeamSectionResult& second = beam.end_results[1];
if (first.end_node == second.end_node) {
add_error(
diagnostics,
"results.duplicate_beam_end_node",
"Beam element result contains the same node at both ends.");
}
if (
first.xi != -1.0 || second.xi != 1.0 ||
!nodal_ids.contains(first.end_node.value()) ||
!nodal_ids.contains(second.end_node.value())) {
add_error(
diagnostics,
"results.invalid_beam_connectivity",
"Beam end results must follow (-1, +1) connectivity and "
"reference nodes in the nodal frame.");
}
if (first.sigma_xx.size() != second.sigma_xx.size()) {
add_error(
diagnostics,
"results.recovery_point_count_mismatch",
"Beam end results must have matching recovery-point "
"counts.");
}
validate_beam_section_result(first, diagnostics);
validate_beam_section_result(second, diagnostics);
}
}
} // namespace
Status validate_result_database(const ResultDatabase& database) {
@@ -106,6 +190,8 @@ Status validate_result_database(const ResultDatabase& database) {
}
validate_nodal_frame(frame.nodal, diagnostics);
validate_element_frame(
frame.element, frame.nodal, diagnostics);
}
}