modify tolerance policy

This commit is contained in:
KOKO\Mimi
2026-08-18 02:29:26 +09:00
parent 123a1b6ccc
commit 624ea4872c
36 changed files with 1909 additions and 672 deletions
+140 -68
View File
@@ -41,8 +41,8 @@ constexpr const char* kSectionName = "cantilever beam elemental forces.csv";
constexpr const char* kInstanceName = "PART-1_1-1";
constexpr std::size_t kNodeCount = 11U;
constexpr std::size_t kElementCount = 10U;
constexpr std::size_t kExpectedRowCount = 176U;
constexpr std::size_t kExpectedMetricCount = 16U;
constexpr std::size_t kExpectedRowCount = 212U;
constexpr std::size_t kExpectedMetricCount = 6U;
using NodalValues = std::array<std::array<double, 6>, kNodeCount>;
using EndpointValues =
@@ -315,14 +315,29 @@ const fesa::test::RowDecision* FindRow(
const fesa::test::ComponentMetrics* FindMetric(
const fesa::test::ComparisonReport& report,
const fesa::test::ComparisonQuantity quantity,
const std::string& family_identity) {
const auto found =
std::find_if(report.metrics.begin(), report.metrics.end(),
[&](const fesa::test::ComponentMetrics& metric) {
return metric.family_identity == family_identity;
});
return found == report.metrics.end() ? nullptr : &*found;
}
const fesa::test::RowDecision* FindSectionRow(
const fesa::test::ComparisonReport& report,
const std::int64_t source_element_label, const int endpoint_index,
const std::string& component) {
const auto found = std::find_if(
report.metrics.begin(), report.metrics.end(),
[&](const fesa::test::ComponentMetrics& metric) {
return metric.quantity == quantity && metric.component == component;
report.rows.begin(), report.rows.end(),
[&](const fesa::test::RowDecision& row) {
return row.reference.quantity ==
fesa::test::ComparisonQuantity::kSectionResultant &&
row.reference.source_element_label == source_element_label &&
row.reference.endpoint_index == endpoint_index &&
row.reference.component == component;
});
return found == report.metrics.end() ? nullptr : &*found;
return found == report.rows.end() ? nullptr : &*found;
}
void ExpectExactRowInventory(const fesa::test::ComparisonReport& report) {
@@ -381,13 +396,25 @@ void ExpectExactRowInventory(const fesa::test::ComparisonReport& report) {
const std::array<std::string, 4> section_components = {"N", "T", "My", "Mz"};
const std::array<std::string, 4> section_units = {
"force", "force*length", "force*length", "force*length"};
for (std::size_t node = 0U; node < kNodeCount; ++node) {
for (std::size_t component = 0U; component < section_components.size();
++component) {
expect_row(fesa::test::ComparisonQuantity::kSectionResultant, node,
section_components[component], section_units[component],
"beam-local",
"/steps/Step-1/frames/0/element/section_resultant");
for (std::size_t element = 0U; element < kElementCount; ++element) {
for (std::size_t endpoint = 0U; endpoint < 2U; ++endpoint) {
for (std::size_t component = 0U; component < section_components.size();
++component) {
ASSERT_LT(row_index, report.rows.size());
const auto& row = report.rows[row_index++];
for (const auto* side : {&row.fesa, &row.reference}) {
EXPECT_EQ(side->source_element_label,
static_cast<std::int64_t>(element + 1U));
EXPECT_EQ(side->endpoint_index, static_cast<int>(endpoint));
EXPECT_EQ(side->source_node_label,
static_cast<std::int64_t>(element + endpoint + 1U));
EXPECT_EQ(side->component, section_components[component]);
EXPECT_EQ(side->unit_dimension, section_units[component]);
EXPECT_EQ(side->coordinate_system, "beam-local");
EXPECT_EQ(side->hdf5_dataset_path,
"/steps/Step-1/frames/0/element/section_resultant");
}
}
}
}
EXPECT_EQ(row_index, report.rows.size());
@@ -475,14 +502,46 @@ TEST(ReferenceComparisonContract,
fixture.Results(), fixture.Legacy()),
"schema-mismatch");
}
{
ContractFixture fixture{"section-missing-endpoint", mismatched_values};
auto lines = ReadLines(fixture.Legacy() / kSectionName);
ASSERT_EQ(lines.size(), kElementCount * 2U + 1U);
lines.pop_back();
WriteLines(fixture.Legacy() / kSectionName, lines);
ExpectFailureCode(fesa::test::ReferenceComparison::Compare(
fixture.Results(), fixture.Legacy()),
"schema-mismatch");
}
{
ContractFixture fixture{"section-duplicate-endpoint", mismatched_values};
auto lines = ReadLines(fixture.Legacy() / kSectionName);
ASSERT_EQ(lines.size(), kElementCount * 2U + 1U);
lines.push_back(lines[1U]);
WriteLines(fixture.Legacy() / kSectionName, lines);
ExpectFailureCode(fesa::test::ReferenceComparison::Compare(
fixture.Results(), fixture.Legacy()),
"schema-mismatch");
}
{
ContractFixture fixture{"section-mismatched-endpoint", mismatched_values};
auto lines = ReadLines(fixture.Legacy() / kSectionName);
ASSERT_GT(lines.size(), 2U);
ReplaceFirst(lines[1U], ",1,1,", ",1,3,");
WriteLines(fixture.Legacy() / kSectionName, lines);
ExpectFailureCode(fesa::test::ReferenceComparison::Compare(
fixture.Results(), fixture.Legacy()),
"schema-mismatch");
}
}
TEST(ReferenceComparisonContract,
AppliesAbaqusOnlyComponentScaleWithoutClampOrDrop) {
AppliesSharedFamilyScaleAndNearZeroBranchesWithoutAnAbsoluteGate) {
auto values = ReferenceValues();
values.displacement[1U][0U] = 0.999e-9;
values.displacement[2U][0U] = 1.001e-9;
values.section_resultants[0U][0U][2U] = 1.0e7 + 9.0;
const double translation_scale = 1.90476272e-2;
const double near_zero_band = 0.01 * translation_scale;
values.displacement[1U][0U] = 0.999 * near_zero_band;
values.displacement[2U][0U] = 1.001 * near_zero_band;
values.section_resultants[0U][0U][2U] = 1.0e7 + 4.999e5;
values.section_resultants[9U][1U][2U] = 0.0;
ContractFixture fixture{"tolerance", values};
@@ -505,28 +564,28 @@ TEST(ReferenceComparisonContract,
ASSERT_NE(deliberate_failure, nullptr);
EXPECT_DOUBLE_EQ(zero->reference.value, 0.0);
EXPECT_DOUBLE_EQ(zero->fesa.value, 0.0);
EXPECT_DOUBLE_EQ(zero->tolerance, 1.0e-9);
EXPECT_DOUBLE_EQ(zero->tolerance, near_zero_band);
EXPECT_TRUE(zero->passed);
EXPECT_TRUE(near_zero->passed);
EXPECT_FALSE(deliberate_failure->passed);
EXPECT_EQ(near_zero->tolerance_branch, "near-zero");
EXPECT_FALSE(near_zero->relative_error_applicable);
const auto* my_metric = FindMetric(
report, fesa::test::ComparisonQuantity::kSectionResultant, "My");
const auto* my_metric = FindMetric(report, "section-moment");
ASSERT_NE(my_metric, nullptr);
EXPECT_DOUBLE_EQ(my_metric->reference_scale, 1.0e7);
const auto* scaled = FindRow(
report, fesa::test::ComparisonQuantity::kSectionResultant, 1, "My");
const auto* residue = FindRow(
report, fesa::test::ComparisonQuantity::kSectionResultant, 11, "My");
EXPECT_EQ(my_metric->components, (std::vector<std::string>{"T", "My", "Mz"}));
const auto* scaled = FindSectionRow(report, 1, 0, "My");
const auto* residue = FindSectionRow(report, 10, 1, "My");
ASSERT_NE(scaled, nullptr);
ASSERT_NE(residue, nullptr);
EXPECT_DOUBLE_EQ(scaled->tolerance, 10.001);
EXPECT_DOUBLE_EQ(scaled->absolute_error, 9.0);
EXPECT_DOUBLE_EQ(scaled->tolerance, 5.0e5);
EXPECT_DOUBLE_EQ(scaled->absolute_error, 4.999e5);
EXPECT_TRUE(scaled->passed);
EXPECT_DOUBLE_EQ(residue->reference.value, -1.56e-2);
EXPECT_DOUBLE_EQ(residue->reference.value, -1.5625e-2);
EXPECT_DOUBLE_EQ(residue->fesa.value, 0.0);
EXPECT_DOUBLE_EQ(residue->absolute_error, 1.56e-2);
EXPECT_DOUBLE_EQ(residue->tolerance, 10.001);
EXPECT_DOUBLE_EQ(residue->absolute_error, 1.5625e-2);
EXPECT_DOUBLE_EQ(residue->tolerance, 1.0e5);
EXPECT_TRUE(residue->passed);
}
@@ -548,19 +607,18 @@ TEST(ReferenceComparisonContract,
report.rows.begin(), report.rows.end(),
[](const fesa::test::RowDecision& row) { return row.passed; }));
const auto* metric =
FindMetric(report, fesa::test::ComparisonQuantity::kDisplacement, "UX");
const auto* metric = FindMetric(report, "displacement-translation");
const auto* worst =
FindRow(report, fesa::test::ComparisonQuantity::kDisplacement, 2, "UX");
ASSERT_NE(metric, nullptr);
ASSERT_NE(worst, nullptr);
EXPECT_DOUBLE_EQ(metric->reference_scale, 0.0);
EXPECT_EQ(metric->row_count, kNodeCount * 3U);
EXPECT_DOUBLE_EQ(metric->reference_scale, 1.90476272e-2);
EXPECT_DOUBLE_EQ(metric->maximum_absolute_error, 1.0e-9);
EXPECT_DOUBLE_EQ(metric->maximum_normalized_error, 1.0);
EXPECT_NEAR(metric->rms_error,
std::sqrt(1.25 / static_cast<double>(kNodeCount)) * 1.0e-9,
EXPECT_NEAR(metric->relative_rms,
std::sqrt(1.25 / static_cast<double>(kNodeCount * 3U)) * 1.0e-9 /
metric->reference_scale,
1.0e-21);
EXPECT_NEAR(metric->norm_error, std::sqrt(1.25) * 1.0e-9, 1.0e-21);
EXPECT_EQ(metric->worst_row,
static_cast<std::size_t>(worst - report.rows.data()));
@@ -589,7 +647,10 @@ TEST(ReferenceComparisonContract,
const std::string first = ReadBytes(json_a);
EXPECT_EQ(first, ReadBytes(json_b));
for (const char* required :
{"\"rows\"", "\"metrics\"", "\"stress_comparison_applicable\":false",
{"\"rows\"", "\"metrics\"", "\"family_identity\"", "\"components\"",
"\"near_zero_band\"", "\"relative_rms\"", "\"row_count\"",
"\"tolerance_branch\"", "\"relative_error_applicable\"",
"\"stress_comparison_applicable\":false",
"\"stress_comparison_reason\"", "\"physics_evidence\"",
"\"free_residual_norm\"", "\"applied_force\"", "\"reaction_force\"",
"\"applied_moment_about_origin\"", "\"reaction_moment_about_origin\"",
@@ -598,11 +659,10 @@ TEST(ReferenceComparisonContract,
}
}
TEST(ReferenceComparisonContract, NormalizesEligibleStationsWithoutAveraging) {
TEST(ReferenceComparisonContract,
PreservesSectionEndpointIdentityWithoutStationNormalization) {
auto values = ReferenceValues();
values.section_resultants[0U][0U] = {2.0e-4, 3.0e-4, 1.0e7, 4.0e-4};
values.section_resultants[0U][1U][2U] = 9.0e6 - 5.0;
values.section_resultants[1U][0U][2U] = 9.0e6 + 5.0;
ContractFixture fixture{"stations", values};
auto result = fesa::test::ReferenceComparison::Compare(fixture.Results(),
@@ -612,35 +672,47 @@ TEST(ReferenceComparisonContract, NormalizesEligibleStationsWithoutAveraging) {
ASSERT_TRUE(report.passed);
EXPECT_TRUE(report.physics_evidence.endpoint_consistency_passed);
const auto* n = FindRow(
report, fesa::test::ComparisonQuantity::kSectionResultant, 1, "N");
const auto* t = FindRow(
report, fesa::test::ComparisonQuantity::kSectionResultant, 1, "T");
const auto* my = FindRow(
report, fesa::test::ComparisonQuantity::kSectionResultant, 1, "My");
const auto* mz = FindRow(
report, fesa::test::ComparisonQuantity::kSectionResultant, 1, "Mz");
ASSERT_NE(n, nullptr);
ASSERT_NE(t, nullptr);
ASSERT_NE(my, nullptr);
ASSERT_NE(mz, nullptr);
EXPECT_DOUBLE_EQ(n->fesa.value, 2.0e-4);
EXPECT_DOUBLE_EQ(t->fesa.value, 3.0e-4);
EXPECT_DOUBLE_EQ(my->fesa.value, 1.0e7);
EXPECT_DOUBLE_EQ(mz->fesa.value, 4.0e-4);
const auto* interior = FindRow(
report, fesa::test::ComparisonQuantity::kSectionResultant, 2, "My");
const auto* interior = FindSectionRow(report, 1, 1, "My");
ASSERT_NE(interior, nullptr);
EXPECT_DOUBLE_EQ(interior->fesa.value, 9.0e6 - 5.0);
EXPECT_DOUBLE_EQ(interior->reference.value, 9.0e6);
EXPECT_DOUBLE_EQ(interior->absolute_error, 5.0);
auto mismatch_values = ReferenceValues();
mismatch_values.section_resultants[0U][1U][2U] = 9.0e6 - 6.0;
mismatch_values.section_resultants[1U][0U][2U] = 9.0e6 + 6.0;
ContractFixture mismatch{"station-mismatch", mismatch_values};
ExpectFailureCode(fesa::test::ReferenceComparison::Compare(mismatch.Results(),
mismatch.Legacy()),
"tolerance-failure");
const auto* adjacent = FindSectionRow(report, 2, 0, "My");
ASSERT_NE(adjacent, nullptr);
EXPECT_DOUBLE_EQ(adjacent->fesa.value, 9.0e6);
EXPECT_DOUBLE_EQ(adjacent->reference.value, 9.0e6);
}
TEST(ReferenceComparisonContract,
MapsEachSectionCsvComponentToItsDirectEndpointResultant) {
auto values = ReferenceValues();
values.section_resultants[0U][0U] = {11.0, 22.0, 33.0, 44.0};
ContractFixture fixture{"section-component-mapping", values};
auto lines = ReadLines(fixture.Legacy() / kSectionName);
ASSERT_EQ(lines.size(), kElementCount * 2U + 1U);
lines[1U] = "Increment 1: Step Time = 1.000,PART-1_1-1,1,1,11,33,44,22";
WriteLines(fixture.Legacy() / kSectionName, lines);
auto result = fesa::test::ReferenceComparison::Compare(fixture.Results(),
fixture.Legacy());
ASSERT_TRUE(result.HasValue());
const auto& report = result.Value();
ASSERT_TRUE(report.passed);
const auto* n = FindSectionRow(report, 1, 0, "N");
const auto* t = FindSectionRow(report, 1, 0, "T");
const auto* my = FindSectionRow(report, 1, 0, "My");
const auto* mz = FindSectionRow(report, 1, 0, "Mz");
ASSERT_NE(n, nullptr);
ASSERT_NE(t, nullptr);
ASSERT_NE(my, nullptr);
ASSERT_NE(mz, nullptr);
EXPECT_DOUBLE_EQ(n->reference.value, 11.0);
EXPECT_DOUBLE_EQ(t->reference.value, 22.0);
EXPECT_DOUBLE_EQ(my->reference.value, 33.0);
EXPECT_DOUBLE_EQ(mz->reference.value, 44.0);
EXPECT_DOUBLE_EQ(n->fesa.value, 11.0);
EXPECT_DOUBLE_EQ(t->fesa.value, 22.0);
EXPECT_DOUBLE_EQ(my->fesa.value, 33.0);
EXPECT_DOUBLE_EQ(mz->fesa.value, 44.0);
}