Add MITC4 drilling diagnostics output and comparison contract
This commit is contained in:
@@ -18,6 +18,10 @@
|
||||
#include "io/hdf5/hdf5_primitives.h"
|
||||
#include "io/hdf5/hdf5_raii.h"
|
||||
|
||||
#include "io/hdf5/mitc4_drilling_diagnostics.h"
|
||||
|
||||
#include "io/hdf5/mitc4_file_hooks.h"
|
||||
|
||||
namespace fesa {
|
||||
namespace {
|
||||
|
||||
@@ -849,13 +853,13 @@ void CheckTables(const hid_t file, const DynamicAnalysisState& state,
|
||||
Status SelfCheck(const std::filesystem::path& path, const Domain& domain,
|
||||
const DynamicAnalysisState& state,
|
||||
const hdf5_internal::WriterModelData& model,
|
||||
const std::vector<Diagnostic>& diagnostics) {
|
||||
const std::vector<Diagnostic>& diagnostics, herr_t (*close_reader)(hid_t)) {
|
||||
try {
|
||||
Hdf5Handle file{
|
||||
hdf5_internal::RequireHdf5Id(
|
||||
H5Fopen(path.string().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT),
|
||||
"Unable to reopen dynamic candidate."),
|
||||
H5Fclose};
|
||||
close_reader};
|
||||
Hdf5Handle metadata{hdf5_internal::RequireHdf5Id(
|
||||
H5Gopen2(file.Get(), "/metadata", H5P_DEFAULT),
|
||||
"The dynamic metadata group is missing."),
|
||||
@@ -902,9 +906,16 @@ Status SelfCheck(const std::filesystem::path& path, const Domain& domain,
|
||||
"Unable to inspect accepted frame group.");
|
||||
Check(information.nlinks == state.AcceptedFrames().size(),
|
||||
"Unexpected frame group inventory.");
|
||||
const auto drilling = hdf5_internal::RequireDrillingDiagnostics(
|
||||
file.Get(), state.AcceptedFrames().front().mitc4_drilling->mode);
|
||||
hdf5_internal::RequireDrilling(drilling.frames.size() == state.AcceptedFrames().size());
|
||||
std::size_t drilling_index = 0U;
|
||||
for (const auto& frame : state.AcceptedFrames()) {
|
||||
hdf5_internal::CheckDrillingFrame(drilling.frames[drilling_index++], frame.frame_index,
|
||||
frame.global_equilibrium, *frame.mitc4_drilling);
|
||||
WriteFrame(file.Get(), domain, frame, true);
|
||||
}
|
||||
hdf5_internal::RequireHdf5(file.CloseChecked(), "Unable to close dynamic readback.");
|
||||
return Status::Ok();
|
||||
} catch (const std::exception& error) {
|
||||
return Failure("dynamic-output-schema", error.what());
|
||||
@@ -913,10 +924,10 @@ Status SelfCheck(const std::filesystem::path& path, const Domain& domain,
|
||||
|
||||
} // namespace
|
||||
|
||||
Status DynamicHdf5ResultsWriter::Write(
|
||||
Status hdf5_internal::WriteDynamicFile(
|
||||
const std::filesystem::path& output_path, const Domain& domain,
|
||||
const DynamicAnalysisState& state,
|
||||
const std::vector<Diagnostic>& diagnostics) {
|
||||
const std::vector<Diagnostic>& diagnostics, const Mitc4FileHooks& hooks) {
|
||||
if (output_path.empty() || output_path.filename().empty() ||
|
||||
!state.IsInitialized() || state.AcceptedFrames().empty() ||
|
||||
domain.Dynamic() == nullptr)
|
||||
@@ -924,6 +935,11 @@ Status DynamicHdf5ResultsWriter::Write(
|
||||
"Dynamic output requires a named path, initialized state, "
|
||||
"and accepted frames.");
|
||||
try {
|
||||
for (const auto& frame : state.AcceptedFrames()) {
|
||||
hdf5_internal::ValidateDrillingEvidence(frame.global_equilibrium, frame.mitc4_drilling);
|
||||
hdf5_internal::RequireDrilling(frame.mitc4_drilling->mode ==
|
||||
state.AcceptedFrames().front().mitc4_drilling->mode);
|
||||
}
|
||||
hdf5_internal::Hdf5ErrorSilencer silence;
|
||||
const auto& step = *domain.Dynamic();
|
||||
Check(state.AcceptedFrames().size() ==
|
||||
@@ -965,24 +981,28 @@ Status DynamicHdf5ResultsWriter::Write(
|
||||
H5Fcreate(candidate_path.string().c_str(), H5F_ACC_EXCL,
|
||||
H5P_DEFAULT, H5P_DEFAULT),
|
||||
"Unable to create dynamic candidate."),
|
||||
H5Fclose};
|
||||
hooks.candidate_close};
|
||||
(void)hdf5_internal::CreateGroup(file.Get(), "/model/shell");
|
||||
hdf5_internal::WriteModel(file.Get(), domain, model);
|
||||
WriteMetadata(file.Get(), domain, state.AcceptedFrames().front());
|
||||
hdf5_internal::WriteDrillingMetadata(file.Get(), state.AcceptedFrames().front().mitc4_drilling->mode);
|
||||
WriteDensity(file.Get(), domain);
|
||||
(void)hdf5_internal::CreateGroup(file.Get(), "/steps");
|
||||
(void)hdf5_internal::CreateGroup(file.Get(), "/steps/Step-1");
|
||||
WriteAcceptedFrames(file.Get(), state.AcceptedFrames());
|
||||
for (const auto& frame : state.AcceptedFrames()) {
|
||||
WriteFrame(file.Get(), domain, frame);
|
||||
hdf5_internal::WriteDrillingFrame(file.Get(),
|
||||
"/steps/Step-1/frames/" + std::to_string(frame.frame_index), *frame.mitc4_drilling);
|
||||
}
|
||||
WriteDiagnostics(file.Get(), diagnostics);
|
||||
hdf5_internal::RequireHdf5(H5Fflush(file.Get(), H5F_SCOPE_GLOBAL),
|
||||
"Unable to flush dynamic candidate.");
|
||||
hdf5_internal::RequireHdf5(file.CloseChecked(),
|
||||
"Unable to close dynamic candidate.");
|
||||
if (hooks.before_self_check) hooks.before_self_check(candidate_path);
|
||||
const Status check =
|
||||
SelfCheck(candidate_path, domain, state, model, diagnostics);
|
||||
SelfCheck(candidate_path, domain, state, model, diagnostics, hooks.reader_close);
|
||||
const Status finalization = hdf5_internal::AtomicFinalizeValidatedCandidate(
|
||||
candidate_path, output_path, check);
|
||||
if (finalization.IsOk()) cleanup.Release();
|
||||
@@ -994,4 +1014,10 @@ Status DynamicHdf5ResultsWriter::Write(
|
||||
}
|
||||
}
|
||||
|
||||
Status DynamicHdf5ResultsWriter::Write(
|
||||
const std::filesystem::path& output_path, const Domain& domain,
|
||||
const DynamicAnalysisState& state, const std::vector<Diagnostic>& diagnostics) {
|
||||
return hdf5_internal::WriteDynamicFile(output_path, domain, state, diagnostics);
|
||||
}
|
||||
|
||||
} // namespace fesa
|
||||
|
||||
Reference in New Issue
Block a user