From 7ee45d4224b1ae003447ad7468c01b68c23d5bc0 Mon Sep 17 00:00:00 2001 From: Tobias Meisel <tobias.meisel@ufz.de> Date: Tue, 15 Dec 2020 13:02:21 +0100 Subject: [PATCH] [MeL/IO] Introduce data structure for handling meta data for hdf writing algorithm --- MeshLib/IO/XDMF/HdfData.cpp | 49 +++++++++++++++++++++++++ MeshLib/IO/XDMF/HdfData.h | 36 +++++++++++++++++++ MeshLib/IO/XDMF/XdmfData.cpp | 68 +++++++++++++++++++++++++++++++++++ MeshLib/IO/XDMF/XdmfData.h | 65 +++++++++++++++++++-------------- MeshLib/IO/XDMF/XdmfHdfData.h | 44 +++++++++++++++++++++++ 5 files changed, 235 insertions(+), 27 deletions(-) create mode 100644 MeshLib/IO/XDMF/HdfData.cpp create mode 100644 MeshLib/IO/XDMF/HdfData.h create mode 100644 MeshLib/IO/XDMF/XdmfData.cpp create mode 100644 MeshLib/IO/XDMF/XdmfHdfData.h diff --git a/MeshLib/IO/XDMF/HdfData.cpp b/MeshLib/IO/XDMF/HdfData.cpp new file mode 100644 index 00000000000..54e3c15b48d --- /dev/null +++ b/MeshLib/IO/XDMF/HdfData.cpp @@ -0,0 +1,49 @@ +#include "HdfData.h" + +#include <hdf5.h> + +#include <map> + +#include "BaseLib/Error.h" +#include "BaseLib/Logging.h" +#include "partition.h" + +namespace MeshLib::IO +{ +static hid_t meshPropertyType2HdfType(MeshPropertyDataType const ogs_data_type) +{ + std::map<MeshPropertyDataType const, hid_t> ogs_to_hdf_type = { + {MeshPropertyDataType::float64, H5T_IEEE_F64LE}, + {MeshPropertyDataType::float32, H5T_IEEE_F32LE}, + {MeshPropertyDataType::int32, H5T_STD_I32LE}, + {MeshPropertyDataType::int64, H5T_STD_I64LE}, + {MeshPropertyDataType::uint32, H5T_STD_U32LE}, + {MeshPropertyDataType::uint64, H5T_STD_U64LE}, + {MeshPropertyDataType::int8, H5T_STD_I8LE}, + {MeshPropertyDataType::uint8, H5T_STD_U8LE}}; + try + { + return ogs_to_hdf_type.at(ogs_data_type); + } + catch (std::exception const& e) + { + OGS_FATAL("No known HDF5 type for OGS type. {:s}", e.what()); + } +} + +HdfData::HdfData(void const* data_start, std::size_t const size_partitioned_dim, + std::size_t const size_tuple, std::string const& name, + MeshPropertyDataType const mesh_property_data_type) + : data_start(data_start), + data_space{size_partitioned_dim, size_tuple}, + name(name) +{ + auto const& partition_info = getPartitionInfo(size_partitioned_dim); + DBUG("HdfData: The partition of dataset {:s} has dimension {:d} and offset {:d}.", + name, size_partitioned_dim, partition_info.first); + auto const& offset_partitioned_dim = partition_info.first; + offsets = {offset_partitioned_dim, 0}; + file_space = {partition_info.second, size_tuple}; + data_type = meshPropertyType2HdfType(mesh_property_data_type); +} +} // namespace MeshLib::IO \ No newline at end of file diff --git a/MeshLib/IO/XDMF/HdfData.h b/MeshLib/IO/XDMF/HdfData.h new file mode 100644 index 00000000000..e31bb62c90b --- /dev/null +++ b/MeshLib/IO/XDMF/HdfData.h @@ -0,0 +1,36 @@ +/** + * \file + * \author Tobias Meisel + * \date 2020-12-08 + * \brief Collects and holds all metadata for writing HDF5 file + * \copyright Copyright (c) 2012-2020, OpenGeoSys Community + * (http://www.opengeosys.org) Distributed under a Modified BSD License. See + * accompanying file LICENSE.txt or http://www.opengeosys.org/project/license + */ + + +#pragma once + +#include <string> +#include <vector> + +#include "MeshPropertyDataType.h" + +namespace MeshLib::IO +{ +using Hdf5DimType = unsigned long long; + +struct HdfData +{ + HdfData(void const* data_start, std::size_t size_partitioned_dim, + std::size_t size_tuple, std::string const& name, + MeshPropertyDataType mesh_property_data_type); + void const* data_start; + std::vector<Hdf5DimType> const data_space; + std::vector<Hdf5DimType> offsets; + std::vector<Hdf5DimType> file_space; + std::string const name; + int64_t data_type; +}; + +} // namespace MeshLib::IO \ No newline at end of file diff --git a/MeshLib/IO/XDMF/XdmfData.cpp b/MeshLib/IO/XDMF/XdmfData.cpp new file mode 100644 index 00000000000..cdee513cad8 --- /dev/null +++ b/MeshLib/IO/XDMF/XdmfData.cpp @@ -0,0 +1,68 @@ +#include "XdmfData.h" + +#include <XdmfArrayType.hpp> +#include <XdmfAttributeCenter.hpp> +#include <XdmfTopologyType.hpp> +#include <cassert> +#include <map> + +#include "BaseLib/Error.h" +#include "MeshLib/Location.h" +#include "partition.h" + +namespace MeshLib::IO + +{ +static boost::shared_ptr<XdmfArrayType const> MeshPropertyDataType2XdmfType( + MeshPropertyDataType const ogs_data_type) +{ + std::map<MeshPropertyDataType, boost::shared_ptr<XdmfArrayType const>> const + ogs_to_xdmf_type = { + {MeshPropertyDataType::float64, XdmfArrayType::Float64()}, + {MeshPropertyDataType::float32, XdmfArrayType::Float32()}, + {MeshPropertyDataType::int32, XdmfArrayType::Int32()}, + // TODO (tm) XdmfLib does not support 64 bit data types so far + //{MeshPropertyDataType::int64, XdmfArrayType::Int64()}, + {MeshPropertyDataType::uint32, XdmfArrayType::UInt32()}, + // TODO (tm) XdmfLib does not support 64 bit data types so far + //{MeshPropertyDataType::uint64, XdmfArrayType::UInt64}, + {MeshPropertyDataType::int8, XdmfArrayType::Int8()}, + {MeshPropertyDataType::uint8, XdmfArrayType::UInt8()}}; + try + { + return ogs_to_xdmf_type.at(ogs_data_type); + } + catch (const std::exception& e) + { + OGS_FATAL("No known HDF5 type for XDMF type. {:s}", e.what()); + } +} + +XdmfData::XdmfData(std::size_t size_partitioned_dim, + std::size_t const size_tuple, + MeshPropertyDataType const mesh_property_data_type, + std::string const& name, + std::optional<MeshLib::MeshItemType> const attribute_center) + : starts{0, 0, 0}, + strides{1, 1, 1}, + name(name), + attribute_center(attribute_center) +{ + auto partition_info = getPartitionInfo(size_partitioned_dim); + DBUG( + "XdmfData: The partition of dataset {:s} has dimension {:d} and offset " + "{:d}.", + name, size_partitioned_dim, partition_info.first); + // TODO (tm) XdmfLib does not support 64 bit data types so far + assert(partition_info.second < std::numeric_limits<unsigned int>::max()); + auto const ui_global_components = + static_cast<unsigned int>(partition_info.second); + auto const ui_tuple_size = static_cast<unsigned int>(size_tuple); + + piece_dims = {ui_global_components, ui_tuple_size}; + block_dims = {static_cast<XdmfDimType>(size_partitioned_dim), + ui_tuple_size}; + + data_type = MeshPropertyDataType2XdmfType(mesh_property_data_type); +} +} // namespace MeshLib::IO \ No newline at end of file diff --git a/MeshLib/IO/XDMF/XdmfData.h b/MeshLib/IO/XDMF/XdmfData.h index 2a8ad7d90d5..6bb86b6aa09 100644 --- a/MeshLib/IO/XDMF/XdmfData.h +++ b/MeshLib/IO/XDMF/XdmfData.h @@ -2,7 +2,7 @@ * \file * \author Tobias Meisel * \date 2020-11-13 - * \brief Definition of the data layer for writing Meshes + * \brief Collects and holds all metadata for writing XDMF file * \copyright * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org) * Distributed under a Modified BSD License. @@ -13,43 +13,54 @@ #pragma once #include <boost/shared_ptr.hpp> +#include <optional> #include <string> #include <vector> -class XdmfAttributeCenter; +#include "MeshLib/Location.h" +#include "MeshPropertyDataType.h" + class XdmfArrayType; namespace MeshLib::IO { using XdmfDimType = unsigned int; -using Hdf5DimType = unsigned long long; -struct Geometry final -{ - std::vector<double> flattend_values; - std::vector<XdmfDimType> const starts; - std::vector<XdmfDimType> const strides; - std::vector<XdmfDimType> const vdims; - std::vector<Hdf5DimType> const vldims; -}; -struct Topology final +struct XdmfData { - std::vector<int> flattend_values; + /** + * \brief XdmfData contains meta data to be passed to the XdmfWriter - it + * does not contain the actual values!! + * @param size_partitioned_dim The first dimension (index 0) is assumed to + * be the dimension that is partitioned. This first dimension expresses the + * length, usually the number of nodes or the number of cells. These values + * give the length of the local partition. + * @param size_tuple We assume there is at most a rank of 2 of data + * (properties). The size of tuple gives the length of the second dimension + * (index 1). + * @param name The name of the attribute. It assumed to be unique. + * @param attribute_center XdmfData is used for topology, geometry and + * attributes. Geometry and topology have never a attribute_center. + * Attributes have always an attribute_center + * @return vector of meta data + */ + XdmfData(std::size_t size_partitioned_dim, std::size_t size_tuple, + MeshPropertyDataType mesh_property_data_type, + std::string const& name, + std::optional<MeshLib::MeshItemType> attribute_center); + // a hyperslab is defined by starts and strides see + // https://www.xdmf.org/index.php/XDMF_Model_and_Format#HyperSlab std::vector<XdmfDimType> const starts; std::vector<XdmfDimType> const strides; - std::vector<XdmfDimType> const vdims; - std::vector<Hdf5DimType> const vldims; -}; - -struct AttributeMeta final -{ - const void* data_start; - std::string name; - boost::shared_ptr<const XdmfAttributeCenter> attribute_center; + // piece and block nomenclature taken from + // https://www.paraview.org/Wiki/VTK/Tutorials/Composite_Datasets in XDMF it + // refers to spatial grid collection composed from subsets + // https://www.xdmf.org/index.php/XDMF_Model_and_Format#Grid + std::vector<XdmfDimType> piece_dims; + std::vector<XdmfDimType> block_dims; boost::shared_ptr<const XdmfArrayType> data_type; - std::vector<XdmfDimType> starts; - std::vector<XdmfDimType> strides; - std::vector<XdmfDimType> vdims; - std::vector<Hdf5DimType> vldims; + std::string const name; + std::optional<MeshLib::MeshItemType> const attribute_center; }; -} // namespace MeshLib::IO \ No newline at end of file + +} // namespace MeshLib::IO diff --git a/MeshLib/IO/XDMF/XdmfHdfData.h b/MeshLib/IO/XDMF/XdmfHdfData.h new file mode 100644 index 00000000000..1b049e40f2b --- /dev/null +++ b/MeshLib/IO/XDMF/XdmfHdfData.h @@ -0,0 +1,44 @@ +/** + * \file + * \author Tobias Meisel + * \date 2020-11-13 + * \brief Holds all data for the combined writing of xdmf and hdf5 file + * \copyright + * Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <vector> + +#include "HdfData.h" +#include "XdmfData.h" + +// TODO (tm) This structs are the result of transformData.cpp. This structures +// can be eliminated. +namespace MeshLib::IO +{ +struct Geometry final +{ + std::vector<double> flattened_values; + HdfData hdf; + XdmfData xdmf; +}; + +struct Topology final +{ + std::vector<int> flattened_values; + HdfData hdf; + XdmfData xdmf; +}; + +struct AttributeMeta final +{ + HdfData hdf; + XdmfData xdmf; +}; +} // namespace MeshLib::IO \ No newline at end of file -- GitLab