#include "fesa/io/hdf5/hdf5_results_writer.h" #include #include #include #include #include "io/hdf5/hdf5_atomic_file.h" #include "io/hdf5/hdf5_model_writer.h" #include "io/hdf5/hdf5_primitives.h" #include "io/hdf5/hdf5_raii.h" #include "io/hdf5/hdf5_result_writer.h" #include "io/hdf5/hdf5_self_check.h" namespace fesa { Status Hdf5ResultsWriter::Write(const std::filesystem::path& output_path, const Domain& domain, const AnalysisState& state, const std::vector& diagnostics) { auto plan_result = hdf5_internal::BuildWriterPlan(output_path, domain, state, diagnostics); if (!plan_result.HasValue()) { return plan_result.GetStatus(); } hdf5_internal::WriterPlan plan = std::move(plan_result.Value()); try { hdf5_internal::Hdf5ErrorSilencer silence_backend_errors; const std::filesystem::path candidate_path = hdf5_internal::MakeCandidatePath(output_path); hdf5_internal::CandidateFileGuard cleanup{candidate_path}; hdf5_internal::Hdf5Handle file{ hdf5_internal::RequireHdf5Id( H5Fcreate(candidate_path.string().c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT), "Unable to create the temporary HDF5 file."), H5Fclose}; (void)hdf5_internal::CreateGroup(file.Get(), "/model"); (void)hdf5_internal::CreateGroup(file.Get(), "/steps/Step-1/frames/0/nodal"); (void)hdf5_internal::CreateGroup(file.Get(), "/steps/Step-1/frames/0/element"); if (hdf5_internal::IsShellDomain(domain)) { (void)hdf5_internal::CreateGroup(file.Get(), "/model/shell"); (void)hdf5_internal::CreateGroup(file.Get(), "/steps/Step-1/frames/0/element/shell"); (void)hdf5_internal::CreateGroup(file.Get(), "/steps/Step-1/frames/0/global"); } hdf5_internal::WriteModel(file.Get(), domain, plan.model_data); hdf5_internal::WriteResults(file.Get(), domain, state, diagnostics, plan); hdf5_internal::RequireHdf5(H5Fflush(file.Get(), H5F_SCOPE_GLOBAL), "Unable to flush the temporary HDF5 file."); hdf5_internal::RequireHdf5( file.CloseChecked(), "Unable to close the temporary HDF5 file after writing."); const Status self_check = hdf5_internal::SelfCheck( candidate_path, domain, state, diagnostics.size(), plan.model_data); const Status atomic = hdf5_internal::AtomicFinalizeValidatedCandidate( candidate_path, output_path, self_check); if (atomic.IsOk()) { cleanup.Release(); } return atomic; } catch (const hdf5_internal::Hdf5Failure& failure) { return hdf5_internal::OutputFailure("hdf5-write-failure", failure.what()); } catch (const std::exception& failure) { return hdf5_internal::OutputFailure("hdf5-write-failure", failure.what()); } } } // namespace fesa