feat(results-and-pipeline): step 0 — result-database

This commit is contained in:
KOKO\Mimi
2026-08-01 00:14:53 +09:00
parent 4b75b72968
commit 5b7de91988
5 changed files with 323 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
#include <fesa/results/result_database.hpp>
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <set>
#include <string>
#include <utility>
namespace fesa {
namespace {
void add_error(
std::vector<Diagnostic>& diagnostics,
std::string code,
std::string message) {
diagnostics.push_back({
DiagnosticStage::results,
Severity::error,
std::move(code),
std::move(message),
std::nullopt,
});
}
bool is_finite(const std::array<double, 6>& field) {
return std::ranges::all_of(
field,
[](const double component) {
return std::isfinite(component);
});
}
void validate_nodal_frame(
const NodalFrame& nodal,
std::vector<Diagnostic>& diagnostics) {
if (
nodal.displacement.size() != nodal.node_ids.size() ||
nodal.reaction.size() != nodal.node_ids.size()) {
add_error(
diagnostics,
"results.nodal_size_mismatch",
"Nodal IDs, displacement, and reaction fields must have "
"matching sizes.");
}
std::set<std::int64_t> node_ids;
for (const NodeId node_id : nodal.node_ids) {
if (!node_ids.insert(node_id.value()).second) {
add_error(
diagnostics,
"results.duplicate_node_id",
"Nodal frame contains duplicate node ID " +
std::to_string(node_id.value()) + ".");
}
}
for (const auto& displacement : nodal.displacement) {
if (!is_finite(displacement)) {
add_error(
diagnostics,
"results.nonfinite_value",
"Nodal displacement contains a nonfinite component.");
}
}
for (const auto& reaction : nodal.reaction) {
if (!is_finite(reaction)) {
add_error(
diagnostics,
"results.nonfinite_value",
"Nodal reaction contains a nonfinite component.");
}
}
}
} // namespace
Status validate_result_database(const ResultDatabase& database) {
std::vector<Diagnostic> diagnostics;
std::set<std::string> step_names;
for (const ResultStep& step : database.steps) {
if (!step_names.insert(step.name).second) {
add_error(
diagnostics,
"results.duplicate_step_name",
"Result database contains duplicate step name '" +
step.name + "'.");
}
std::set<double> frame_times;
for (const ResultFrame& frame : step.frames) {
if (!std::isfinite(frame.step_time)) {
add_error(
diagnostics,
"results.nonfinite_value",
"Result frame has a nonfinite step time.");
} else if (!frame_times.insert(frame.step_time).second) {
add_error(
diagnostics,
"results.duplicate_frame_time",
"Result step '" + step.name +
"' contains duplicate frame time " +
std::to_string(frame.step_time) + ".");
}
validate_nodal_frame(frame.nodal, diagnostics);
}
}
return {diagnostics.empty(), std::move(diagnostics)};
}
} // namespace fesa