test: add quad02 stored reference regression

This commit is contained in:
NINI
2026-05-04 23:51:00 +09:00
parent 948a9448ff
commit 3284b52611
6 changed files with 111 additions and 8 deletions
+56
View File
@@ -190,6 +190,23 @@ std::vector<fesa::Real> toVector(const fesa::MITC4ElementDofVector& values) {
return {values.begin(), values.end()};
}
std::string readTextFile(const std::string& path) {
std::ifstream input(path);
std::ostringstream buffer;
buffer << input.rdbuf();
FESA_CHECK(input.good() || !buffer.str().empty());
return buffer.str();
}
void checkComparisonPass(const fesa::ComparisonResult& comparison) {
if (!comparison.pass) {
throw std::runtime_error("reference comparison failed: max_abs_error=" +
std::to_string(comparison.max_abs_error) +
", max_rel_error=" + std::to_string(comparison.max_rel_error) +
", diagnostics=" + std::to_string(comparison.diagnostics.size()));
}
}
fesa::MITC4StrainVector localStrainAt(const fesa::MITC4Geometry& geometry,
const fesa::MITC4ElementDofVector& values,
fesa::Real xi,
@@ -1057,6 +1074,45 @@ FESA_TEST(displacement_comparator_reports_duplicate_actual_nodes) {
FESA_CHECK(fesa::containsDiagnostic(compared.diagnostics, "FESA-COMPARE-DUPLICATE-ACTUAL"));
}
FESA_TEST(quad02_reference_fixture_discovery_is_consistent) {
fesa::AbaqusInputParser parser;
const auto original = parser.parseFile(sourceRoot() + "/references/quad_02.inp");
FESA_CHECK(!original.ok());
FESA_CHECK(fesa::containsDiagnostic(original.diagnostics, "FESA-PARSE-UNSUPPORTED-KEYWORD"));
const auto normalized = parser.parseFile(sourceRoot() + "/references/quad_02_phase1.inp");
FESA_CHECK(normalized.ok());
FESA_CHECK(normalized.domain.nodes.size() == 121);
FESA_CHECK(normalized.domain.elements.size() == 100);
FESA_CHECK(normalized.domain.steps.size() == 1);
FESA_CHECK(normalized.domain.steps.front().name == "Step-1");
const auto reference = fesa::loadDisplacementCsv(sourceRoot() + "/references/quad_02_displacements.csv");
FESA_CHECK(!fesa::hasError(reference.diagnostics));
FESA_CHECK(reference.rows.size() == normalized.domain.nodes.size());
for (const auto& [node_id, node] : normalized.domain.nodes) {
(void)node;
FESA_CHECK(reference.rows.count(node_id) == 1);
}
}
FESA_TEST(quad02_phase1_stored_displacement_reference_regression) {
const auto input_text = readTextFile(sourceRoot() + "/references/quad_02_phase1.inp");
const auto analysis = fesa::runLinearStaticInputString(input_text, "quad_02_phase1.inp");
FESA_CHECK(analysis.ok());
FESA_CHECK(analysis.state.converged);
FESA_CHECK(analysis.result_file.steps.size() == 1);
const auto& frame = analysis.result_file.steps[0].frames[0];
FESA_CHECK(frame.field_outputs.count("U") == 1);
const auto expected = fesa::loadDisplacementCsv(sourceRoot() + "/references/quad_02_displacements.csv");
FESA_CHECK(!fesa::hasError(expected.diagnostics));
const auto comparison = fesa::compareDisplacements(frame.field_outputs.at("U"), expected, {1.0e-12, 1.0e-5, 1.0});
checkComparisonPass(comparison);
FESA_CHECK(comparison.max_abs_error <= 1.0e-5);
FESA_CHECK(comparison.max_rel_error <= 1.0e-5);
}
FESA_TEST(mitc4_shape_functions_node_order_and_tying_points) {
auto center = fesa::shapeFunctions(0.0, 0.0);
const fesa::Real sum = center.n[0] + center.n[1] + center.n[2] + center.n[3];