From 8c24f29d297b0da48b72c6284c93c62a5b2a2f46 Mon Sep 17 00:00:00 2001
From: Tobias Meisel <tobias.meisel@ufz.de>
Date: Tue, 20 Jul 2021 15:19:34 +0200
Subject: [PATCH] [MeL/IO] XDMF: Use new xdmf writer

---
 MeshLib/IO/XDMF/MeshPropertyDataType.h |   5 +-
 MeshLib/IO/XDMF/Xdmf3Writer.cpp        | 182 -------------------------
 MeshLib/IO/XDMF/Xdmf3Writer.h          |  77 -----------
 MeshLib/IO/XDMF/XdmfData.cpp           |  41 +-----
 MeshLib/IO/XDMF/XdmfData.h             |  12 +-
 MeshLib/IO/XDMF/XdmfHdfWriter.cpp      |  42 ++++--
 MeshLib/IO/XDMF/XdmfHdfWriter.h        |  14 +-
 MeshLib/IO/XDMF/transformData.cpp      | 124 +++++++++--------
 MeshLib/IO/writeMeshToFile.cpp         |   6 +-
 MeshLib/MeshEnums.h                    |   3 +-
 ProcessLib/Output/Output.cpp           |   2 +-
 11 files changed, 125 insertions(+), 383 deletions(-)
 delete mode 100644 MeshLib/IO/XDMF/Xdmf3Writer.cpp
 delete mode 100644 MeshLib/IO/XDMF/Xdmf3Writer.h

diff --git a/MeshLib/IO/XDMF/MeshPropertyDataType.h b/MeshLib/IO/XDMF/MeshPropertyDataType.h
index 35d32bf1fa2..e792809d962 100644
--- a/MeshLib/IO/XDMF/MeshPropertyDataType.h
+++ b/MeshLib/IO/XDMF/MeshPropertyDataType.h
@@ -15,7 +15,7 @@
 // TODO (tm) If used on several other places move definition of propertyVector
 enum class MeshPropertyDataType
 {
-    unknown,
+    unknown=0,
     float64,
     float32,
     int32,
@@ -23,5 +23,6 @@ enum class MeshPropertyDataType
     uint32,
     uint64,
     int8,
-    uint8
+    uint8,
+    enum_length
 };
