Add MITC4 drilling diagnostics output and comparison contract

This commit is contained in:
KOKO\Mimi
2026-10-20 09:45:58 +09:00
parent 3d5c296651
commit a73d3fc9ca
31 changed files with 1175 additions and 45 deletions
@@ -23,6 +23,10 @@
#include "fesa/fem/dof_manager.h"
#include "io/hdf5/hdf5_raii.h"
#include "io/hdf5/mitc4_drilling_diagnostics.h"
#include "mitc4_fault_test_helpers.h"
namespace {
using fesa::hdf5_internal::Hdf5Handle;
@@ -145,6 +149,8 @@ fesa::DynamicAcceptedFrameState MakeFrame(const fesa::Domain& domain,
{fesa::ShellSectionPosition::kMiddle, 0.0, {}},
{fesa::ShellSectionPosition::kTop, 1.0, {}}}}});
}
frame.mitc4_drilling = fesa::Mitc4DrillingEvidence{
fesa::Mitc4DrillingMode::kDirectSpring, {}, frame.global_equilibrium};
return frame;
}
@@ -670,3 +676,58 @@ TEST(DynamicHdf5ResultsWriter, FailedAtomicReplacementPreservesPreviousBytes) {
}
} // namespace
TEST(DynamicHdf5ResultsWriter, DrillingModesIncludeInitialAndEveryAcceptedFrame) {
for (const auto mode : {fesa::Mitc4DrillingMode::kDirectSpring,
fesa::Mitc4DrillingMode::kLegacyCorotatedTwist}) {
auto fixture = MakeFixture();
for (std::uint32_t i = 0; i < 3U; ++i) {
auto frame = MakeFrame(*fixture.domain, i);
frame.mitc4_drilling->mode = mode;
ASSERT_TRUE(fixture.state.CommitAcceptedFrame(frame).IsOk());
}
TempFile path{"drilling-roundtrip"};
ASSERT_TRUE(fesa::DynamicHdf5ResultsWriter{}.Write(path.Path(), *fixture.domain, fixture.state, {}).IsOk());
Hdf5Handle file{H5Fopen(path.Path().string().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT), H5Fclose};
const auto stored = fesa::hdf5_internal::ReadDrillingDiagnostics(file.Get());
ASSERT_TRUE(stored);
EXPECT_EQ(stored->formulation, fesa::Mitc4DrillingModeName(mode));
ASSERT_EQ(stored->frames.size(), 3U);
for (std::size_t i = 0; i < 3U; ++i) {
EXPECT_EQ(stored->frames[i].frame_index, i);
EXPECT_EQ(stored->frames[i].raw_equilibrium, fixture.state.AcceptedFrames()[i].global_equilibrium);
EXPECT_EQ(stored->frames[i].equilibrium_with_drilling,
fixture.state.AcceptedFrames()[i].mitc4_drilling->equilibrium_with_drilling);
}
}
}
TEST(DynamicHdf5ResultsWriter, DrillingMissingActualStatePreservesPriorFinal) {
auto fixture = MakeFixture();
for (std::uint32_t i = 0; i < 3U; ++i) {
auto frame = MakeFrame(*fixture.domain, i);
frame.mitc4_drilling.reset();
ASSERT_TRUE(fixture.state.CommitAcceptedFrame(frame).IsOk());
}
TempFile path{"drilling-missing"};
std::ofstream(path.Path(), std::ios::binary) << "prior";
EXPECT_FALSE(fesa::DynamicHdf5ResultsWriter{}.Write(path.Path(), *fixture.domain, fixture.state, {}).IsOk());
std::ifstream stream{path.Path(), std::ios::binary};
EXPECT_EQ((std::string{std::istreambuf_iterator<char>{stream}, {}}), "prior");
}
TEST(DynamicHdf5ResultsWriter, DrillingLifecycleFaultsPreserveFinalBytes) {
auto fixture = MakeFixture();
CommitHistory(fixture);
TempFile path{"drilling-faults"};
for (const std::string fault : {"candidate-close", "reader-close", "markers", "datasets"}) {
SCOPED_TRACE(fault);
std::ofstream(path.Path(), std::ios::binary | std::ios::trunc) << "prior";
EXPECT_FALSE(fesa::hdf5_internal::WriteDynamicFile(path.Path(), *fixture.domain, fixture.state, {},
fesa::test::Mitc4LifecycleFault(fault)).IsOk());
std::ifstream stream{path.Path(), std::ios::binary};
EXPECT_EQ((std::string{std::istreambuf_iterator<char>{stream}, {}}), "prior");
}
}