From a8e58b4869c8f18b7bedfe78d000279b17bada48 Mon Sep 17 00:00:00 2001
From: guj <jgu@lbl.gov>
Date: Mon, 10 Apr 2017 09:31:36 -0700
Subject: [PATCH] setting up for hdf5

---
 cmake/FindPHDF5.cmake              |  59 +++++
 include/engine/hdf5/HDF5ReaderP.h  |   4 +
 include/engine/hdf5/HDF5WriterP.h  | 224 +++++++++++++++++
 source/engine/hdf5/HDF5ReaderP.cpp |  11 +
 source/engine/hdf5/HDF5WriterP.cpp | 374 +++++++++++++++++++++++++++++
 5 files changed, 672 insertions(+)
 create mode 100644 cmake/FindPHDF5.cmake
 create mode 100644 include/engine/hdf5/HDF5ReaderP.h
 create mode 100644 include/engine/hdf5/HDF5WriterP.h
 create mode 100644 source/engine/hdf5/HDF5ReaderP.cpp
 create mode 100644 source/engine/hdf5/HDF5WriterP.cpp

diff --git a/cmake/FindPHDF5.cmake b/cmake/FindPHDF5.cmake
new file mode 100644
index 000000000..e357e7279
--- /dev/null
+++ b/cmake/FindPHDF5.cmake
@@ -0,0 +1,59 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+#
+# FindPHDF5
+# ---------
+#
+
+
+if(NOT PHDF5_FOUND)
+  if((NOT HDF5_DIR) AND (NOT (ENV{HDF5_DIR} STREQUAL "")))
+    set(HDF5_DIR "$ENV{HDF5_DIR}")
+  endif()
+
+  # Search for the core libraries
+  if(HDF5_DIR)
+    # If a root directory is specified, then don't look anywhere else 
+    find_path(PHDF5_INCLUDE_DIR hdf5.h
+      HINTS ${HDF5_DIR}/include
+      NO_DEFAULT_PATHS
+    )
+    set(_PHDF5_LIBRARY_HINT HINTS ${HDF5_DIR}/lib NO_DEFAULT_PATHS)
+  else()
+    # Otherwise use the include dir as a basis to search for the lib
+    find_path(PHDF5_INCLUDE_DIR hdf5.h)
+    if(PHDF5_INCLUDE_DIR)
+      get_filename_component(_PHDF5_PREFIX "${PHDF5_INCLUDE_DIR}" PATH)
+      set(_PHDF5_LIBRARY_HINT HINTS ${_PHDF5_PREFIX}/lib)
+      unset(_PHDF5_PREFIX)
+    endif()
+  endif()
+  find_library(PHDF5_LIBRARY hdf5 ${_PHDF5_LIBRARY_HINT})
+  unset(_PHDF5_LIBRARY_HINT)
+
+
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(PHDF5  DEFAULT_MSG  PHDF5_LIBRARY PHDF5_INCLUDE_DIR)
+
+  find_package_handle_standard_args(PHDF5
+    FOUND_VAR PHDF5_FOUND
+    REQUIRED_VARS
+      PHDF5_INCLUDE_DIR
+      PHDF5_LIBRARY
+  )
+
+  MESSAGE(STATUS "PHDF5_FOUND: " ${PHDF5_FOUND} "HDF5_DIR: " ${HDF5_DIR} "TARGET=" ${TARGET} )
+  if(PHDF5_FOUND)
+    set(PHDF5_INCLUDE_DIRS ${PHDF5_INCLUDE_DIR})
+    set(PHDF5_LIBRARIES ${PHDF5_LIBRARY})
+    if(PHDF5_FOUND AND NOT TARGET PHDF5::PHDF5)
+      add_library(PHDF5::PHDF5 UNKNOWN IMPORTED)
+      set_target_properties(PHDF5::PHDF5 PROPERTIES
+        IMPORTED_LOCATION "${PHDF5_LIBRARY}"
+        INTERFACE_INCLUDE_DIRECTORIES "${PHDF5_INCLUDE_DIR}"
+      )
+    endif()
+  endif()
+endif()
diff --git a/include/engine/hdf5/HDF5ReaderP.h b/include/engine/hdf5/HDF5ReaderP.h
new file mode 100644
index 000000000..28d688208
--- /dev/null
+++ b/include/engine/hdf5/HDF5ReaderP.h
@@ -0,0 +1,4 @@
+#ifndef HDF5_READER_P_H
+#define HDF5_READER_P_H
+
+#endif
diff --git a/include/engine/hdf5/HDF5WriterP.h b/include/engine/hdf5/HDF5WriterP.h
new file mode 100644
index 000000000..27d5e8d10
--- /dev/null
+++ b/include/engine/hdf5/HDF5WriterP.h
@@ -0,0 +1,224 @@
+/*
+ * HDF5WriterP.h
+ *
+ *  Created on: March 20, 2017
+ *      Author: Junmin
+ */
+
+#ifndef HDF5_WRITER_P_H_
+#define HDF5_WRITER_P_H_
+
+#include <iostream> //std::cout must be removed, only used for hello example
+#include <unistd.h> //sleep must be removed
+
+#include "core/Engine.h"
+#include "format/BP1Writer.h"
+
+// supported capsules
+#include "capsule/heap/STLVector.h"
+
+#include "ADIOS_MPI.h"
+
+#include "hdf5.h"
+
+namespace adios {
+
+typedef struct {
+  double _re; /*real part*/
+  double _im; /*imaginary part*/
+} ADIOS2_Complex_Double;
+
+typedef struct {
+  float _re; // real
+  float _im; // imaginary part
+} ADIOS2_Complex_Float;
+
+// using ADIOS2_Complex_Float = std::complex<float>;
+
+typedef struct {
+  long double _re; /*real part*/
+  long double _im; /*imaginary part*/
+} ADIOS2_Complex_LongDouble;
+
+class HDF5Writer : public Engine {
+
+public:
+  /**
+   * Constructor for single BP capsule engine, writes in BP format into a single
+   * heap capsule
+   * @param name unique name given to the engine
+   * @param accessMode
+   * @param mpiComm
+   * @param method
+   * @param debugMode
+   */
+
+  HDF5Writer(ADIOS &adios, const std::string name, const std::string accessMode,
+             MPI_Comm mpiComm, const Method &method,
+             const bool debugMode = false, const unsigned int cores = 1);
+
+  ~HDF5Writer();
+
+  void Write(Variable<char> &variable, const char *values);
+  void Write(Variable<unsigned char> &variable, const unsigned char *values);
+  void Write(Variable<short> &variable, const short *values);
+  void Write(Variable<unsigned short> &variable, const unsigned short *values);
+  void Write(Variable<int> &variable, const int *values);
+  void Write(Variable<unsigned int> &variable, const unsigned int *values);
+  void Write(Variable<long int> &variable, const long int *values);
+  void Write(Variable<unsigned long int> &variable,
+             const unsigned long int *values);
+  void Write(Variable<long long int> &variable, const long long int *values);
+  void Write(Variable<unsigned long long int> &variable,
+             const unsigned long long int *values);
+  void Write(Variable<float> &variable, const float *values);
+  void Write(Variable<double> &variable, const double *values);
+  void Write(Variable<long double> &variable, const long double *values);
+  void Write(Variable<std::complex<float>> &variable,
+             const std::complex<float> *values);
+  void Write(Variable<std::complex<double>> &variable,
+             const std::complex<double> *values);
+  void Write(Variable<std::complex<long double>> &variable,
+             const std::complex<long double> *values);
+
+  void Write(const std::string variableName, const char *values);
+  void Write(const std::string variableName, const unsigned char *values);
+  void Write(const std::string variableName, const short *values);
+  void Write(const std::string variableName, const unsigned short *values);
+  void Write(const std::string variableName, const int *values);
+  void Write(const std::string variableName, const unsigned int *values);
+  void Write(const std::string variableName, const long int *values);
+  void Write(const std::string variableName, const unsigned long int *values);
+  void Write(const std::string variableName, const long long int *values);
+  void Write(const std::string variableName,
+             const unsigned long long int *values);
+  void Write(const std::string variableName, const float *values);
+  void Write(const std::string variableName, const double *values);
+  void Write(const std::string variableName, const long double *values);
+  void Write(const std::string variableName, const std::complex<float> *values);
+  void Write(const std::string variableName,
+             const std::complex<double> *values);
+  void Write(const std::string variableName,
+             const std::complex<long double> *values);
+
+  void Close(const int transportIndex = -1);
+  /*
+  {
+      std::cout<<" ===> CLOSING HDF5 <===== "<<std::endl;
+      //H5Dclose(_dset_id);
+      //H5Sclose(_filespace);
+      //H5Sclose(_memspace);
+      //H5Pclose(_plist_id);
+      H5Fclose(_file_id);
+  }
+  */
+private:
+  capsule::STLVector
+      m_Buffer; ///< heap capsule, contains data and metadata buffers
+
+  void Init();
+  void clean();
+
+  hid_t _plist_id, _file_id, _dset_id;
+  hid_t _memspace, _filespace;
+
+  hid_t DefH5T_COMPLEX_DOUBLE;
+  hid_t DefH5T_COMPLEX_FLOAT;
+  hid_t DefH5T_COMPLEX_LongDOUBLE;
+
+  hid_t DefH5T_filetype_COMPLEX_DOUBLE;
+  hid_t DefH5T_filetype_COMPLEX_FLOAT;
+  hid_t DefH5T_filetype_COMPLEX_LongDOUBLE;
+
+  template <class T>
+  void UseHDFWrite(Variable<T> &variable, const T *values, hid_t h5type);
+
+  /*
+  template<class T>
+    void UseHDFWrite( Variable<T>& variable, const T* values, hid_t h5type )
+  {
+      //here comes your magic at Writing now variable.m_UserValues has the data
+  passed by the user
+      //set variable
+      variable.m_AppValues = values;
+      m_WrittenVariables.insert( variable.m_Name );
+
+      std::cout<<"writting : "<<variable.m_Name<<" dim
+  size:"<<variable.m_GlobalDimensions.size()<<std::endl;
+
+      int dimSize = variable.m_GlobalDimensions.size();
+      //hsize_t     dimsf[dimSize], count[dimSize], offset[dimSize];
+      std::vector<hsize_t>  dimsf, count, offset;
+
+      for(int i=0; i<dimSize; i++) {
+        dimsf.push_back(variable.m_GlobalDimensions[i]);
+        count.push_back(dimsf[i]);
+        offset.push_back(0);
+      }
+      count[0] = dimsf[0]/m_SizeMPI;
+      offset[0]= m_RankMPI*count[0];
+
+      _filespace = H5Screate_simple(dimSize, dimsf.data(), NULL);
+
+      _dset_id = H5Dcreate(_file_id, variable.m_Name.c_str(), h5type,
+  _filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+      H5Sclose(_filespace);
+
+      _memspace = H5Screate_simple(dimSize, count.data(), NULL);
+
+      //Select hyperslab
+
+      _filespace = H5Dget_space(_dset_id);
+      H5Sselect_hyperslab(_filespace, H5S_SELECT_SET, offset.data(), NULL,
+  count.data(), NULL);
+
+
+      //  Create property list for collective dataset write.
+
+      _plist_id = H5Pcreate(H5P_DATASET_XFER);
+      H5Pset_dxpl_mpio(_plist_id, H5FD_MPIO_COLLECTIVE);
+
+      herr_t status;
+      if (m_SizeMPI == 1) {
+        status = H5Dwrite(_dset_id, h5type, _memspace, _filespace, _plist_id,
+  values);
+      } else {
+        std::vector<T> val;
+        for (int i=0; i<100; i++) {
+          //hsize_t c = count[i];
+          //hsize_t o = offset[i];
+          val.push_back(0);
+        }
+        status = H5Dwrite(_dset_id, h5type, _memspace, _filespace, _plist_id,
+  val.data());
+      }
+
+      if (status < 0) {
+        // error
+        std::cerr<<" Write failed. "<<std::endl;
+      }
+
+      std::cout <<" ==> User is responsible for freeing the data "<<std::endl;
+      //free(values);
+
+
+      //Close/release resources.
+
+      //H5Dclose(_dset_id);
+      //H5Sclose(_filespace);
+      //H5Sclose(_memspace);
+      //H5Pclose(_plist_id);
+      //H5Fclose(_file_id);
+
+      H5Dclose(_dset_id);
+      H5Sclose(_filespace);
+      H5Sclose(_memspace);
+      H5Pclose(_plist_id);
+
+  }
+  */
+};
+
+} // end namespace adios
+
+#endif /* HDF5_WRITER_P_H_ */
diff --git a/source/engine/hdf5/HDF5ReaderP.cpp b/source/engine/hdf5/HDF5ReaderP.cpp
new file mode 100644
index 000000000..2412944f4
--- /dev/null
+++ b/source/engine/hdf5/HDF5ReaderP.cpp
@@ -0,0 +1,11 @@
+/*
+ * HDF5ReaderP.cpp
+ *
+ *  Created on: Mar 23, 2017
+ *      Author: junmin
+ */
+
+#include <iostream> //needs to go away, this is just for demo purposes
+
+#include "engine/hdf5/HDF5ReaderP.h"
+
diff --git a/source/engine/hdf5/HDF5WriterP.cpp b/source/engine/hdf5/HDF5WriterP.cpp
new file mode 100644
index 000000000..5d07fd6e7
--- /dev/null
+++ b/source/engine/hdf5/HDF5WriterP.cpp
@@ -0,0 +1,374 @@
+/*
+ * HDF5WriterP.cpp
+ *
+ *  Created on: Mar 23, 2017
+ *      Author: junmin
+ */
+
+#include <iostream> //needs to go away, this is just for demo purposes
+
+#ifdef ADIOS_HAVE_MPI
+#include "engine/hdf5/HDF5WriterP.h"
+
+#include "core/Support.h"
+#include "functions/adiosFunctions.h" //CSVToVector
+
+// supported transports
+//#include "transport/file/FD.h"      // uses POSIX
+//#include "transport/file/FP.h"      // uses C FILE*
+//#include "transport/file/FStream.h" // uses C++ fstream
+
+namespace adios {
+
+HDF5Writer::HDF5Writer(ADIOS &adios, const std::string name,
+                       const std::string accessMode, MPI_Comm mpiComm,
+                       const Method &method, const bool debugMode,
+                       const unsigned int cores)
+    : Engine(adios, "HDF5Writer", name, accessMode, mpiComm, method, debugMode,
+             cores, " HDF5Writer constructor (or call to ADIOS Open).\n"),
+      m_Buffer(accessMode, m_RankMPI, m_DebugMode) {
+  DefH5T_COMPLEX_DOUBLE =
+      H5Tcreate(H5T_COMPOUND, sizeof(ADIOS2_Complex_Double));
+  DefH5T_COMPLEX_FLOAT = H5Tcreate(H5T_COMPOUND, sizeof(ADIOS2_Complex_Float));
+  DefH5T_COMPLEX_LongDOUBLE =
+      H5Tcreate(H5T_COMPOUND, sizeof(ADIOS2_Complex_LongDouble));
+
+  // compound data type for memory
+  H5Tinsert(DefH5T_COMPLEX_DOUBLE, "double real",
+            HOFFSET(ADIOS2_Complex_Double, _re), H5T_NATIVE_DOUBLE);
+  H5Tinsert(DefH5T_COMPLEX_DOUBLE, "double img",
+            HOFFSET(ADIOS2_Complex_Double, _im), H5T_NATIVE_DOUBLE);
+  H5Tinsert(DefH5T_COMPLEX_FLOAT, "float real",
+            HOFFSET(ADIOS2_Complex_Float, _re), H5T_NATIVE_FLOAT);
+  H5Tinsert(DefH5T_COMPLEX_FLOAT, "float img",
+            HOFFSET(ADIOS2_Complex_Float, _im), H5T_NATIVE_FLOAT);
+  H5Tinsert(DefH5T_COMPLEX_LongDOUBLE, "ldouble real",
+            HOFFSET(ADIOS2_Complex_LongDouble, _re), H5T_NATIVE_LDOUBLE);
+  H5Tinsert(DefH5T_COMPLEX_LongDOUBLE, "ldouble img",
+            HOFFSET(ADIOS2_Complex_LongDouble, _im), H5T_NATIVE_LDOUBLE);
+
+  // data type for file
+  int ldsize = H5Tget_size(H5T_NATIVE_DOUBLE);
+  DefH5T_filetype_COMPLEX_DOUBLE = H5Tcreate(H5T_COMPOUND, ldsize + ldsize);
+  H5Tinsert(DefH5T_filetype_COMPLEX_DOUBLE, "double real", 0, H5T_IEEE_F64BE);
+  H5Tinsert(DefH5T_filetype_COMPLEX_DOUBLE, "double img", ldsize,
+            H5T_IEEE_F64BE);
+
+  ldsize = H5Tget_size(H5T_NATIVE_FLOAT);
+  DefH5T_filetype_COMPLEX_FLOAT = H5Tcreate(H5T_COMPOUND, ldsize + ldsize);
+  H5Tinsert(DefH5T_filetype_COMPLEX_FLOAT, "float real", 0, H5T_IEEE_F32BE);
+  H5Tinsert(DefH5T_filetype_COMPLEX_FLOAT, "float img", ldsize, H5T_IEEE_F32BE);
+
+  ldsize = H5Tget_size(
+      H5T_NATIVE_LDOUBLE); // note that sizeof(H5T_NATIVE_LDOUBLE) returned 4!!
+  DefH5T_filetype_COMPLEX_LongDOUBLE = H5Tcreate(H5T_COMPOUND, ldsize + ldsize);
+  H5Tinsert(DefH5T_filetype_COMPLEX_LongDOUBLE, "ldouble real", 0,
+            H5T_NATIVE_LDOUBLE);
+  H5Tinsert(DefH5T_filetype_COMPLEX_LongDOUBLE, "ldouble img", ldsize,
+            H5T_NATIVE_LDOUBLE);
+
+  Init();
+}
+
+HDF5Writer::~HDF5Writer() {}
+
+void HDF5Writer::Init() {
+  if (m_AccessMode != "w" && m_AccessMode != "write" && m_AccessMode != "a" &&
+      m_AccessMode != "append") {
+    throw std::invalid_argument(
+        "ERROR: HDF5Writer doesn't support access mode " + m_AccessMode +
+        ", in call to ADIOS Open or HDF5Writer constructor\n");
+  }
+  std::cout << "method: # of inputs:" << m_Method.m_Parameters.size()
+            << std::endl;
+  std::cout << "::Init hdf5 parallel writer. File name:" << m_Name << std::endl;
+
+  _plist_id = H5Pcreate(H5P_FILE_ACCESS);
+
+#ifdef HAVE_MPI
+  H5Pset_fapl_mpio(_plist_id, m_MPIComm, MPI_INFO_NULL);
+#endif
+
+  /*
+   * Create a new file collectively and release property list identifier.
+   */
+  _file_id = H5Fcreate(m_Name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, _plist_id);
+  H5Pclose(_plist_id);
+}
+
+void HDF5Writer::Write(Variable<char> &variable, const char *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_CHAR);
+}
+
+void HDF5Writer::Write(Variable<unsigned char> &variable,
+                       const unsigned char *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_UCHAR);
+}
+
+void HDF5Writer::Write(Variable<short> &variable, const short *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_SHORT);
+}
+
+void HDF5Writer::Write(Variable<unsigned short> &variable,
+                       const unsigned short *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_USHORT);
+}
+
+void HDF5Writer::Write(Variable<int> &variable, const int *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_INT);
+}
+
+void HDF5Writer::Write(Variable<unsigned int> &variable,
+                       const unsigned int *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_UINT);
+}
+
+void HDF5Writer::Write(Variable<long int> &variable, const long int *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_LONG);
+}
+
+void HDF5Writer::Write(Variable<unsigned long int> &variable,
+                       const unsigned long int *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_ULONG);
+}
+
+void HDF5Writer::Write(Variable<long long int> &variable,
+                       const long long int *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_LLONG);
+}
+
+void HDF5Writer::Write(Variable<unsigned long long int> &variable,
+                       const unsigned long long int *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_ULLONG);
+}
+
+void HDF5Writer::Write(Variable<float> &variable, const float *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_FLOAT);
+}
+
+void HDF5Writer::Write(Variable<double> &variable, const double *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_DOUBLE);
+}
+
+void HDF5Writer::Write(Variable<long double> &variable,
+                       const long double *values) {
+  UseHDFWrite(variable, values, H5T_NATIVE_LDOUBLE);
+}
+
+void HDF5Writer::Write(Variable<std::complex<float>> &variable,
+                       const std::complex<float> *values) {
+  UseHDFWrite(variable, values, DefH5T_filetype_COMPLEX_FLOAT);
+}
+
+void HDF5Writer::Write(Variable<std::complex<double>> &variable,
+                       const std::complex<double> *values) {
+  UseHDFWrite(variable, values, DefH5T_filetype_COMPLEX_DOUBLE);
+}
+
+void HDF5Writer::Write(Variable<std::complex<long double>> &variable,
+                       const std::complex<long double> *values) {
+  UseHDFWrite(variable, values, DefH5T_filetype_COMPLEX_LongDOUBLE);
+}
+
+// String version
+void HDF5Writer::Write(const std::string variableName, const char *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<char>(variableName), values, H5T_NATIVE_CHAR);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const unsigned char *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<unsigned char>(variableName), values,
+              H5T_NATIVE_UCHAR);
+}
+
+void HDF5Writer::Write(const std::string variableName, const short *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<short>(variableName), values,
+              H5T_NATIVE_SHORT);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const unsigned short *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<unsigned short>(variableName), values,
+              H5T_NATIVE_USHORT);
+}
+
+void HDF5Writer::Write(const std::string variableName, const int *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<int>(variableName), values, H5T_NATIVE_INT);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const unsigned int *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<unsigned int>(variableName), values,
+              H5T_NATIVE_UINT);
+}
+
+void HDF5Writer::Write(const std::string variableName, const long int *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<long int>(variableName), values,
+              H5T_NATIVE_LONG);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const unsigned long int *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<unsigned long int>(variableName), values,
+              H5T_NATIVE_ULONG);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const long long int *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<long long int>(variableName), values,
+              H5T_NATIVE_LLONG);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const unsigned long long int *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<unsigned long long int>(variableName), values,
+              H5T_NATIVE_ULLONG);
+}
+
+void HDF5Writer::Write(const std::string variableName, const float *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<float>(variableName), values,
+              H5T_NATIVE_FLOAT);
+}
+
+void HDF5Writer::Write(const std::string variableName, const double *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<double>(variableName), values,
+              H5T_NATIVE_DOUBLE);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const long double *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<long double>(variableName), values,
+              H5T_NATIVE_LDOUBLE);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const std::complex<float> *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<std::complex<float>>(variableName), values,
+              DefH5T_COMPLEX_FLOAT);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const std::complex<double> *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<std::complex<double>>(variableName), values,
+              DefH5T_COMPLEX_DOUBLE);
+}
+
+void HDF5Writer::Write(const std::string variableName,
+                       const std::complex<long double> *values) {
+  UseHDFWrite(m_ADIOS.GetVariable<std::complex<long double>>(variableName),
+              values, DefH5T_COMPLEX_LongDOUBLE);
+}
+
+void HDF5Writer::Close(const int transportIndex) {
+  std::cout << " ===> CLOSING HDF5 <===== " << std::endl;
+  // H5Dclose(_dset_id);
+  // H5Sclose(_filespace);
+  // H5Sclose(_memspace);
+  // H5Pclose(_plist_id);
+  H5Fclose(_file_id);
+}
+
+template <class T>
+void HDF5Writer::UseHDFWrite(Variable<T> &variable, const T *values,
+                             hid_t h5type) {
+  // here comes your magic at Writing now variable.m_UserValues has the data
+  // passed by the user
+  // set variable
+  variable.m_AppValues = values;
+  m_WrittenVariables.insert(variable.m_Name);
+
+  std::cout << "writting : " << variable.m_Name
+            << " dim size:" << variable.m_GlobalDimensions.size() << std::endl;
+
+  int dimSize = variable.m_GlobalDimensions.size();
+  for (int i = 0; i < dimSize; i++) {
+    std::cout << " dim: " << i << ", size:" << variable.m_GlobalDimensions[i]
+              << " offset=" << variable.m_GlobalOffsets[i]
+              << " count=" << variable.m_Dimensions[i] << std::endl;
+  }
+  std::vector<hsize_t> dimsf, count, offset;
+
+  for (int i = 0; i < dimSize; i++) {
+    dimsf.push_back(variable.m_GlobalDimensions[i]);
+    count.push_back(variable.m_Dimensions[i]);
+    offset.push_back(variable.m_GlobalOffsets[i]);
+  }
+
+  _filespace = H5Screate_simple(dimSize, dimsf.data(), NULL);
+
+  _dset_id = H5Dcreate(_file_id, variable.m_Name.c_str(), h5type, _filespace,
+                       H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  // H5Sclose(_filespace);
+
+  _memspace = H5Screate_simple(dimSize, count.data(), NULL);
+
+  // Select hyperslab
+  _filespace = H5Dget_space(_dset_id);
+  H5Sselect_hyperslab(_filespace, H5S_SELECT_SET, offset.data(), NULL,
+                      count.data(), NULL);
+
+  //  Create property list for collective dataset write.
+  _plist_id = H5Pcreate(H5P_DATASET_XFER);
+  H5Pset_dxpl_mpio(_plist_id, H5FD_MPIO_COLLECTIVE);
+
+  herr_t status;
+
+  if (h5type == DefH5T_filetype_COMPLEX_FLOAT) {
+    /*
+    ADIOS2_Complex_Float v[3];
+    v[0]._re = 1.1, v[0]._im = 1.2;
+    v[1]._re = 2.1, v[1]._im = 2.2;
+    v[2]._re = 3.1, v[2]._im = 3.2;
+    // status = H5Dwrite(_dset_id, DefH5T_COMPLEX_FLOAT, _memspace, _filespace,
+    // _plist_id, values);
+    status = H5Dwrite(_dset_id, DefH5T_COMPLEX_FLOAT, _memspace, _filespace,
+                      _plist_id, v);
+    */
+  } else if (h5type == DefH5T_filetype_COMPLEX_DOUBLE) {
+    /*
+    ADIOS2_Complex_Double v[3];
+    v[0]._re = 1.1, v[0]._im = 1.2;
+    v[1]._re = 2.1, v[1]._im = 2.2;
+    v[2]._re = 3.1, v[2]._im = 3.2;
+    status = H5Dwrite(_dset_id, DefH5T_COMPLEX_DOUBLE, _memspace, _filespace,
+                      _plist_id, v);
+    */
+  } else if (h5type == DefH5T_filetype_COMPLEX_LongDOUBLE) {
+    /*
+    ADIOS2_Complex_LongDouble v[3];
+    v[0]._re = 1.1, v[0]._im = 1.2;
+    v[1]._re = 2.1, v[1]._im = 2.2;
+    v[2]._re = 3.1, v[2]._im = 3.2;
+    status = H5Dwrite(_dset_id, DefH5T_COMPLEX_LongDOUBLE, _memspace,
+                      _filespace, _plist_id, v);
+    */
+  } else {
+    status =
+        H5Dwrite(_dset_id, h5type, _memspace, _filespace, _plist_id, values);
+  }
+
+  if (status < 0) {
+    // error
+    std::cerr << " Write failed. " << std::endl;
+  }
+
+  std::cout << " ==> User is responsible for freeing the data " << std::endl;
+  // free(values);
+
+  // Close/release resources.
+
+  // H5Dclose(_dset_id);
+  // H5Sclose(_filespace);
+  // H5Sclose(_memspace);
+  // H5Pclose(_plist_id);
+  // H5Fclose(_file_id);
+
+  H5Dclose(_dset_id);
+  H5Sclose(_filespace);
+  H5Sclose(_memspace);
+  H5Pclose(_plist_id);
+}
+
+} // end namespace adios
+
+#endif //ADIOS_HAVE_MPI 
-- 
GitLab