\ No newline at end of file
diff --git a/MeshLib/IO/XDMF/Xdmf3Writer.cpp b/MeshLib/IO/XDMF/Xdmf3Writer.cpp
deleted file mode 100644
index 91556c378c9..00000000000
--- a/MeshLib/IO/XDMF/Xdmf3Writer.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * \file
- * \copyright
- * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
- *            Distributed under a Modified BSD License.
- *              See accompanying file LICENSE.txt or
- *              http://www.opengeosys.org/project/license
- */
-
-#include "Xdmf3Writer.h"
-
-#include <Xdmf.hpp>
-#include <XdmfAttribute.hpp>
-#include <XdmfDomain.hpp>
-#include <XdmfGeometryType.hpp>
-#include <XdmfGridCollection.hpp>
-#include <XdmfGridCollectionType.hpp>
-#include <XdmfHDF5Controller.hpp>
-#include <XdmfHeavyDataDescription.hpp>
-#include <XdmfInformation.hpp>
-#include <XdmfTopologyType.hpp>
-#include <XdmfUnstructuredGrid.hpp>
-#include <XdmfWriter.hpp>
-#include <string>
-
-#include "InfoLib/GitInfo.h"
-
-using namespace MeshLib::IO;
-using namespace std::string_literals;
-
-boost::shared_ptr<const XdmfAttributeCenter> elemTypeOGS2XDMF(
-    MeshLib::MeshItemType const elem_type)
-{
-    std::map<MeshLib::MeshItemType,
-             boost::shared_ptr<const XdmfAttributeCenter>>
-        mesh_item_type_ogs2xdmf = {
-            {MeshLib::MeshItemType::Cell, XdmfAttributeCenter::Cell()},
-            {MeshLib::MeshItemType::Edge, XdmfAttributeCenter::Edge()},
-            {MeshLib::MeshItemType::Face, XdmfAttributeCenter::Face()},
-            {MeshLib::MeshItemType::Node, XdmfAttributeCenter::Node()},
-            {MeshLib::MeshItemType::IntegrationPoint,
-             XdmfAttributeCenter::Other()}};
-
-    return mesh_item_type_ogs2xdmf.at(elem_type);
-}
-
-static std::string getDataSection(std::string const& name)
-{
-    return "data/"s + name;
-}
-
-static std::vector<XdmfDimType> prependDimension(
-    XdmfDimType const prepend_value, std::vector<XdmfDimType> const& dimensions)
-{
-    std::vector<XdmfDimType> dims = {prepend_value};
-    dims.insert(dims.end(), dimensions.begin(), dimensions.end());
-    return dims;
-}
-
-static boost::shared_ptr<XdmfGeometry> getLightGeometry(
-    std::string const& hdf5filename, XdmfData const& geometry)
-{
-    auto xdmf_geometry = XdmfGeometry::New();
-    xdmf_geometry->setType(XdmfGeometryType::XYZ());
-    boost::shared_ptr<XdmfHDF5Controller> geometry_controller =
-        XdmfHDF5Controller::New(hdf5filename,
-                                getDataSection("geometry"),
-                                XdmfArrayType::Float64(),
-                                geometry.starts,
-                                geometry.strides,
-                                geometry.global_block_dims,
-                                geometry.global_block_dims);
-    xdmf_geometry->setHeavyDataController(geometry_controller);
-    return xdmf_geometry;
-}
-
-static boost::shared_ptr<XdmfTopology> getLightTopology(
-    std::string const& hdf5filename, XdmfData const& topology)
-{
-    auto xdmf_topology = XdmfTopology::New();
-    xdmf_topology->setType(XdmfTopologyType::Mixed());
-    auto topology_controller =
-        XdmfHDF5Controller::New(hdf5filename,
-                                getDataSection("topology"),
-                                XdmfArrayType::Int32(),
-                                topology.starts,
-                                topology.strides,
-                                topology.global_block_dims,
-                                topology.global_block_dims);
-    xdmf_topology->setHeavyDataController(topology_controller);
-    return xdmf_topology;
-}
-
-static boost::shared_ptr<XdmfAttribute> getLightAttribute(
-    std::string const& hdf5filename, int const step, XdmfData const& attribute)
-{
-    std::vector<XdmfDimType> starts = prependDimension(step, attribute.starts);
-    std::vector<XdmfDimType> strides = prependDimension(1, attribute.strides);
-    std::vector<XdmfDimType> global_block_dims =
-        prependDimension(1, attribute.global_block_dims);
-    std::vector<XdmfDimType> all_global_block_dims =
-        prependDimension(step + 1, attribute.global_block_dims);
-
-    auto const attribute_controller =
-        XdmfHDF5Controller::New(hdf5filename,
-                                getDataSection(attribute.name),
-                                attribute.data_type,
-                                starts,
-                                strides,
-                                global_block_dims,
-                                all_global_block_dims);
-
-    auto const xdmf_attribute = XdmfAttribute::New();
-    auto const center = elemTypeOGS2XDMF(*(attribute.attribute_center));
-    xdmf_attribute->setCenter(center);
-    xdmf_attribute->setName(attribute.name);
-    xdmf_attribute->setHeavyDataController(attribute_controller);
-    return xdmf_attribute;
-}
-
-namespace MeshLib::IO
-{
-Xdmf3Writer::Xdmf3Writer(XdmfData const& geometry, XdmfData const& topology,
-                         std::vector<XdmfData> constant_attributes,
-                         std::vector<XdmfData> variable_attributes,
-                         std::filesystem::path const& filepath,
-                         int const time_step)
-    : _variable_attributes(std::move(variable_attributes)),
-      _hdf5filename(filepath.stem().string() + ".h5")
-{
-    _initial_geometry = getLightGeometry(_hdf5filename, geometry);
-    _initial_topology = getLightTopology(_hdf5filename, topology);
-
-    std::transform(
-        constant_attributes.begin(), constant_attributes.end(),
-        std::back_inserter(_constant_attributes),
-        [&](XdmfData const& attribute) -> boost::shared_ptr<XdmfAttribute> {
-            return getLightAttribute(_hdf5filename, time_step, attribute);
-        });
-
-    _writer = XdmfWriter::New(filepath.string());
-    _writer->setMode(XdmfWriter::DistributedHeavyData);
-
-    auto version = XdmfInformation::New();
-    version->setKey(GitInfoLib::GitInfo::OGS_VERSION);
-    version->setValue(GitInfoLib::GitInfo::ogs_version);
-
-    auto grid_collection = XdmfGridCollection::New();
-    grid_collection->setType(XdmfGridCollectionType::Temporal());
-
-    _root = XdmfDomain::New();
-    _root->insert(version);
-    _root->insert(grid_collection);
-}
-
-Xdmf3Writer::~Xdmf3Writer()
-{
-    _root->accept(_writer);
-}
-
-void Xdmf3Writer::writeStep(int const time_step, double const time)
-{
-    auto grid = XdmfUnstructuredGrid::New();
-    grid->setGeometry(_initial_geometry);
-    grid->setTopology(_initial_topology);
-
-    for (auto const& constant_attribute : _constant_attributes)
-    {
-        grid->insert(constant_attribute);
-    }
-
-    grid->setTime(XdmfTime::New(time));
-
-    for (auto const& attribute : _variable_attributes)
-    {
-        grid->insert(getLightAttribute(_hdf5filename, time_step, attribute));
-    }
-
-    auto grid_collection = _root->getGridCollection(0);
-    grid_collection->insert(grid);
-}
-}  // namespace MeshLib::IO
diff --git a/MeshLib/IO/XDMF/Xdmf3Writer.h b/MeshLib/IO/XDMF/Xdmf3Writer.h
deleted file mode 100644
index 5489609d5fc..00000000000
--- a/MeshLib/IO/XDMF/Xdmf3Writer.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * \file
- * \author Tobias Meisel
- * \date   2020-11-13
- * \brief  XdmfWriter which takes contiguous data and writes 1 xdmf + 1 hdf file
- * \copyright
- * Copyright (c) 2012-2021, 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 <filesystem.h>
-
-#include <boost/shared_ptr.hpp>
-
-#include "MeshLib/Mesh.h"
-#include "XdmfData.h"
-
-class XdmfAttribute;
-class XdmfGridCollection;
-class XdmfTopology;
-class XdmfGeometry;
-class XdmfWriter;
-class XdmfDomain;
-
-namespace MeshLib::IO
-{
-struct Geometry;
-struct Topology;
-}  // namespace MeshLib::IO
-
-namespace MeshLib::IO
-{
-class Xdmf3Writer final
-{
-public:
-    /**
-     * \brief Write xdmf and h5 file with geometry and topology data.
-     * The data itself is held by a structure outside of this class.
-     * The writer assumes a constant data holder (data itself can change, memory
-     * address is the same)
-     * @param geometry contains meta data to coordinates
-     * @param topology contains meta data cells
-     * @param constant_attributes vector of constant attributes (each attribute
-     * is a OGS mesh property)
-     * @param variable_attributes vector of variable attributes (each attribute
-     * is a OGS mesh property
-     * @param filepath absolute or relative filepath to the hdf5 file
-     * @param time_step number of the step (temporal collection)
-     */
-    Xdmf3Writer(XdmfData const& geometry, XdmfData const& topology,
-                std::vector<XdmfData> constant_attributes,
-                std::vector<XdmfData> variable_attributes,
-                std::filesystem::path const& filepath, int time_step);
-    /**
-     * \brief Write attribute data that has modified to previous time step or
-     * initial
-     * @param time_step number of the step (temporal collection)
-     * @param time time value of the current time_step
-     */
-    void writeStep(int time_step, double time);
-    ~Xdmf3Writer();
-
-private:
-    boost::shared_ptr<XdmfGridCollection> _gridCollection;
-    boost::shared_ptr<XdmfTopology> _initial_topology;
-    boost::shared_ptr<XdmfGeometry> _initial_geometry;
-    std::vector<boost::shared_ptr<XdmfAttribute>> _constant_attributes;
-    std::vector<XdmfData> const _variable_attributes;
-    boost::shared_ptr<XdmfWriter> _writer;
-    boost::shared_ptr<XdmfDomain> _root;
-    std::string const _hdf5filename;
-};
-}  // namespace MeshLib::IO
diff --git a/MeshLib/IO/XDMF/XdmfData.cpp b/MeshLib/IO/XDMF/XdmfData.cpp
index a2e0462e48e..2aa9bf64cb2 100644
--- a/MeshLib/IO/XDMF/XdmfData.cpp
+++ b/MeshLib/IO/XDMF/XdmfData.cpp
@@ -9,9 +9,6 @@
 
 #include "XdmfData.h"
 
