75 lines
3.0 KiB
C++
75 lines
3.0 KiB
C++
#include "fesa/io/hdf5/hdf5_results_writer.h"
|
|
|
|
#include <exception>
|
|
#include <filesystem>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#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<Diagnostic>& 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
|