feat(beam-reference-qualification): correlate Abaqus beam results
This commit is contained in:
@@ -240,6 +240,66 @@ TEST(ComparisonMetric, RejectsComponentCountMismatch) {
|
||||
report.failures, "validation.component_count_mismatch"));
|
||||
}
|
||||
|
||||
TEST(CorrelationMetric, ComputesComponentWiseRmseAndRelativeL2) {
|
||||
const std::vector<fesa::ComparisonSample> inputs{
|
||||
sample(
|
||||
fesa::ReferenceQuantity::displacement,
|
||||
{"Part-1-1", 101, std::nullopt},
|
||||
{3.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 1.0e-9}),
|
||||
sample(
|
||||
fesa::ReferenceQuantity::displacement,
|
||||
{"Part-1-1", 102, std::nullopt},
|
||||
{4.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 1.0e-9}),
|
||||
};
|
||||
|
||||
const auto report = fesa::correlate_samples(inputs);
|
||||
|
||||
ASSERT_TRUE(report.evaluable);
|
||||
ASSERT_TRUE(report.failures.empty());
|
||||
ASSERT_EQ(report.metrics.size(), 6U);
|
||||
EXPECT_EQ(report.metrics[0].quantity, fesa::ReferenceQuantity::displacement);
|
||||
EXPECT_EQ(report.metrics[0].component_index, 0U);
|
||||
EXPECT_EQ(report.metrics[0].value_count, 2U);
|
||||
EXPECT_DOUBLE_EQ(
|
||||
report.metrics[0].root_mean_square_error,
|
||||
std::sqrt(12.5));
|
||||
EXPECT_DOUBLE_EQ(report.metrics[0].relative_l2_error, 1.0);
|
||||
EXPECT_DOUBLE_EQ(report.metrics[1].root_mean_square_error, 0.0);
|
||||
EXPECT_DOUBLE_EQ(report.metrics[1].relative_l2_error, 0.0);
|
||||
}
|
||||
|
||||
TEST(CorrelationMetric, UsesAbsoluteScaleNormForNearZeroReference) {
|
||||
const std::vector<fesa::ComparisonSample> inputs{
|
||||
sample(
|
||||
fesa::ReferenceQuantity::reaction,
|
||||
{"Part-1-1", 101, std::nullopt},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{3.0e-9, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 1.0e-9}),
|
||||
sample(
|
||||
fesa::ReferenceQuantity::reaction,
|
||||
{"Part-1-1", 102, std::nullopt},
|
||||
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{4.0e-9, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
{0.0, 1.0e-9}),
|
||||
};
|
||||
|
||||
const auto report = fesa::correlate_samples(inputs);
|
||||
|
||||
ASSERT_TRUE(report.evaluable);
|
||||
ASSERT_EQ(report.metrics.size(), 6U);
|
||||
EXPECT_DOUBLE_EQ(
|
||||
report.metrics[0].root_mean_square_error,
|
||||
std::sqrt(12.5) * 1.0e-9);
|
||||
EXPECT_DOUBLE_EQ(
|
||||
report.metrics[0].relative_l2_error,
|
||||
5.0 / std::sqrt(2.0));
|
||||
}
|
||||
|
||||
TEST(EntityMatching, MatchesNodalResultByInstanceAndExternalLabel) {
|
||||
const auto frame = result_frame();
|
||||
const std::array reference{0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
||||
|
||||
@@ -72,14 +72,14 @@ TEST(ReferenceCsv, ReadsSuppliedDisplacementsWithWhitespaceHeader) {
|
||||
EXPECT_EQ(
|
||||
result.rows.front().quantity,
|
||||
fesa::ReferenceQuantity::displacement);
|
||||
EXPECT_EQ(result.rows.front().position.instance_name, "Part-1-1");
|
||||
EXPECT_EQ(result.rows.front().position.instance_name, "PART-1_1-1");
|
||||
EXPECT_EQ(result.rows.front().position.entity_label, 1);
|
||||
EXPECT_FALSE(result.rows.front().position.end_node_label.has_value());
|
||||
EXPECT_EQ(
|
||||
result.rows.front().values,
|
||||
(std::vector<double>{0.0, 0.0, -1.0e-32, 0.0, 1.0e-31, 0.0}));
|
||||
(std::vector<double>{0.0, 0.0, -1.0e-30, 0.0, 1.0e-29, 0.0}));
|
||||
EXPECT_EQ(result.rows.back().position.entity_label, 11);
|
||||
EXPECT_EQ(result.rows.back().values[2], -1.92e-4);
|
||||
EXPECT_EQ(result.rows.back().values[2], -1.91857e-2);
|
||||
}
|
||||
|
||||
TEST(ReferenceCsv, ReadsSuppliedReactionsWithWhitespaceHeader) {
|
||||
@@ -90,12 +90,12 @@ TEST(ReferenceCsv, ReadsSuppliedReactionsWithWhitespaceHeader) {
|
||||
|
||||
ASSERT_TRUE(result.diagnostics.empty());
|
||||
ASSERT_EQ(result.rows.size(), 11U);
|
||||
EXPECT_EQ(result.rows.front().position.instance_name, "Part-1-1");
|
||||
EXPECT_EQ(result.rows.front().position.instance_name, "PART-1_1-1");
|
||||
EXPECT_EQ(result.rows.front().position.entity_label, 1);
|
||||
EXPECT_FALSE(result.rows.front().position.end_node_label.has_value());
|
||||
EXPECT_EQ(
|
||||
result.rows.front().values,
|
||||
(std::vector<double>{0.0, 0.0, 1.0e4, 0.0, -1.0e5, 0.0}));
|
||||
(std::vector<double>{0.0, 0.0, 1.0e6, 0.0, -1.0e7, 0.0}));
|
||||
}
|
||||
|
||||
TEST(InternalForceCsv, MapsAllSixComponentsAndElementEndPosition) {
|
||||
@@ -115,7 +115,26 @@ TEST(InternalForceCsv, MapsAllSixComponentsAndElementEndPosition) {
|
||||
EXPECT_EQ(*result.rows.front().position.end_node_label, 101);
|
||||
EXPECT_EQ(
|
||||
result.rows.front().values,
|
||||
(std::vector<double>{1.25, -2.5, 3.75, -4.0, 5.5, -6.25}));
|
||||
(std::vector<double>{1.25, 3.75, -2.5, -6.25, -4.0, 5.5}));
|
||||
}
|
||||
|
||||
TEST(InternalForceCsv, AcceptsTrailingEmptyAbaqusExportColumns) {
|
||||
const TemporaryCsv input{
|
||||
"fesa-reference-trailing-empty-columns.csv",
|
||||
"Part Instance Name,Element Label,Node Label,SF-SF1,SF-SF2,"
|
||||
"SF-SF3,SM-SM1,SM-SM2,SM-SM3,,,\n"
|
||||
"PART-1_1-1,1,1,1,2,3,4,5,6,,,\n"};
|
||||
|
||||
const auto result = fesa::read_reference_csv(
|
||||
fesa::ReferenceQuantity::internal_force,
|
||||
input.path(),
|
||||
"unused-request-name");
|
||||
|
||||
ASSERT_TRUE(result.diagnostics.empty());
|
||||
ASSERT_EQ(result.rows.size(), 1U);
|
||||
EXPECT_EQ(
|
||||
result.rows.front().values,
|
||||
(std::vector<double>{1.0, 3.0, 2.0, 6.0, 4.0, 5.0}));
|
||||
}
|
||||
|
||||
TEST(StressCsv, FillsOmittedInstanceAndReadsCentroidStress) {
|
||||
|
||||
Reference in New Issue
Block a user