-#include <XdmfArrayType.hpp>
-#include <XdmfAttributeCenter.hpp>
-#include <XdmfTopologyType.hpp>
 #include <cassert>
 #include <map>
 
@@ -20,38 +17,13 @@
 #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 const 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)
+                   std::optional<MeshLib::MeshItemType> const attribute_center,
+                   unsigned int const index)
     : starts([&size_tuple]() {
           if (size_tuple > 1)
           {
@@ -65,15 +37,17 @@ XdmfData::XdmfData(std::size_t const size_partitioned_dim,
       strides([&size_tuple]() {
           if (size_tuple > 1)
           {
-              return std::vector<XdmfDimType>{1};
+              return std::vector<XdmfDimType>{1, 1};
           }
           else
           {
-              return std::vector<XdmfDimType>{1, 1};
+              return std::vector<XdmfDimType>{1};
           }
       }()),
+      data_type(mesh_property_data_type),
       name(name),
-      attribute_center(attribute_center)
+      attribute_center(attribute_center),
+      index(index)
 {
     auto partition_info = getPartitionInfo(size_partitioned_dim);
     // TODO (tm) XdmfLib does not support 64 bit data types so far
@@ -92,7 +66,6 @@ XdmfData::XdmfData(std::size_t const size_partitioned_dim,
         global_block_dims = {ui_global_components, ui_tuple_size};
     }
 
-    data_type = MeshPropertyDataType2XdmfType(mesh_property_data_type);
     DBUG(
         "XDMF: dataset name: {:s}, offset: {:d} "
         "global_blocks: {:d}, tuples: {:d}",
diff --git a/MeshLib/IO/XDMF/XdmfData.h b/MeshLib/IO/XDMF/XdmfData.h
index 959e7d1536b..b6a826eeed8 100644
--- a/MeshLib/IO/XDMF/XdmfData.h
+++ b/MeshLib/IO/XDMF/XdmfData.h
@@ -26,7 +26,7 @@ namespace MeshLib::IO
 {
 using XdmfDimType = unsigned int;
 
-struct XdmfData
+struct XdmfData final
 {
     /**
      * \brief XdmfData contains meta data to be passed to the XdmfWriter - it
@@ -43,19 +43,25 @@ struct XdmfData
      * @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
+     * @param index The position of the DataItem parents in a grid
+     * (representing a single step). Convention is: 1=Time, 2=
+     * Geometry, 3=Topology, 4>=Attribute
+     *
      */
     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);
+             std::optional<MeshLib::MeshItemType> attribute_center,
+             unsigned int const index);
     // 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> global_block_dims;
-    boost::shared_ptr<const XdmfArrayType> data_type;
+    MeshPropertyDataType const data_type;
     std::string const name;
     std::optional<MeshLib::MeshItemType> const attribute_center;
+    unsigned int index;
 };
 
 }  // namespace MeshLib::IO
diff --git a/MeshLib/IO/XDMF/XdmfHdfWriter.cpp b/MeshLib/IO/XDMF/XdmfHdfWriter.cpp
index a33354b118f..7ec87403806 100644
--- a/MeshLib/IO/XDMF/XdmfHdfWriter.cpp
+++ b/MeshLib/IO/XDMF/XdmfHdfWriter.cpp
@@ -12,16 +12,17 @@
 #include <algorithm>
 #include <functional>
 
+#include "InfoLib/GitInfo.h"
 #include "partition.h"
 #include "transformData.h"
+#include "writeXdmf.h"
 
 namespace MeshLib::IO
 {
 XdmfHdfWriter::XdmfHdfWriter(MeshLib::Mesh const& mesh,
                              std::filesystem::path const& filepath,
-                             int const time_step,
-                             std::set<std::string>
-                                 variable_output_names,
+                             int const time_step, double const initial_time,
+                             std::set<std::string> const& variable_output_names,
                              bool const use_compression)
 {
     // transform Data into contiguous data and collect meta data
@@ -87,7 +88,13 @@ XdmfHdfWriter::XdmfHdfWriter(MeshLib::Mesh const& mesh,
     std::vector<XdmfData> xdmf_attributes;
     std::transform(attributes.begin(), attributes.end(),
                    std::back_inserter(xdmf_attributes),
-                   [](AttributeMeta att) -> XdmfData { return att.xdmf; });
+                   [&attributes](AttributeMeta& att) -> XdmfData {
+                       size_t const i = &att - &attributes.front();
+                       // index 1 geo, index 2 topology, attributes start at
+                       // index 3
+                       att.xdmf.index = i + 4;
+                       return att.xdmf;
+                   });
 
     std::function<bool(XdmfData)> is_variable_xdmf_attribute =
         [&variable_output_names](XdmfData data) -> bool {
@@ -100,28 +107,33 @@ XdmfHdfWriter::XdmfHdfWriter(MeshLib::Mesh const& mesh,
     std::copy_if(xdmf_attributes.begin(), xdmf_attributes.end(),
                  back_inserter(xdmf_variable_attributes),
                  is_variable_xdmf_attribute);
-
     std::vector<XdmfData> xdmf_constant_attributes;
     std::copy_if(xdmf_attributes.begin(), xdmf_attributes.end(),
                  back_inserter(xdmf_constant_attributes),
                  std::not_fn(is_variable_xdmf_attribute));
 
-    _xdmf_writer = std::make_unique<Xdmf3Writer>(
-        geometry.xdmf, topology.xdmf, std::move(xdmf_constant_attributes),
-        std::move(xdmf_variable_attributes), xdmf_filepath, time_step);
+    if (isFileManager())
+    {
+        auto xdmf_writer_fn =
+            write_xdmf(geometry.xdmf, topology.xdmf, xdmf_constant_attributes,
+                       xdmf_variable_attributes, hdf_filepath.string(),
+                       GitInfoLib::GitInfo::ogs_version);
+        _xdmf_writer = std::make_unique<XdmfWriter>(xdmf_filepath.string(),
+                                                    xdmf_writer_fn);
+        _xdmf_writer->addTimeStep(initial_time);
+    }
 }
 
-void XdmfHdfWriter::writeStep(int const time_step, double const time) const
+void XdmfHdfWriter::writeStep([[maybe_unused]] int const& time_step,
+                              double const& time)
 {
-    _hdf_writer->writeStep(time_step);
-
-    // XDMF
+    // ToDo (tm) time_step will be used for simulation continuation (restart)
+    _hdf_writer->writeStep();
     // The light data is only written by just one process
-    if (!_xdmf_writer)
+    if (isFileManager())
     {
-        return;
+        _xdmf_writer->addTimeStep(time);
     }
-    _xdmf_writer->writeStep(time_step, time);
 }
 
 }  // namespace MeshLib::IO
diff --git a/MeshLib/IO/XDMF/XdmfHdfWriter.h b/MeshLib/IO/XDMF/XdmfHdfWriter.h
index 311821c098b..d4301f0b7ab 100644
--- a/MeshLib/IO/XDMF/XdmfHdfWriter.h
+++ b/MeshLib/IO/XDMF/XdmfHdfWriter.h
@@ -19,7 +19,7 @@
 
 #include "HdfWriter.h"
 #include "MeshLib/Mesh.h"
-#include "Xdmf3Writer.h"
+#include "XdmfWriter.h"
 
 namespace MeshLib::IO
 {
@@ -31,6 +31,7 @@ public:
      * @param mesh Mesh or NodePartitionedMesh to be written to file(s)
      * @param filepath absolute or relative filepath to the hdf5 file
      * @param time_step number of the step (temporal collection)
+     * @param initial_time time in seconds of the first time step
      * @param variable_output_names names of all process variables (attributes)
      * that change over time
      * @param use_compression if true, zlib compression in HDFWriter component
@@ -38,19 +39,20 @@ public:
      */
     XdmfHdfWriter(MeshLib::Mesh const& mesh,
                   std::filesystem::path const& filepath, int time_step,
-                  std::set<std::string> variable_output_names,
+                  double initial_time,
+                  std::set<std::string> const& variable_output_names,
                   bool use_compression);
+
     /**
-     * \brief Write attribute data that has modified to previous time step or
-     * initial
+     * \brief Adds data for either lazy (xdmf) or eager (hdf) writing algorithm
      * @param time_step number of the step (temporal collection)
      * @param time time value of the current time_step
      */
-    void writeStep(int time_step, double time) const;
+    void writeStep(int const& time_step, double const& time);
 
 private:
     // hdf_writer must be destructed before xdmf_writer
-    std::unique_ptr<Xdmf3Writer> _xdmf_writer;
     std::unique_ptr<HdfWriter> _hdf_writer;
+    std::unique_ptr<XdmfWriter> _xdmf_writer;
 };
 }  // namespace MeshLib::IO
\ No newline at end of file
diff --git a/MeshLib/IO/XDMF/transformData.cpp b/MeshLib/IO/XDMF/transformData.cpp
index 10244d1bb93..33ac0e59859 100644
--- a/MeshLib/IO/XDMF/transformData.cpp
+++ b/MeshLib/IO/XDMF/transformData.cpp
@@ -11,11 +11,13 @@
 
 #include "transformData.h"
 
-#include <XdmfTopologyType.hpp>
 #include <algorithm>
+#include <array>
 #include <optional>
 #include <string>
 
+
+#include "BaseLib/cpp23.h"
 #include "InfoLib/GitInfo.h"
 #include "MeshLib/Elements/Element.h"
 #include "MeshLib/Mesh.h"
@@ -24,37 +26,47 @@
 #include "MeshPropertyDataType.h"
 #include "partition.h"
 
+
+using namespace BaseLib;
 namespace MeshLib::IO
 {
-// \TODO (tm) constexpr by other function signature can not be transformed to
-// constexpr shared_ptr is not literal type / has non trivial destructor
-boost::shared_ptr<const XdmfTopologyType> cellTypeOGS2XDMF(
-    MeshLib::CellType const cell_type)
+struct XdmfTopology
+{
+    // https://www.xdmf.org/index.php/XDMF_Model_and_Format#Topology, Section
+    // Arbitrary
+    unsigned int id;
+    unsigned int number_of_nodes;
+};
+
+constexpr auto elemOGSTypeToXDMFType()
+{
+    std::array<XdmfTopology, to_underlying(MeshLib::CellType::enum_length)> elem_type{};
+    elem_type[to_underlying(MeshLib::CellType::POINT1)] = {0x1, 1};
+    elem_type[to_underlying(MeshLib::CellType::LINE2)] = {0x2, 2};
+    elem_type[to_underlying(MeshLib::CellType::LINE3)] = {0x2, 3};
+    elem_type[to_underlying(MeshLib::CellType::TRI3)] = {0x4, 3};
+    elem_type[to_underlying(MeshLib::CellType::TRI6)] = {0x24, 6};
+    elem_type[to_underlying(MeshLib::CellType::QUAD4)] = {0x5, 4};
+    elem_type[to_underlying(MeshLib::CellType::QUAD8)] = {0x25, 8};
+    elem_type[to_underlying(MeshLib::CellType::QUAD9)] = {0x23, 9};
+    elem_type[to_underlying(MeshLib::CellType::TET4)] = {0x6, 4};
+    elem_type[to_underlying(MeshLib::CellType::TET10)] = {0x26, 10};
+    elem_type[to_underlying(MeshLib::CellType::HEX8)] = {0x9, 8};
+    elem_type[to_underlying(MeshLib::CellType::HEX20)] = {0x30, 20};
+    elem_type[to_underlying(MeshLib::CellType::HEX27)] = {0x32, 27};
+    elem_type[to_underlying(MeshLib::CellType::PRISM6)] = {
+        0x8, 6};  // parallel triangle wedge
+    elem_type[to_underlying(MeshLib::CellType::PRISM15)] = {0x28, 15};
+    elem_type[to_underlying(MeshLib::CellType::PRISM18)] = {0x29, 18};
+    elem_type[to_underlying(MeshLib::CellType::PYRAMID5)] = {0x7, 5};
+    elem_type[to_underlying(MeshLib::CellType::PYRAMID13)] = {0x27, 13};
+    return elem_type;
+}
+
+auto cellTypeOGS2XDMF(MeshLib::CellType const& cell_type)
 {
-    static std::map<MeshLib::CellType const,
-                    boost::shared_ptr<const XdmfTopologyType> const>
-        elem_type_ogs2xdmf = {
-            {MeshLib::CellType::POINT1, XdmfTopologyType::Polyvertex()},
-            {MeshLib::CellType::LINE2, XdmfTopologyType::Polyline(2)},
-            {MeshLib::CellType::LINE3, XdmfTopologyType::Polyline(3)},
-            {MeshLib::CellType::QUAD4, XdmfTopologyType::Quadrilateral()},
-            {MeshLib::CellType::QUAD8, XdmfTopologyType::Quadrilateral_8()},
-            {MeshLib::CellType::QUAD9, XdmfTopologyType::Quadrilateral_9()},
-            {MeshLib::CellType::TET4, XdmfTopologyType::Tetrahedron()},
-            {MeshLib::CellType::TET10, XdmfTopologyType::Tetrahedron_10()},
-            {MeshLib::CellType::TRI3, XdmfTopologyType::Triangle()},
-            {MeshLib::CellType::TRI6, XdmfTopologyType::Triangle_6()},
-            {MeshLib::CellType::PRISM6,
-             XdmfTopologyType::Wedge()},  // parallel triangle wedge
-            {MeshLib::CellType::PRISM15, XdmfTopologyType::Wedge_15()},
-            {MeshLib::CellType::PRISM18, XdmfTopologyType::Wedge_18()},
-            {MeshLib::CellType::PYRAMID13, XdmfTopologyType::Pyramid_13()},
-            {MeshLib::CellType::PYRAMID5, XdmfTopologyType::Pyramid()},
-            {MeshLib::CellType::HEX20, XdmfTopologyType::Hexahedron_20()},
-            {MeshLib::CellType::HEX27, XdmfTopologyType::Hexahedron_27()},
-            {MeshLib::CellType::HEX8, XdmfTopologyType::Hexahedron()}};
-
-    return elem_type_ogs2xdmf.at(cell_type);
+    constexpr auto elem_type_ogs2xdmf = elemOGSTypeToXDMFType();
+    return elem_type_ogs2xdmf[to_underlying(cell_type)];
 }
 
 std::optional<AttributeMeta> transformAttribute(
@@ -106,33 +118,31 @@ std::optional<AttributeMeta> transformAttribute(
                           "Signed int has 32-1 bits");
             data_type = MeshPropertyDataType::int32;
         }
-        // \TODO (tm) Reimplement size checks
+        // ToDo (tm) These tests are platform specific and currently fail on Windows
         // else if constexpr (std::is_same_v<long, decltype(basic_type)>)
-        // {
-        //     static_assert((std::numeric_limits<long>::digits == 63),
-        //                   "Signed int has 64-1 bits");
-        //     data_type = XdmfArrayType::Int64();
-        // }
+        //{
+        //    static_assert((std::numeric_limits<long>::digits == 63),
+        //                  "Signed int has 64-1 bits");
+        //    data_type = MeshPropertyDataType::int64;
+        //}
+        // else if constexpr (std::is_same_v<unsigned long,
+        // decltype(basic_type)>)
+        //{
+        //    static_assert((std::numeric_limits<unsigned long>::digits == 64),
+        //                  "Unsigned long has 64 bits");
+        //    data_type = MeshPropertyDataType::uint64;
+        //}
         else if constexpr (std::is_same_v<unsigned int, decltype(basic_type)>)
         {
             static_assert((std::numeric_limits<unsigned int>::digits == 32),
                           "Unsigned int has 32 bits");
             data_type = MeshPropertyDataType::uint32;
         }
-        // else if constexpr (std::is_same_v<unsigned long,
-        // decltype(basic_type)>)
-        // {
-        //     static_assert((std::numeric_limits<unsigned long>::digits == 64),
-        //                   "Unsigned long has 64 bits");
-        //     // \TODO (tm) Extend XdmfLibrary with 64bit data types
-        //     data_type = XdmfArrayType::UInt32();
-        // }
         else if constexpr (std::is_same_v<std::size_t, decltype(basic_type)>)
         {
             static_assert((std::numeric_limits<std::size_t>::digits == 64),
                           "size_t has 64 bits");
-            // \TODO (tm) Extend XdmfLibrary with 64bit data types
-            data_type = MeshPropertyDataType::uint32;
+            data_type = MeshPropertyDataType::uint64;
         }
         else if constexpr (std::is_same_v<char, decltype(basic_type)>)
         {
@@ -182,7 +192,7 @@ std::optional<AttributeMeta> transformAttribute(
         HdfData(data_ptr, num_of_tuples, ui_global_components, name, data_type);
 
     XdmfData xdmf = XdmfData(num_of_tuples, ui_global_components, data_type,
-                             name, mesh_item_type);
+                             name, mesh_item_type, 0);
 
     return AttributeMeta{std::move(hdf), std::move(xdmf)};
 }
@@ -234,11 +244,9 @@ Geometry transformGeometry(MeshLib::Mesh const& mesh)
                           point_size,
                           name,
                           MeshPropertyDataType::float64);
-    XdmfData xdmf = XdmfData(partition_dim,
-                             point_size,
-                             MeshPropertyDataType::float64,
-                             name,
-                             std::nullopt);
+    XdmfData xdmf =
+        XdmfData(partition_dim, point_size, MeshPropertyDataType::float64, name,
+                 std::nullopt, 2);
 
     return Geometry{std::move(values), std::move(hdf), std::move(xdmf)};
 }
@@ -247,18 +255,18 @@ Topology transformTopology(MeshLib::Mesh const& mesh, std::size_t const offset)
 {
     std::string const name = "topology";
     std::vector<MeshLib::Element*> const& elements = mesh.getElements();
-    // \TODO (tm) Precalculate exact size
     std::vector<int> values;
     values.reserve(elements.size());
 
     for (auto const& cell : elements)
     {
-        auto const cell_type = cellTypeOGS2XDMF(cell->getCellType());
-        auto const cell_type_id = cell_type->getID();
-        values.push_back(cell_type_id);
-        if (cell_type_id == 2 || cell_type_id == 3)
+        auto const ogs_cell_type = cell->getCellType();
+        auto const xdmf_cell_id = cellTypeOGS2XDMF(ogs_cell_type).id;
+        values.push_back(xdmf_cell_id);
+        if (ogs_cell_type == MeshLib::CellType::LINE2 ||
+            ogs_cell_type == MeshLib::CellType::LINE3)
         {
-            values.push_back(cell_type->getNodesPerElement());
+            values.push_back(cellTypeOGS2XDMF(ogs_cell_type).number_of_nodes);
         }
 
         for (std::size_t i = 0; i < cell->getNumberOfNodes(); ++i)
@@ -271,7 +279,7 @@ Topology transformTopology(MeshLib::Mesh const& mesh, std::size_t const offset)
     HdfData hdf = HdfData(values.data(), values.size(), 1, name,
                           MeshPropertyDataType::int32);
     XdmfData xdmf = XdmfData(values.size(), 1, MeshPropertyDataType::int32,
-                             name, std::nullopt);
+                             name, std::nullopt, 3);
 
     return Topology{std::move(values), std::move(hdf), std::move(xdmf)};
 }
diff --git a/MeshLib/IO/writeMeshToFile.cpp b/MeshLib/IO/writeMeshToFile.cpp
index 81d9eb6d839..53fab4f321c 100644
--- a/MeshLib/IO/writeMeshToFile.cpp
+++ b/MeshLib/IO/writeMeshToFile.cpp
@@ -48,9 +48,8 @@ int writeMeshToFile(const MeshLib::Mesh& mesh,
 #ifdef OGS_USE_XDMF
     if (file_path.extension().string() == ".xdmf")
     {
-        MeshLib::IO::XdmfHdfWriter(
-            mesh, file_path, 0, variable_output_names, true);
-
+        MeshLib::IO::XdmfHdfWriter(mesh, file_path, 0, 0.0,
+                                   variable_output_names, true);
         return 0;
     }
 #endif
@@ -58,5 +57,4 @@ int writeMeshToFile(const MeshLib::Mesh& mesh,
         file_path.string());
     return -1;
 }
-
 }  // namespace MeshLib::IO
diff --git a/MeshLib/MeshEnums.h b/MeshLib/MeshEnums.h
index 9a137657584..658b9d93faa 100644
--- a/MeshLib/MeshEnums.h
+++ b/MeshLib/MeshEnums.h
@@ -59,7 +59,8 @@ enum class CellType
     PRISM15 = 15,
     PRISM18 = 16,
     PYRAMID5 = 17,
-    PYRAMID13 = 18
+    PYRAMID13 = 18,
+    enum_length
 };
 
 /**
diff --git a/ProcessLib/Output/Output.cpp b/ProcessLib/Output/Output.cpp
index 790bae18b58..cc2ac5b9ec4 100644
--- a/ProcessLib/Output/Output.cpp
+++ b/ProcessLib/Output/Output.cpp
@@ -245,7 +245,7 @@ void Output::outputMeshXdmf(OutputFile const& output_file,
         std::filesystem::path path(output_file.path);
         _mesh_xdmf_hdf_writer = std::make_unique<MeshLib::IO::XdmfHdfWriter>(
         MeshLib::IO::XdmfHdfWriter(
-                mesh, path, timestep,
+                mesh, path, timestep, t,
                 _output_data_specification.output_variables, output_file.compression));
     }
     _mesh_xdmf_hdf_writer->writeStep(timestep, t);
-- 
GitLab