diff --git a/bindings/python/include/ADIOSPy.h b/bindings/python/include/ADIOSPy.h
index b1a009370675a3bcaeee97598cc7da3a83c2f413..8d2179adb2ef62b9dd89de59dc3bb3a33a3b2d74 100644
--- a/bindings/python/include/ADIOSPy.h
+++ b/bindings/python/include/ADIOSPy.h
@@ -23,7 +23,7 @@
 #include "adios2/pybind11/pybind11.h"
 #endif
 
-#include "adios2/ADIOS.h"
+#include "../../../source/adios2/core/ADIOS.h"
 #include "adios2/MethodPy.h"
 #include "adios2/VariablePy.h"
 #include "adios2/adiosPyFunctions.h" //ListToVector, VectorToList
diff --git a/bindings/python/include/MethodPy.h b/bindings/python/include/MethodPy.h
index 3b012f566dce3d9fb7f3fe49181d7ea6becebb4a..4187c5f0f41e865368e58ccb703433d736425498 100644
--- a/bindings/python/include/MethodPy.h
+++ b/bindings/python/include/MethodPy.h
@@ -20,7 +20,7 @@
 #include "adios2/pybind11/pybind11.h"
 #endif
 
-#include "adios2/core/Method.h"
+#include "../../../source/adios2/core/IO.h"
 
 namespace adios
 {
diff --git a/doc/API_design/API_example_use.cpp b/doc/API_design/API_example_use.cpp
index bc1c00fc820732729e2d4fa4ffc0008fd02f2bff..a9e6d4bf162e8631cc992fd861e2401f53dfe4b2 100644
--- a/doc/API_design/API_example_use.cpp
+++ b/doc/API_design/API_example_use.cpp
@@ -2,7 +2,7 @@
  * of the ideas */
 #include <mpi.h>
 
-#include "adios2/ADIOS.h"
+#include "../../source/adios2/core/ADIOS.h"
 
 void cb_AsyncWriteAdvanceCompleted(std::shared_ptr<adios::Engine> writer)
 {
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index cff55b7612dea88c6033417e74a3e199434fde0a..0ea4819bccbfb48f061076bbadb16dac07818466 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -3,6 +3,7 @@
 # accompanying file Copyright.txt for details.
 #------------------------------------------------------------------------------#
 
+add_subdirectory(basics)
 add_subdirectory(hello)
 add_subdirectory(heatTransfer)
 add_subdirectory(experimental)
diff --git a/examples/basics/CMakeLists.txt b/examples/basics/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..94fa54cd4c435d3cb4b83e199e909d21e85e8194
--- /dev/null
+++ b/examples/basics/CMakeLists.txt
@@ -0,0 +1,9 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+add_subdirectory(globalArray)
+add_subdirectory(joinedArray)
+add_subdirectory(localArray)
+add_subdirectory(values)
diff --git a/examples/basics/globalArray/CMakeLists.txt b/examples/basics/globalArray/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7a0af15e3e998029c72366b30d034fddab35445c
--- /dev/null
+++ b/examples/basics/globalArray/CMakeLists.txt
@@ -0,0 +1,17 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+add_executable(globalArray_write globalArray_write.cpp)
+
+if(ADIOS_USE_MPI)
+  find_package(MPI COMPONENTS C REQUIRED)
+
+  target_include_directories(globalArray_write PRIVATE ${MPI_C_INCLUDE_PATH})
+  target_link_libraries(globalArray_write ${MPI_C_LIBRARIES})
+
+endif()
+
+target_link_libraries(globalArray_write adios2)
+
diff --git a/examples/basics/globalArray/globalArray.xml b/examples/basics/globalArray/globalArray.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba
--- /dev/null
+++ b/examples/basics/globalArray/globalArray.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<adios-config>
+
+    <io name="Output">
+        <engine name="BPFileWriter"/>
+        <transport name= "File"/>
+    </io>
+
+</adios-config>
+
diff --git a/examples/basics/globalArray/globalArray_write.cpp b/examples/basics/globalArray/globalArray_write.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a8a34d46a7f8440acd36709beaa31778c8064b8
--- /dev/null
+++ b/examples/basics/globalArray/globalArray_write.cpp
@@ -0,0 +1,136 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Write a global array from multiple processors.
+ *
+ * A global array is an N-dimensional array. A process can write a sub-array
+ * into the global array by stating the N-dimensional offset and the size of
+ * the sub-array. At reading, one can read back any portion of the array
+ * regardless of how many processors wrote that data.
+ *
+ * Processes are NOT required
+ * - to stay in the boundaries of the global dimensions. However, one will not
+ * be able to read back data outside of the boundaries.
+ * - to fill the whole global array, i.e. one can leave holes in it. At reading,
+ * one will get the fill-value set for the array for those coordinates that
+ * are not written by any process.
+ *
+ * The global dimensions of a global array MUST NOT change over time.
+ * If they are, then the array should be handled as a local array. Of course, if
+ * only a single output step is written to a file, that still shows up at
+ * reading as a global array.
+ *
+ * The decomposition of the array across the processes, however, can change
+ * between output steps.
+ *
+ * Created on: Jun 2, 2017
+ *      Author: pnorbert
+ */
+
+#include <iostream>
+#include <vector>
+
+#include <adios2.h>
+#ifdef ADIOS2_HAVE_MPI
+#include <mpi.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+    int rank = 0, nproc = 1;
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
+#endif
+    const bool adiosDebug = true;
+    const int NSTEPS = 5;
+
+#ifdef ADIOS2_HAVE_MPI
+    adios::ADIOS adios("globalArray.xml", MPI_COMM_WORLD);
+#else
+    adios::ADIOS adios("globalArray.xml");
+#endif
+
+    // Application variables for output
+    const unsigned int Nx = 10;
+    // Global 2D array, size of nproc x Nx, with 1D decomposition
+    // Each process writes one "row" of the 2D matrix.
+    std::vector<double> row(Nx);
+
+    try
+    {
+        // Get io settings from the config file or
+        // create one with default settings here
+        adios::IO &io = adios.DeclareIO("Output");
+
+        /*
+         * Define global array: type, name, global dimensions
+         * The local process' part (start, count) can be defined now or later
+         * before Write().
+         */
+        adios::Variable<double> &varGlobalArray =
+            io.DefineVariable<double>("GlobalArray", {(unsigned int)nproc, Nx});
+
+        // Open file. "w" means we overwrite any existing file on disk,
+        // but Advance() will append steps to the same file.
+        auto writer = io.Open("globalArray.bp", adios::OpenMode::Write);
+
+        if (!writer)
+            throw std::ios_base::failure(
+                "ERROR: failed to open file with ADIOS\n");
+
+        for (int step = 0; step < NSTEPS; step++)
+        {
+            for (int i = 0; i < Nx; i++)
+            {
+                row[i] = step * Nx * nproc * 1.0 + rank * Nx * 1.0 + (double)i;
+            }
+
+            // Make a 2D selection to describe the local dimensions of the
+            // variable we write and its offsets in the global spaces
+            adios::SelectionBoundingBox sel({(unsigned int)rank, 0}, {1, Nx});
+            varGlobalArray.SetSelection(sel);
+            writer->Write<double>(varGlobalArray, row.data());
+
+            // Indicate we are done for this step.
+            // Disk I/O will be performed during this call unless
+            // time aggregation postpones all of that to some later step
+            writer->Advance();
+        }
+
+        // Called once: indicate that we are done with this output for the run
+        writer->Close();
+    }
+    catch (std::invalid_argument &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::ios_base::failure &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "System exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::exception &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Finalize();
+#endif
+
+    return 0;
+}
diff --git a/examples/basics/joinedArray/CMakeLists.txt b/examples/basics/joinedArray/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c4fe971950a755f41fff0c5b0917bee2c2b20987
--- /dev/null
+++ b/examples/basics/joinedArray/CMakeLists.txt
@@ -0,0 +1,17 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+add_executable(joinedArray_write joinedArray_write.cpp)
+
+if(ADIOS_USE_MPI)
+  find_package(MPI COMPONENTS C REQUIRED)
+
+  target_include_directories(joinedArray_write PRIVATE ${MPI_C_INCLUDE_PATH})
+  target_link_libraries(joinedArray_write ${MPI_C_LIBRARIES})
+
+endif()
+
+target_link_libraries(joinedArray_write adios2)
+
diff --git a/examples/basics/joinedArray/joinedArray.xml b/examples/basics/joinedArray/joinedArray.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba
--- /dev/null
+++ b/examples/basics/joinedArray/joinedArray.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<adios-config>
+
+    <io name="Output">
+        <engine name="BPFileWriter"/>
+        <transport name= "File"/>
+    </io>
+
+</adios-config>
+
diff --git a/examples/basics/joinedArray/joinedArray_write.cpp b/examples/basics/joinedArray/joinedArray_write.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d878ed891430122545fc2bee66e04f0556ec014a
--- /dev/null
+++ b/examples/basics/joinedArray/joinedArray_write.cpp
@@ -0,0 +1,138 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Write local arrays from multiple processors and make ADIOS join them
+ * at reading to show a global array
+ *
+ * If every process has an array that is different only in one dimension
+ * it can be presented as a global array by joining the arrays together.
+ * E.g. if every process has a table with a different number of rows,
+ * and one does not want to do a global communication to calculate the offsets
+ * in the global table, one can just write the local arrays and let ADIOS
+ * calculate the offsets at read time (when all sizes are known by any process).
+ *
+ * bpls can show the size of each block of the table:
+ * bpls -D <file> <variable>
+ *
+ * Note: only one dimension can be joinable, every other dimension must be the
+ * same on each process.
+ *
+ * Note: the local dimension size in the joinable dimension is allowed to change
+ * over time within each processor. However, if the sum of all local sizes
+ * changes over time, the result will look like a local array.
+ * (Because global arrays with changing global dimension over time can only be
+ * handled as local arrays in ADIOS)
+ *
+ *
+ * Created on: Jun 2, 2017
+ *      Author: pnorbert
+ */
+
+#include <iostream>
+#include <vector>
+
+#include <adios2.h>
+#ifdef ADIOS2_HAVE_MPI
+#include <mpi.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+    int rank = 0, nproc = 1;
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
+#endif
+    const bool adiosDebug = true;
+    const int NSTEPS = 5;
+
+    // generate different random numbers on each process,
+    // but always the same sequence at each run
+    srand(rank * 32767);
+
+#ifdef ADIOS2_HAVE_MPI
+    adios::ADIOS adios("localArray.xml", MPI_COMM_WORLD);
+#else
+    adios::ADIOS adios("localArray.xml");
+#endif
+
+    // Application variables for output
+    // random size per process, 5..10 each
+    const unsigned int Nrows = rand() % 6 + 5;
+    const unsigned int Ncols = 4;
+    // Local array, size is fixed over time on each process
+    std::vector<double> mytable(Nrows * Ncols);
+
+    try
+    {
+        // Get io settings from the config file or
+        // create one with default settings here
+        adios::IO &io = adios.DeclareIO("Output");
+
+        /*
+         * Define joinable local array: type, name, global and local size
+         * Starting offset can be an empty vector
+         * Only one global dimension can be joined
+         */
+        adios::Variable<double> &varTable = io.DefineVariable<double>(
+            "table", {adios::JoinedDim, Ncols}, {}, {Nrows, Ncols});
+
+        // Open file. "w" means we overwrite any existing file on disk,
+        // but Advance() will append steps to the same file.
+        auto writer = io.Open("joinedArray.bp", adios::OpenMode::Write);
+
+        if (writer == nullptr)
+            throw std::ios_base::failure(
+                "ERROR: failed to open file with ADIOS\n");
+
+        for (int step = 0; step < NSTEPS; step++)
+        {
+            for (int row = 0; row < Nrows; row++)
+            {
+                for (int col = 0; col < Ncols; col++)
+                {
+                    mytable[row * Ncols + col] =
+                        rank * 1.0 + row * 0.1 + col * 0.01;
+                }
+            }
+
+            writer->Write<double>(varTable, mytable.data());
+
+            writer->Advance();
+        }
+
+        writer->Close();
+    }
+    catch (std::invalid_argument &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::ios_base::failure &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "System exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::exception &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Finalize();
+#endif
+
+    return 0;
+}
diff --git a/examples/basics/localArray/CMakeLists.txt b/examples/basics/localArray/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..91077b8cedcd7a2abdb8412a74774f25e14e546d
--- /dev/null
+++ b/examples/basics/localArray/CMakeLists.txt
@@ -0,0 +1,17 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+add_executable(localArray_write localArray_write.cpp)
+
+if(ADIOS_USE_MPI)
+  find_package(MPI COMPONENTS C REQUIRED)
+
+  target_include_directories(localArray_write PRIVATE ${MPI_C_INCLUDE_PATH})
+  target_link_libraries(localArray_write ${MPI_C_LIBRARIES})
+
+endif()
+
+target_link_libraries(localArray_write adios2)
+
diff --git a/examples/basics/localArray/localArray.xml b/examples/basics/localArray/localArray.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba
--- /dev/null
+++ b/examples/basics/localArray/localArray.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<adios-config>
+
+    <io name="Output">
+        <engine name="BPFileWriter"/>
+        <transport name= "File"/>
+    </io>
+
+</adios-config>
+
diff --git a/examples/basics/localArray/localArray_write.cpp b/examples/basics/localArray/localArray_write.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1efba98b20b3ab2d5b558ce609ff22027936a8bc
--- /dev/null
+++ b/examples/basics/localArray/localArray_write.cpp
@@ -0,0 +1,151 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Write local arrays from multiple processors.
+ *
+ * If one cannot or does not want to organize arrays present on each process
+ * as one global array, still one can write them out with the same name.
+ * Reading, however, needs to be handled differently: each process' array has
+ * to be read separately, using Writeblock selections. The size of each process
+ * block should be discovered by the reading application by inquiring per-block
+ * size information of the variable, and allocate memory for reading
+ * accordingly.
+ *
+ * bpls can show the size of each block of the variable:
+ * bpls -D <file> <variable>
+ *
+ *
+ * Created on: Jun 2, 2017
+ *      Author: pnorbert
+ */
+
+#include <iostream>
+#include <vector>
+
+#include <adios2.h>
+#ifdef ADIOS2_HAVE_MPI
+#include <mpi.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+    int rank = 0, nproc = 1;
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
+#endif
+    const bool adiosDebug = true;
+    const int NSTEPS = 5;
+
+    // generate different random numbers on each process,
+    // but always the same sequence at each run
+    srand(rank * 32767);
+
+#ifdef ADIOS2_HAVE_MPI
+    adios::ADIOS adios("localArray.xml", MPI_COMM_WORLD);
+#else
+    adios::ADIOS adios("localArray.xml");
+#endif
+
+    // Application variables for output
+    // random size per process, 5..10 each
+    unsigned int Nx = rand() % 6 + 5;
+    // Local array, size is fixed over time on each process
+    std::vector<double> v1(Nx);
+
+    // random size per process, a different size at each step
+    unsigned int Nelems;
+    // Local array, size is changing over time on each process
+    std::vector<double> v2;
+
+    try
+    {
+        // Get io settings from the config file or
+        // create one with default settings here
+        adios::IO &io = adios.DeclareIO("Output");
+
+        /*
+         * Define local array: type, name, local size
+         * Global dimension and starting offset must be an empty vector
+         */
+        adios::Variable<double> &varV1 =
+            io.DefineVariable<double>("v1", {}, {}, {Nx});
+
+        /*
+         * Define local array: type, name
+         * Global dimension and starting offset must be an empty vector
+         * but local size must NOT be an empty vector.
+         * We can use {adios::UnknownDim} for this purpose or any number
+         * but we will modify it before writing
+         */
+        adios::Variable<double> &varV2 =
+            io.DefineVariable<double>("v2", {}, {}, {adios::UnknownDim});
+
+        // Open file. "w" means we overwrite any existing file on disk,
+        // but Advance() will append steps to the same file.
+        auto writer = io.Open("localArray.bp", adios::OpenMode::Write);
+
+        if (writer == nullptr)
+            throw std::ios_base::failure(
+                "ERROR: failed to open file with ADIOS\n");
+
+        for (int step = 0; step < NSTEPS; step++)
+        {
+            for (int i = 0; i < Nx; i++)
+            {
+                v1[i] = rank * 1.0 + step * 0.1;
+            }
+
+            writer->Write<double>(varV1, v1.data());
+
+            // random size per process per step, 5..10 each
+            Nelems = rand() % 6 + 5;
+            v2.reserve(Nelems);
+            for (int i = 0; i < Nelems; i++)
+            {
+                v2[i] = rank * 1.0 + step * 0.1;
+            }
+
+            // Set the size of the array now because we did not know
+            // the size at the time of definition
+            varV2.SetSelection({}, {Nelems});
+            writer->Write<double>(varV2, v2.data());
+
+            writer->Advance();
+        }
+
+        writer->Close();
+    }
+    catch (std::invalid_argument &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::ios_base::failure &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "System exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::exception &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Finalize();
+#endif
+
+    return 0;
+}
diff --git a/examples/basics/values/CMakeLists.txt b/examples/basics/values/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b5894f894d855a004bcce67448470ea633b18b67
--- /dev/null
+++ b/examples/basics/values/CMakeLists.txt
@@ -0,0 +1,17 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+add_executable(values_write values_write.cpp)
+
+if(ADIOS_USE_MPI)
+  find_package(MPI COMPONENTS C REQUIRED)
+
+  target_include_directories(values_write PRIVATE ${MPI_C_INCLUDE_PATH})
+  target_link_libraries(values_write ${MPI_C_LIBRARIES})
+
+endif()
+
+target_link_libraries(values_write adios2)
+
diff --git a/examples/basics/values/values.xml b/examples/basics/values/values.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba
--- /dev/null
+++ b/examples/basics/values/values.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<adios-config>
+
+    <io name="Output">
+        <engine name="BPFileWriter"/>
+        <transport name= "File"/>
+    </io>
+
+</adios-config>
+
diff --git a/examples/basics/values/values_write.cpp b/examples/basics/values/values_write.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..90e3fd4bde97188564eebbb9d1bdb9936eae6171
--- /dev/null
+++ b/examples/basics/values/values_write.cpp
@@ -0,0 +1,158 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Write single values to a file. There are four different cases:
+ * 1. Global constant - same on all processes, constant over time
+ * 2. Global value - same on all processes, may change over time
+ * 3. Local constants - different across processes, constant over time
+ * 4. Local value - different across processes, may change over time
+ *
+ * Constants are not handled separately from time-varying values in ADIOS.
+ * Simply write them only in the first step.
+ *
+ * Writing a global value from multiple processes does not hurt but it is
+ * useless.
+ *
+ * Created on: Jun 2, 2017
+ *      Author: pnorbert
+ */
+
+#include <iostream>
+#include <vector>
+
+#include <adios2.h>
+#ifdef ADIOS2_HAVE_MPI
+#include <mpi.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+    int rank = 0, nproc = 1;
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
+#endif
+    const bool adiosDebug = true;
+    const int NSTEPS = 5;
+
+    // generate different random numbers on each process,
+    // but always the same sequence at each run
+    srand(rank * 32767);
+
+#ifdef ADIOS2_HAVE_MPI
+    adios::ADIOS adios("values.xml", MPI_COMM_WORLD);
+#else
+    adios::ADIOS adios("values.xml");
+#endif
+
+    // Application variables for output
+    // 1. Global value, constant across processes, constant over time
+    // This is 'nproc'
+
+    // 2. Global value, constant across processes, varying value over time
+    // This is 'step'
+
+    // 3. Local value, varying across processes, constant over time
+    // It will appear in reading as a 1D array of nproc elements.
+    // This is 'rank'
+
+    // 4. Local value, varying across processes, varying over time
+    unsigned int Nparts; // random size per process, 5..10 each
+
+    try
+    {
+        // Get io settings from the config file or
+        // create one with default settings here
+        adios::IO &io = adios.DeclareIO("Output");
+
+        /*
+         * Define variables
+         */
+        // 1. Global constant, same value across processes, constant over time
+        adios::Variable<int> &varNproc = io.DefineVariable<int>("Nproc");
+
+        // 2. Global value, same value across processes, varying value over time
+        adios::Variable<int> &varStep = io.DefineVariable<int>("Step");
+
+        // 3. Local value, varying across processes, constant over time
+        adios::Variable<int> &varProcessID =
+            io.DefineVariable<int>("ProcessID", {adios::LocalValueDim});
+
+        // 4. Local value, varying across processes, varying over time
+        adios::Variable<unsigned int> &varNparts =
+            io.DefineVariable<unsigned int>("Nparts", {adios::LocalValueDim});
+
+        // Open file. "w" means we overwrite any existing file on disk,
+        // but Advance() will append steps to the same file.
+        auto writer = io.Open("values.bp", adios::OpenMode::Write);
+
+        if (!writer)
+            throw std::ios_base::failure(
+                "ERROR: failed to open file with ADIOS\n");
+
+        for (int step = 0; step < NSTEPS; step++)
+        {
+            // random size per process, 5..10 each
+            Nparts = rand() % 6 + 5;
+
+            // 1. and 2. Writing a global value from only one process
+            if (rank == 0)
+            {
+                // 1. Writing a global constant value only once
+                if (step == 0)
+                {
+                    writer->Write<int>("Nproc", nproc);
+                }
+                writer->Write<int>(varStep, step);
+            }
+
+            // 3. and 4. Writing a local value on every process. Will be shown
+            // at reading as a 1D array
+            if (step == 0)
+            {
+                writer->Write<int>(varProcessID, rank);
+            }
+            writer->Write<unsigned int>(varNparts, Nparts);
+
+            // Indicate we are done for this step.
+            // Disk I/O will be performed during this call unless
+            // time aggregation postpones all of that to some later step
+            writer->Advance();
+        }
+
+        // Called once: indicate that we are done with this output for the run
+        writer->Close();
+    }
+    catch (std::invalid_argument &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::ios_base::failure &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "System exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+    catch (std::exception &e)
+    {
+        if (rank == 0)
+        {
+            std::cout << "Exception, STOPPING PROGRAM\n";
+            std::cout << e.what() << "\n";
+        }
+    }
+
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Finalize();
+#endif
+
+    return 0;
+}
diff --git a/examples/experimental/multistep/reader_allsteps.cpp b/examples/experimental/multistep/reader_allsteps.cpp
index 6e669aec53ec4befb693bab12e3af9498f45f1a9..7b50a98bace368713560061a28bda4509d1671e8 100644
--- a/examples/experimental/multistep/reader_allsteps.cpp
+++ b/examples/experimental/multistep/reader_allsteps.cpp
@@ -73,9 +73,9 @@ int main(int argc, char *argv[])
     const bool adiosDebug = true;
 
 #ifdef ADIOS2_HAVE_MPI
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::WARN);
+    adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
 #else
-    adios::ADIOS adios(adios::Verbose::WARN);
+    adios::ADIOS adios(adios::DebugON);
 #endif
 
     // Info variables from the file
@@ -108,8 +108,8 @@ int main(int argc, char *argv[])
     {
         // Define method for engine creation
         // 1. Get method def from config file or define new one
-        adios::Method &bpReaderSettings = adios.DeclareMethod("input");
-        if (!bpReaderSettings.IsUserDefined())
+        adios::IO &bpReaderSettings = adios.DeclareIO("input");
+        if (!bpReaderSettings.InConfigFile())
         {
             // if not defined by user, we can change the default settings
             bpReaderSettings.SetEngine(
@@ -122,9 +122,10 @@ int main(int argc, char *argv[])
         // Default behavior
         // auto bpReader = adios.Open( "myNumbers.bp", "r" );
         // this would just open with a default transport, which is "BP"
-        auto bpReader = adios.Open("myNumbers.bp", "r", bpReaderSettings);
+        auto bpReader =
+            bpReaderSettings.Open("myNumbers.bp", adios::OpenMode::Read);
 
-        if (bpReader == nullptr)
+        if (!bpReader)
             throw std::ios_base::failure(
                 "ERROR: failed to open ADIOS bpReader\n");
 
@@ -132,7 +133,7 @@ int main(int argc, char *argv[])
          * own
          * number of steps */
 
-        adios::Variable<int> *vNproc = bpReader->InquireVariableInt("Nproc");
+        adios::Variable<int> *vNproc = bpReader->InquireVariable<int>("Nproc");
         Nwriters = vNproc->m_Data[0];
         if (rank == 0)
             std::cout << "# of writers = " << Nwriters << std::endl;
@@ -142,7 +143,7 @@ int main(int argc, char *argv[])
          */
         // read a Global scalar which has a single value in a step
         adios::Variable<unsigned int> *vNX =
-            bpReader->InquireVariableUInt("NX");
+            bpReader->InquireVariable<unsigned int>("NX");
         Nx = vNX->m_Data[0];
         // bpReader->Read<unsigned int>("NX", &Nx);
         if (rank == 0)
@@ -154,19 +155,19 @@ int main(int argc, char *argv[])
            and read does not read it as array by default.
         */
         adios::Variable<unsigned int> *vNY =
-            bpReader->InquireVariableUInt("NY");
-        Nys.resize(vNY->GetNSteps()); // number of steps available
+            bpReader->InquireVariable<unsigned int>("NY");
+        Nys.resize(vNY->m_AvailableSteps); // number of steps available
         // make a StepSelection to select multiple steps. Args: From, #of
         // consecutive steps
         // ? How do we make a selection for an arbitrary list of steps ?
-        vNY->SetStepSelection(0, vNY->GetNSteps());
+        vNY->SetStepSelection(0, vNY->m_AvailableSteps);
         bpReader->Read<unsigned int>(*vNY, Nys.data());
         if (rank == 0)
             Print1DArray(Nys.data(), Nys.size(), "NY");
 
         /* ProcessID */
         adios::Variable<int> *vProcessID =
-            bpReader->InquireVariableInt("ProcessID");
+            bpReader->InquireVariable<int>("ProcessID");
         if (vProcessID->m_Shape[0] != Nwriters)
         {
             std::cout << "ERROR: Unexpected array size of ProcessID = "
@@ -183,13 +184,13 @@ int main(int argc, char *argv[])
         // elements.
         // We can read all steps into a 2D array of nproc * Nwriters
         adios::Variable<unsigned int> *vNparts =
-            bpReader->InquireVariableUInt("Nparts");
+            bpReader->InquireVariable<unsigned int>("Nparts");
         unsigned int **Nparts =
-            Make2DArray<unsigned int>(vNparts->GetNSteps(), Nwriters);
-        vNparts->SetStepSelection(0, vNparts->GetNSteps());
+            Make2DArray<unsigned int>(vNparts->m_AvailableSteps, Nwriters);
+        vNparts->SetStepSelection(0, vNparts->m_AvailableSteps);
         bpReader->Read<unsigned int>(*vNparts, Nparts[0]);
         if (rank == 0)
-            Print2DArray(Nparts, vNparts->GetNSteps(), Nwriters, "Nparts");
+            Print2DArray(Nparts, vNparts->m_AvailableSteps, Nwriters, "Nparts");
         Delete2DArray(Nparts);
 #ifdef ADIOS2_HAVE_MPI
         MPI_Barrier(MPI_COMM_WORLD);
@@ -200,7 +201,7 @@ int main(int argc, char *argv[])
          */
         // inquiry about a variable, whose name we know
         adios::Variable<double> *vGlobalArrayFixedDims =
-            bpReader->InquireVariableDouble("GlobalArrayFixedDims");
+            bpReader->InquireVariable<double>("GlobalArrayFixedDims");
 
         if (vGlobalArrayFixedDims == nullptr)
             throw std::ios_base::failure(
@@ -221,43 +222,39 @@ int main(int argc, char *argv[])
             std::cout << "GlobalArrayFixedDims parallel read" << std::endl;
 
         double **GlobalArrayFixedDims =
-            Make2DArray<double>(vGlobalArrayFixedDims->GetNSteps(), count);
+            Make2DArray<double>(vGlobalArrayFixedDims->m_AvailableSteps, count);
 
         // Make a 1D selection to describe the local dimensions of the variable
         // we READ and its offsets in the global spaces
         vGlobalArrayFixedDims->SetSelection({start}, {count});
         vGlobalArrayFixedDims->SetStepSelection(
-            0, vGlobalArrayFixedDims->GetNSteps());
+            0, vGlobalArrayFixedDims->m_AvailableSteps);
         bpReader->Read<double>(*vGlobalArrayFixedDims, GlobalArrayFixedDims[0]);
 #ifdef ADIOS2_HAVE_MPI
         MPI_Barrier(MPI_COMM_WORLD);
         MPI_Status status;
-#endif
-
         int token = 0;
-#ifdef ADIOS2_HAVE_MPI
         if (rank > 0)
             MPI_Recv(&token, 1, MPI_INT, rank - 1, 0, MPI_COMM_WORLD, &status);
+#endif
         std::cout << "Rank " << rank << " read start = " << start
                   << " count = " << count << std::endl;
-#endif
-        Print2DArray(GlobalArrayFixedDims, vGlobalArrayFixedDims->GetNSteps(),
-                     count, "GlobalArrayFixedDims");
+        Print2DArray(GlobalArrayFixedDims,
+                     vGlobalArrayFixedDims->m_AvailableSteps, count,
+                     "GlobalArrayFixedDims");
 #ifdef ADIOS2_HAVE_MPI
         if (rank < nproc - 1)
             MPI_Send(&token, 1, MPI_INT, rank + 1, 0, MPI_COMM_WORLD);
-#endif
-        Delete2DArray(GlobalArrayFixedDims);
-#ifdef ADIOS2_HAVE_MPI
         MPI_Barrier(MPI_COMM_WORLD);
 #endif
+        Delete2DArray(GlobalArrayFixedDims);
 
         /*
          * LocalArrayFixedDims
          */
         // inquiry about a variable, whose name we know
         adios::Variable<float> *vLocalArrayFixedDims =
-            bpReader->InquireVariableFloat("LocalArrayFixedDims");
+            bpReader->InquireVariable<float>("LocalArrayFixedDims");
         if (vLocalArrayFixedDims->m_Shape[0] != adios::IrregularDim)
         {
             throw std::ios_base::failure(
@@ -276,9 +273,9 @@ int main(int argc, char *argv[])
          */
         // inquiry about a variable, whose name we know
         adios::Variable<float> *vLocalArrayFixedDimsJoined =
-            bpReader->InquireVariableFloat("LocalArrayFixedDimsJoined");
+            bpReader->InquireVariable<float>("LocalArrayFixedDimsJoined");
         float **LocalArrayFixedDimsJoined =
-            Make2DArray<float>(vLocalArrayFixedDimsJoined->GetNSteps(),
+            Make2DArray<float>(vLocalArrayFixedDimsJoined->m_AvailableSteps,
                                vLocalArrayFixedDimsJoined->m_Shape[0]);
 
         // Make a 1D selection to describe the local dimensions of the variable
@@ -286,12 +283,12 @@ int main(int argc, char *argv[])
         vLocalArrayFixedDimsJoined->SetSelection(
             {0}, {vLocalArrayFixedDimsJoined->m_Shape[0]});
         vLocalArrayFixedDimsJoined->SetStepSelection(
-            0, vLocalArrayFixedDimsJoined->GetNSteps());
+            0, vLocalArrayFixedDimsJoined->m_AvailableSteps);
         bpReader->Read<float>(*vLocalArrayFixedDimsJoined,
                               LocalArrayFixedDimsJoined[0]);
         if (rank == 0)
             Print2DArray(LocalArrayFixedDimsJoined,
-                         vLocalArrayFixedDimsJoined->GetNSteps(),
+                         vLocalArrayFixedDimsJoined->m_AvailableSteps,
                          vLocalArrayFixedDimsJoined->m_Shape[0],
                          "LocalArrayFixedDimsJoined");
         Delete2DArray(LocalArrayFixedDimsJoined);
@@ -304,7 +301,7 @@ int main(int argc, char *argv[])
          */
         // inquiry about a variable, whose name we know
         adios::Variable<double> *vGlobalArray =
-            bpReader->InquireVariableDouble("GlobalArray");
+            bpReader->InquireVariable<double>("GlobalArray");
         std::cout << "GlobalArray [" << vGlobalArray->m_Shape[0] << "]";
         std::cout << " = Cannot read this variable yet...\n";
         if (vGlobalArray->m_Shape[0] != adios::IrregularDim)
diff --git a/examples/experimental/multistep/reader_stepping.cpp b/examples/experimental/multistep/reader_stepping.cpp
index dbb88b5f2c1e1648db7926b0f68a9ef440646c32..cdee26c1f57dfdb60bd963d54257d4da3370e742 100644
--- a/examples/experimental/multistep/reader_stepping.cpp
+++ b/examples/experimental/multistep/reader_stepping.cpp
@@ -26,9 +26,9 @@ int main(int argc, char *argv[])
     const bool adiosDebug = true;
 
 #ifdef ADIOS2_HAVE_MPI
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::WARN);
+    adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
 #else
-    adios::ADIOS adios(adios::Verbose::WARN);
+    adios::ADIOS adios(adios::DebugON);
 #endif
 
     // Info variables from the file
@@ -60,8 +60,8 @@ int main(int argc, char *argv[])
     {
         // Define method for engine creation
         // 1. Get method def from config file or define new one
-        adios::Method &bpReaderSettings = adios.DeclareMethod("input");
-        if (!bpReaderSettings.IsUserDefined())
+        adios::IO &bpReaderSettings = adios.DeclareIO("input");
+        if (!bpReaderSettings.InConfigFile())
         {
             // if not defined by user, we can change the default settings
             bpReaderSettings.SetEngine(
@@ -70,8 +70,9 @@ int main(int argc, char *argv[])
             // this is default, nothing to be done
         }
 
-        auto bpReader = adios.Open("myNumbers.bp", "r", bpReaderSettings);
-        if (bpReader != nullptr)
+        auto bpReader =
+            bpReaderSettings.Open("myNumbers.bp", adios::OpenMode::Read);
+        if (!bpReader)
         {
             int step = 0;
             while (bpReader->GetAdvanceStatus() == adios::AdvanceStatus::OK)
@@ -83,19 +84,19 @@ int main(int argc, char *argv[])
                 {
                     // read a Global scalar which has a single value in a step
                     adios::Variable<int> *vNproc =
-                        bpReader->InquireVariableInt("Nproc");
+                        bpReader->InquireVariable<int>("Nproc");
                     Nwriters = vNproc->m_Data[0];
                     std::cout << "# of writers = " << Nwriters << std::endl;
 
                     adios::Variable<unsigned int> *vNX =
-                        bpReader->InquireVariableUInt("NX");
+                        bpReader->InquireVariable<unsigned int>("NX");
                     Nx = vNX->m_Data[0];
                     // bpReader->Read<unsigned int>("NX", &Nx);
                     std::cout << "NX = " << Nx << std::endl;
                 }
 
                 adios::Variable<unsigned int> *vNY =
-                    bpReader->InquireVariableUInt("NY");
+                    bpReader->InquireVariable<unsigned int>("NY");
                 Ny = vNY->m_Data[0];
                 std::cout << "NY = " << Ny << std::endl;
 
@@ -115,27 +116,21 @@ int main(int argc, char *argv[])
     }
     catch (std::invalid_argument &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::ios_base::failure &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
     }
 
 #ifdef ADIOS2_HAVE_MPI
diff --git a/examples/experimental/multistep/writer_multistep.cpp b/examples/experimental/multistep/writer_multistep.cpp
index fce148ff74ed4e290dccf34926b08f84266daa77..dc2c4706492d19b2f29b4cd9f225aa36e1dcd9f5 100644
--- a/examples/experimental/multistep/writer_multistep.cpp
+++ b/examples/experimental/multistep/writer_multistep.cpp
@@ -32,9 +32,9 @@ int main(int argc, char *argv[])
     srand(rank * 32767);
 
 #ifdef ADIOS2_HAVE_MPI
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::WARN);
+    adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
 #else
-    adios::ADIOS adios(adios::Verbose::WARN);
+    adios::ADIOS adios(adios::DebugON);
 #endif
 
     // Application variables for output
@@ -61,88 +61,99 @@ int main(int argc, char *argv[])
 
     try
     {
+
+        // Define method for engine creation
+        // 1. Get method def from config file or define new one
+        adios::IO &bpWriterSettings = adios.DeclareIO("output");
+        if (!bpWriterSettings.InConfigFile())
+        {
+            // if not defined by user, we can change the default settings
+            bpWriterSettings.SetEngine("ADIOS1Writer");
+            // ISO-POSIX file is the default transport
+            // Passing parameters to the transport
+            bpWriterSettings.AddTransport("file"
+#ifdef ADIOS2_HAVE_MPI
+                                          ,
+                                          "library=MPI-IO"
+#endif
+                                          );
+            // Passing parameters to the engine
+            bpWriterSettings.SetParameters("have_metadata_file=yes");
+            // number of aggregators
+            // bpWriterSettings.SetParameters("Aggregation", (nproc + 1) / 2);
+        }
         /*
          * Define variables
          */
         // 1. Global value, constant across processes, constant over time
         adios::Variable<unsigned int> &varNX =
-            adios.DefineVariable<unsigned int>("NX");
-        adios::Variable<int> &varNproc = adios.DefineVariable<int>("Nproc");
+            bpWriterSettings.DefineVariable<unsigned int>("NX");
+        adios::Variable<int> &varNproc =
+            bpWriterSettings.DefineVariable<int>("Nproc");
 
         // 2. Local value, varying across processes, constant over time
         adios::Variable<int> &varProcessID =
-            adios.DefineVariable<int>("ProcessID", {adios::LocalValueDim});
+            bpWriterSettings.DefineVariable<int>("ProcessID",
+                                                 {adios::LocalValueDim});
 
-        // 3. Global array, global dimensions (shape), offsets (start) and local
+        // 3. Global array, global dimensions (shape), offsets (start) and
+        // local
         // dimensions (count)  are  constant over time
         adios::Variable<double> &varGlobalArrayFixedDims =
-            adios.DefineVariable<double>("GlobalArrayFixedDims", {nproc * Nx});
+            bpWriterSettings.DefineVariable<double>("GlobalArrayFixedDims",
+                                                    {nproc * Nx});
 
         // 4. Local array, local dimensions and offsets are
         // constant over time.
         // 4.a. Want to see this at reading as a bunch of local arrays
         adios::Variable<float> &varLocalArrayFixedDims =
-            adios.DefineVariable<float>("LocalArrayFixedDims", {}, {},
-                                        {LocalArrayFixedDims.size()});
+            bpWriterSettings.DefineVariable<float>(
+                "LocalArrayFixedDims", {}, {}, {LocalArrayFixedDims.size()});
         // 4.b. Joined array, a 1D array, with global dimension and offsets
         // calculated at read time
         adios::Variable<float> &varLocalArrayFixedDimsJoined =
-            adios.DefineVariable<float>("LocalArrayFixedDimsJoined",
-                                        {adios::JoinedDim}, {},
-                                        {LocalArrayFixedDims.size()});
+            bpWriterSettings.DefineVariable<float>(
+                "LocalArrayFixedDimsJoined", {adios::JoinedDim}, {},
+                {LocalArrayFixedDims.size()});
 
-        // 5. Global value, constant across processes, VARYING value over time
+        // 5. Global value, constant across processes, VARYING value over
+        // time
         adios::Variable<unsigned int> &varNY =
-            adios.DefineVariable<unsigned int>("NY");
+            bpWriterSettings.DefineVariable<unsigned int>("NY");
 
         // 6. Local value, varying across processes, VARYING over time
         adios::Variable<unsigned int> &varNparts =
-            adios.DefineVariable<unsigned int>("Nparts",
-                                               {adios::LocalValueDim});
+            bpWriterSettings.DefineVariable<unsigned int>(
+                "Nparts", {adios::LocalValueDim});
 
         // 7. Global array, dimensions and offsets are VARYING over time
         adios::Variable<double> &varGlobalArray =
-            adios.DefineVariable<double>("GlobalArray", {adios::UnknownDim});
+            bpWriterSettings.DefineVariable<double>("GlobalArray",
+                                                    {adios::UnknownDim});
 
         // 8. Local array, dimensions and offsets are VARYING over time
-        adios::Variable<float> &varIrregularArray = adios.DefineVariable<float>(
-            "Irregular", {}, {}, {adios::UnknownDim});
+        adios::Variable<float> &varIrregularArray =
+            bpWriterSettings.DefineVariable<float>("Irregular", {}, {},
+                                                   {adios::UnknownDim});
 
-        // add transform to variable in group...not executed (just testing API)
+        // add transform to variable in group...not executed (just testing
+        // API)
         // adios::Transform bzip2 = adios::transform::BZIP2();
         // varNice->AddTransform(bzip2, 1);
 
-        // Define method for engine creation
-        // 1. Get method def from config file or define new one
-        adios::Method &bpWriterSettings = adios.DeclareMethod("output");
-        if (!bpWriterSettings.IsUserDefined())
-        {
-            // if not defined by user, we can change the default settings
-            bpWriterSettings.SetEngine("ADIOS1Writer");
-            // ISO-POSIX file is the default transport
-            // Passing parameters to the transport
-            bpWriterSettings.AddTransport("File"
-#ifdef ADIOS2_HAVE_MPI
-                                          ,
-                                          "library=MPI-IO"
-#endif
-                                          );
-            // Passing parameters to the engine
-            bpWriterSettings.SetParameters("have_metadata_file", "yes");
-            // number of aggregators
-            // bpWriterSettings.SetParameters("Aggregation", (nproc + 1) / 2);
-        }
-
         // Open returns a smart pointer to Engine containing the Derived class
         // Writer
         // "w" means we overwrite any existing file on disk, but AdvanceStep
         // will
         // append steps later.
-        auto bpWriter = adios.Open("myNumbers.bp", "w", bpWriterSettings);
+        auto bpWriter =
+            bpWriterSettings.Open("myNumbers.bp", adios::OpenMode::Write);
 
-        if (bpWriter == nullptr)
+        if (!bpWriter)
+        {
             throw std::ios_base::failure(
                 "ERROR: failed to open ADIOS bpWriter\n");
+        }
 
         for (int step = 0; step < NSTEPS; step++)
         {
@@ -232,27 +243,21 @@ int main(int argc, char *argv[])
     }
     catch (std::invalid_argument &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::ios_base::failure &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
     }
 
 #ifdef ADIOS2_HAVE_MPI
diff --git a/examples/heatTransfer/CMakeLists.txt b/examples/heatTransfer/CMakeLists.txt
index 02e4cd30c850a0af1b3cd322cd386cb61a766109..09392deb58488b28cb45f1f71512678aa4bc12e9 100644
--- a/examples/heatTransfer/CMakeLists.txt
+++ b/examples/heatTransfer/CMakeLists.txt
@@ -3,5 +3,10 @@
 # accompanying file Copyright.txt for details.
 #------------------------------------------------------------------------------#
 
-add_subdirectory(write)
-add_subdirectory(read)
+
+if(ADIOS_USE_ADIOS1)
+  add_subdirectory(write)
+  add_subdirectory(read)
+endif()
+
+
diff --git a/examples/heatTransfer/read/heatRead_adios2.cpp b/examples/heatTransfer/read/heatRead_adios2.cpp
index 0bc88e911647f3166b9a2b451c6798484d47216c..93bc3faf9f691928114609678f9d8c6602a207c9 100644
--- a/examples/heatTransfer/read/heatRead_adios2.cpp
+++ b/examples/heatTransfer/read/heatRead_adios2.cpp
@@ -44,30 +44,32 @@ int main(int argc, char *argv[])
     MPI_Comm_rank(mpiReaderComm, &rank);
     MPI_Comm_size(mpiReaderComm, &nproc);
 
-    adios::ADIOS ad("adios2.xml", mpiReaderComm, adios::Verbose::INFO);
+    adios::ADIOS ad("adios2.xml", mpiReaderComm, adios::DebugON);
 
     // Define method for engine creation
     // 1. Get method def from config file or define new one
 
-    adios::Method &bpReaderSettings = ad.DeclareMethod("input");
-    if (!bpReaderSettings.IsUserDefined())
+    adios::IO &bpReaderIO = ad.DeclareIO("input");
+    if (!bpReaderIO.InConfigFile())
     {
         // if not defined by user, we can change the default settings
         // BPFileWriter is the default engine
-        bpReaderSettings.SetEngine("ADIOS1Reader");
-        // Allow an extra thread for data processing
-        bpReaderSettings.AllowThreads(1);
+        bpReaderIO.SetEngine("ADIOS1Reader");
+        bpReaderIO.SetParameters("num_threads=2");
+
         // ISO-POSIX file is the default transport
         // Passing parameters to the transport
-        bpReaderSettings.AddTransport("File", "verbose=4");
-        bpReaderSettings.SetParameters("OpenAsFile");
+        bpReaderIO.AddTransport("File", "verbose=4");
     }
 
-    auto bpReader = ad.Open(inputfile, "r", mpiReaderComm, bpReaderSettings);
+    auto bpReader =
+        bpReaderIO.Open(inputfile, adios::OpenMode::Read, mpiReaderComm);
 
-    if (bpReader == nullptr)
+    if (!bpReader)
+    {
         throw std::ios_base::failure("ERROR: failed to open " +
                                      std::string(inputfile) + "\n");
+    }
 
     unsigned int gndx;
     unsigned int gndy;
@@ -75,17 +77,19 @@ int main(int argc, char *argv[])
     // bpReader->Read<unsigned int>("gndy", &gndy);
 
     adios::Variable<unsigned int> *vgndx =
-        bpReader->InquireVariableUInt("gndx");
+        bpReader->InquireVariable<unsigned int>("gndx");
+
     gndx = vgndx->m_Data[0];
+
     adios::Variable<unsigned int> *vgndy =
-        bpReader->InquireVariableUInt("gndy");
+        bpReader->InquireVariable<unsigned int>("gndy");
     gndy = vgndy->m_Data[0];
 
     if (rank == 0)
     {
         std::cout << "gndx       = " << gndx << std::endl;
         std::cout << "gndy       = " << gndy << std::endl;
-        std::cout << "# of steps = " << vgndy->GetNSteps() << std::endl;
+        std::cout << "# of steps = " << vgndy->m_AvailableSteps << std::endl;
     }
 
     // 1D decomposition of the columns, which is inefficient for reading!
@@ -100,20 +104,20 @@ int main(int argc, char *argv[])
     std::cout << "rank " << rank << " reads " << readsize[1]
               << " columns from offset " << offset[1] << std::endl;
 
-    adios::Variable<double> *vT = bpReader->InquireVariableDouble("T");
+    adios::Variable<double> *vT = bpReader->InquireVariable<double>("T");
 
-    double *T = new double[vT->GetNSteps() * readsize[0] * readsize[1]];
+    double *T = new double[vT->m_AvailableSteps * readsize[0] * readsize[1]];
 
     // Create a 2D selection for the subset
     vT->SetSelection(offset, readsize);
-    vT->SetStepSelection(0, vT->GetNSteps());
+    vT->SetStepSelection(0, vT->m_AvailableSteps);
 
     // Arrays are read by scheduling one or more of them
     // and performing the reads at once
     bpReader->ScheduleRead<double>(*vT, T);
-    bpReader->PerformReads(adios::PerformReadMode::BLOCKINGREAD);
+    bpReader->PerformReads(adios::ReadMode::Blocking);
 
-    printData(T, readsize.data(), offset.data(), rank, vT->GetNSteps());
+    printData(T, readsize.data(), offset.data(), rank, vT->m_AvailableSteps);
     bpReader->Close();
     delete[] T;
     MPI_Finalize();
diff --git a/examples/heatTransfer/write/IO_adios1.cpp b/examples/heatTransfer/write/IO_adios1.cpp
index 95e0be201a853095b8f96b23a29653e6d1cfb0bc..caba2796b3d8206d95606b6f201ce2b571dea3eb 100644
--- a/examples/heatTransfer/write/IO_adios1.cpp
+++ b/examples/heatTransfer/write/IO_adios1.cpp
@@ -30,7 +30,7 @@ IO::IO(const Settings &s, MPI_Comm comm)
     m_outputfilename = s.outputfile + ".bp";
     adios_init_noxml(comm);
     adios_declare_group(&group, "heat", "", adios_stat_default);
-    adios_select_method(group, "MPI", "", "");
+    adios_select_method(group, "POSIX", "", "");
 
     adios_define_var(group, "gndx", "", adios_integer, "", "", "");
     adios_define_var(group, "gndy", "", adios_integer, "", "", "");
diff --git a/examples/heatTransfer/write/IO_adios2.cpp b/examples/heatTransfer/write/IO_adios2.cpp
index 13fd9a45cd9f26cd7a73d520dde7806598d389e7..7db73cacc27d93321931fad49e2c6e1a15c2a789 100644
--- a/examples/heatTransfer/write/IO_adios2.cpp
+++ b/examples/heatTransfer/write/IO_adios2.cpp
@@ -24,35 +24,26 @@ IO::IO(const Settings &s, MPI_Comm comm)
 {
     rank_saved = s.rank;
     m_outputfilename = s.outputfile + ".bp";
-    ad = new adios::ADIOS("adios2.xml", comm, adios::Verbose::INFO);
+    ad = new adios::ADIOS("config.xml", comm, adios::DebugON);
 
     // Define method for engine creation
-    // 1. Get method def from config file or define new one
 
-    adios::Method &bpWriterSettings = ad->DeclareMethod("output");
-    if (!bpWriterSettings.IsUserDefined())
+    adios::IO &bpio = ad->DeclareIO("output");
+    if (!bpio.InConfigFile())
     {
         // if not defined by user, we can change the default settings
         // BPFileWriter is the default engine
-        bpWriterSettings.SetEngine("ADIOS1Writer");
+
         // Allow an extra thread for data processing
-        bpWriterSettings.AllowThreads(1);
         // ISO-POSIX file is the default transport
         // Passing parameters to the transport
-        bpWriterSettings.AddTransport("File", "library=MPI-IO");
-
-        const std::string aggregatorsParam("Aggregators=" +
-                                           std::to_string((s.nproc + 1) / 2));
-        bpWriterSettings.SetParameters("have_metadata_file=yes",
-                                       aggregatorsParam);
     }
 
-    //    ad->DefineScalar<unsigned int>("gndx", true);
-    varGndx = &ad->DefineVariable<unsigned int>("gndx");
-    ad->DefineVariable<unsigned int>("gndy");
+    varGndx = &bpio.DefineVariable<unsigned int>("gndx");
+    bpio.DefineVariable<unsigned int>("gndy");
 
     // define T as 2D global array
-    varT = &ad->DefineArray<double>(
+    varT = &bpio.DefineVariable<double>(
         "T",
         // Global dimensions
         {s.gndx, s.gndy},
@@ -66,10 +57,12 @@ IO::IO(const Settings &s, MPI_Comm comm)
     // varT.AddTransform( tr, "" );
     // varT.AddTransform( tr,"accuracy=0.001" );  // for ZFP
 
-    bpWriter = ad->Open(m_outputfilename, "w", comm, bpWriterSettings);
+    bpWriter = bpio.Open(m_outputfilename, adios::OpenMode::Write, comm);
 
-    if (bpWriter == nullptr)
+    if (!bpWriter)
+    {
         throw std::ios_base::failure("ERROR: failed to open ADIOS bpWriter\n");
+    }
 }
 
 IO::~IO()
diff --git a/examples/heatTransfer/write/IO_ph5_adios2.cpp b/examples/heatTransfer/write/IO_ph5_adios2.cpp
index e694d9f291698cbb51f4bc8b0e304e32d6d90e1f..01fca5621dc5fdb1c3a193511f08525cbe61d077 100644
--- a/examples/heatTransfer/write/IO_ph5_adios2.cpp
+++ b/examples/heatTransfer/write/IO_ph5_adios2.cpp
@@ -24,46 +24,44 @@ IO::IO(const Settings &s, MPI_Comm comm)
 {
     rank_saved = s.rank;
     m_outputfilename = s.outputfile + ".h5";
-    // adios::ADIOS adios(comm, adios::Verbose::INFO, false);
-    ad = new adios::ADIOS(comm, adios::Verbose::INFO, false);
+    ad = new adios::ADIOS(comm, adios::DebugOFF);
 
     // Define method for engine creation
     // 1. Get method def from config file or define new one
 
-    adios::Method &h5writerSettings = ad->DeclareMethod("output");
-    if (!h5writerSettings.IsUserDefined())
+    adios::IO &h5io = ad->DeclareIO("output");
+    if (!h5io.InConfigFile())
     {
         // if not defined by user, we can change the default settings
         // BPFileWriter is the default engine
-        h5writerSettings.SetEngine("HDF5Writer");
+        h5io.SetEngine("HDF5Writer");
         // Allow an extra thread for data processing
 
         const std::string aggregatorsParam("Aggregators=" +
                                            std::to_string((s.nproc + 1) / 2));
-        h5writerSettings.SetParameters("have_metadata_file=yes",
-                                       aggregatorsParam);
+        h5io.SetParameters("have_metadata_file=yes", aggregatorsParam);
     }
 
     //    ad->DefineScalar<unsigned int>("gndx", true);
-    varGndx = &(ad->DefineVariable<unsigned int>("gndx"));
-    ad->DefineVariable<unsigned int>("gndy");
+    varGndx = &h5io.DefineVariable<unsigned int>("gndx");
+    h5io.DefineVariable<unsigned int>("gndy");
 
     // define T as 2D global array
-    varT = &(ad->DefineArray<double>(
+    varT = &h5io.DefineVariable<double>(
         "T",
         // Global dimensions
         {s.gndx, s.gndy},
         // starting offset of the local array in the global space
         {s.offsx, s.offsy},
         // local size, could be defined later using SetSelection()
-        {s.ndx, s.ndy}));
+        {s.ndx, s.ndy});
 
     // add transform to variable
     // adios::Transform tr = adios::transform::BZIP2( );
     // varT.AddTransform( tr, "" );
     // varT.AddTransform( tr,"accuracy=0.001" );  // for ZFP
 
-    h5writer = ad->Open(m_outputfilename, "w", comm, h5writerSettings);
+    h5writer = h5io.Open(m_outputfilename, adios::OpenMode::Write, comm);
 
     if (h5writer == nullptr)
         throw std::ios_base::failure("ERROR: failed to open ADIOS h5writer\n");
diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt
index 6719c2042ff03407a28f5e4e27c7402a2463c5d2..d01f1256fc13d301d7616c0ddf55547b8fce2b23 100644
--- a/examples/hello/CMakeLists.txt
+++ b/examples/hello/CMakeLists.txt
@@ -4,7 +4,7 @@
 #------------------------------------------------------------------------------#
 
 add_subdirectory(bpWriter)
-add_subdirectory(timeBP)
+add_subdirectory(bpTimeWriter)
 
 if(ADIOS_USE_ADIOS1)
   add_subdirectory(adios1Writer)
diff --git a/examples/hello/README.md b/examples/hello/README.md
index 0c780bd6b2830759ef4f16846646dd326d3e0404..c08d40e97f23217ddf2cbf34cf72c670c8d901d7 100644
--- a/examples/hello/README.md
+++ b/examples/hello/README.md
@@ -1,13 +1,15 @@
 examples/hello 
 
-Provides tests and illustrates how to use very basic functionality for a new component in adios2
-
+Provides tests and illustrates how to use very basic functionality in adios2
 
 * adios1Writer (ADIOS_USE_ADIOS1=ON)
-	1. Write BP format files using adios1 library through adios2 interface  
+    1. Write BP format files using adios1 library through adios2 interface  
 	
 * bpWriter
-    1. Write BP format files 
+    1. Write BP format files for one Variable
+    
+* bpTimeWriter
+    1. Write BP format files for two Variables (one is timestep) using time aggregation
     
 * datamanReader (to be deprecated, ADIOS_USE_DataMan=ON)
     1. Read real-time WAN streams using dataman
diff --git a/examples/hello/adios1Writer/helloADIOS1Writer.cpp b/examples/hello/adios1Writer/helloADIOS1Writer.cpp
index 7403775dfe897f2e0ffbdc7fc3e3f8cb07066672..1041f895cafe00c998b1adc4a7d8a3dc7486e604 100644
--- a/examples/hello/adios1Writer/helloADIOS1Writer.cpp
+++ b/examples/hello/adios1Writer/helloADIOS1Writer.cpp
@@ -2,118 +2,86 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloWriter.cpp
+ * helloADIOS1Writer.cpp : Simple self-descriptive example of how to write a
+ * variable to a ADIOS1 BP File that lives in several MPI processes. Test runs
+ * when ADIOS2 is linked with ADIOS1 library
  *
  *  Created on: Feb 16, 2017
- *      Author: wfg
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
  */
 
-#include <iostream>
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <stdexcept> //std::invalid_argument std::exception
 #include <vector>
 
-#include <mpi.h>
-
 #include <adios2.h>
+#ifdef ADIOS2_HAVE_MPI
+#include <mpi.h>
+#endif
 
 int main(int argc, char *argv[])
 {
     MPI_Init(&argc, &argv);
-    int rank, nproc;
+    int rank = 0, size = 1;
+#ifdef ADIOS2_HAVE_MPI
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
-    const bool adiosDebug = true;
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::INFO, adiosDebug);
-
-    // Application variable
-    float frank = (float)rank;
-    std::vector<double> myDoubles = {
-        frank,        frank + 0.1f, frank + 0.2f, frank + 0.3f, frank + 0.4f,
-        frank + 0.5f, frank + 0.6f, frank + 0.7f, frank + 0.8f, frank + 0.9f};
-    const std::size_t Nx = myDoubles.size();
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
+#endif
 
-    const std::size_t rows = 3;
-    const std::size_t columns = 3;
-
-    std::vector<float> myMatrix;
-    myMatrix.reserve(rows * columns);
-    myMatrix.push_back(frank + 0.0);
-    myMatrix.push_back(frank + 0.1), myMatrix.push_back(frank + 0.2);
-    myMatrix.push_back(frank + 0.3);
-    myMatrix.push_back(frank + 0.4), myMatrix.push_back(frank + 0.5);
-    myMatrix.push_back(frank + 0.6);
-    myMatrix.push_back(frank + 0.7), myMatrix.push_back(frank + 0.8);
-
-    frank = -(float)rank;
-    std::vector<float> myMatrix2 = {frank - 0.1f, frank - 0.2f, frank - 0.3f,
-                                    frank - 0.4f, frank - 0.5f, frank - 0.6f,
-                                    frank - 0.7f, frank - 0.8f, frank - 0.9f};
+    /** Application variable */
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
 
     try
     {
-        // Define variable and local size
-        adios::Variable<double> &ioMyDoubles = adios.DefineVariable<double>(
-            "myDoubles", {nproc, Nx}, {rank, 0}, {1, Nx});
-        adios::Variable<float> &ioMyMatrix =
-            adios.DefineVariable<float>("myMatrix", {nproc * rows, columns},
-                                        {rank * rows, 0}, {rows, columns});
-        adios::Variable<float> &ioMyMatrix2 =
-            adios.DefineVariable<float>("myMatrix2", {rows, nproc * columns},
-                                        {0, rank * columns}, {rows, columns});
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &bpWriterSettings = adios.DeclareMethod("hello");
-        bpWriterSettings.SetEngine("ADIOS1Writer");
-        bpWriterSettings.SetParameters("profile_units=mus");
-        bpWriterSettings.SetIOMode(adios::IOMode::COLLECTIVE);
-        bpWriterSettings.AddTransport(
-            "File", "profile_units=mus",
-            "have_metadata_file=no"); // uses default POSIX library
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &adios1IO = adios.DeclareIO("ADIOS1IO");
+        adios1IO.SetEngine("ADIOS1Writer");
+        adios1IO.AddTransport("file", "library=MPI");
 
-        // Create engine smart pointer due to polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // Writer
-        auto bpWriter = adios.Open("hello_adios1.bp", "w", bpWriterSettings);
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios::Variable<float> &bpFloats = adios1IO.DefineVariable<float>(
+            "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios::ConstantDims);
 
-        if (bpWriter == nullptr)
-            throw std::ios_base::failure(
-                "ERROR: couldn't create bpWriter at Open\n");
+        /** Engine derived class, spawned to start IO operations */
+        auto adios1Writer =
+            adios1IO.Open("myVector.bp", adios::OpenMode::Write);
 
-        bpWriter->Write<double>(ioMyDoubles,
-                                myDoubles.data()); // Base class Engine
-                                                   // own the Write<T>
-                                                   // that will call
-                                                   // overloaded Write
-                                                   // from Derived
+        if (!adios1Writer)
+        {
+            throw std::ios_base::failure(
+                "ERROR: adios1Writer not created at Open\n");
+        }
 
-        bpWriter->Write<float>(ioMyMatrix, myMatrix.data());
-        bpWriter->Write<float>(ioMyMatrix2, myMatrix2.data());
+        /** Write variable for buffering */
+        adios1Writer->Write<float>(bpFloats, myFloats.data());
 
-        bpWriter->Close();
+        /** Create bp file, engine becomes unreachable after this*/
+        adios1Writer->Close();
     }
     catch (std::invalid_argument &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::ios_base::failure &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
     }
 
     MPI_Finalize();
diff --git a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp
index 89487cf289afe720309b3f6885d15bdcb4d884f3..46c03b898025cf7677c4fa7f4d1dcfe156a917d9 100644
--- a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp
+++ b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp
@@ -2,10 +2,10 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloADIOSNoXML_OOP.cpp
+ * helloADIOS1Writer_nompi.cpp : non mpi version of helloADIOS1Writer
  *
  *  Created on: Jan 9, 2017
- *      Author: wfg
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
  */
 
 #include <iostream>
@@ -15,65 +15,41 @@
 
 int main(int argc, char *argv[])
 {
-    const bool adiosDebug = true;
-    adios::ADIOS adios(adios::Verbose::INFO, adiosDebug);
-
-    // Application variable
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    const std::size_t rows = 3;
-    const std::size_t columns = 3;
-    std::vector<float> myMatrix = {1, 2, 3, 4, 5, 6, 7, 8, 9};
-
-    std::vector<float> myMatrix2 = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
+    /** Application variable */
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
 
     try
     {
-        // Define variable and local size
-        adios::Variable<double> &ioMyDoubles =
-            adios.DefineVariable<double>("myDoubles", adios::Dims{Nx});
-        adios::Variable<float> &ioMyMatrix =
-            adios.DefineVariable<float>("myMatrix", adios::Dims{rows, columns});
-        adios::Variable<float> &ioMyMatrix2 = adios.DefineVariable<float>(
-            "myMatrix2", adios::Dims{rows, columns});
-        adios::Variable<float> &ioMyMatrix3 = adios.DefineVariable<float>(
-            "myMatrix3", adios::Dims{rows, columns});
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(adios::DebugON);
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &adios1IO = adios.DeclareIO("ADIOS1IO");
+        adios1IO.SetEngine("ADIOS1Writer");
+        adios1IO.AddTransport("file");
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &bpWriterSettings = adios.DeclareMethod("hello");
-        bpWriterSettings.SetIOMode(adios::IOMode::COLLECTIVE);
-        bpWriterSettings.SetParameters("profile_units=mus");
-        bpWriterSettings.AddTransport("File", "have_metadata_file=yes",
-                                      "profile_units=mus");
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios::Variable<float> &bpFloats = adios1IO.DefineVariable<float>(
+            "bpFloats", {}, {}, {Nx}, adios::ConstantDims);
 
-        // Create engine smart pointer due to polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // Writer
-        auto bpFileWriter =
-            adios.Open("hello_adios1_nompi.bp", "w", bpWriterSettings);
+        /** Engine derived class, spawned to start IO operations */
+        auto adios1Writer =
+            adios1IO.Open("myVector.bp", adios::OpenMode::Write);
 
-        if (bpFileWriter == nullptr)
+        if (!adios1Writer)
+        {
             throw std::ios_base::failure(
-                "ERROR: couldn't create bpWriter at Open\n");
+                "ERROR: hdf5Writer not created at Open\n");
+        }
 
-        ioMyDoubles.SetSelection({0}, {Nx});
-        adios::SelectionBoundingBox box({0, 0}, {rows, columns});
-        ioMyMatrix.SetSelection(box);
-        ioMyMatrix2.SetSelection(box);
-        ioMyMatrix3.SetSelection(box);
+        /** Write variable for buffering */
+        adios1Writer->Write<float>(bpFloats, myFloats.data());
 
-        bpFileWriter->Write<double>(
-            ioMyDoubles,
-            myDoubles.data()); // Base class Engine own the Write<T>
-                               // that will call overloaded Write from
-                               // Derived
-        bpFileWriter->Write<float>(ioMyMatrix, myMatrix.data());   // 2d Example
-        bpFileWriter->Write<float>(ioMyMatrix2, myMatrix2.data()); // 2d Example
-        bpFileWriter->Write<float>(ioMyMatrix3, myMatrix2.data()); // 2d Example
-        bpFileWriter->Close();
-        //
+        /** Create bp file, engine becomes unreachable after this*/
+        adios1Writer->Close();
     }
     catch (std::invalid_argument &e)
     {
diff --git a/examples/hello/timeBP/CMakeLists.txt b/examples/hello/bpTimeWriter/CMakeLists.txt
similarity index 55%
rename from examples/hello/timeBP/CMakeLists.txt
rename to examples/hello/bpTimeWriter/CMakeLists.txt
index 7f5d44cc2a63e2c1d4d09cbc51634ce8b6acab62..f95bd367c6bdf59d1fba09f245f2f58c6c11bd7d 100644
--- a/examples/hello/timeBP/CMakeLists.txt
+++ b/examples/hello/bpTimeWriter/CMakeLists.txt
@@ -6,10 +6,10 @@
 if(ADIOS_USE_MPI)
   find_package(MPI COMPONENTS C REQUIRED)
 
-  add_executable(hello_timeBPWriter timeBPWriter.cpp)
-  target_include_directories(hello_timeBPWriter PRIVATE ${MPI_C_INCLUDE_PATH})
-  target_link_libraries(hello_timeBPWriter ${MPI_C_LIBRARIES})
+  add_executable(hello_bpTimeWriter helloBPTimeWriter.cpp)
+  target_include_directories(hello_bpTimeWriter PRIVATE ${MPI_C_INCLUDE_PATH})
+  target_link_libraries(hello_bpTimeWriter ${MPI_C_LIBRARIES})
 else()
-  add_executable(hello_timeBPWriter timeBPWriter_nompi.cpp)
+  add_executable(hello_bpTimeWriter helloBPTimeWriter_nompi.cpp)
 endif()
-target_link_libraries(hello_timeBPWriter adios2)
+target_link_libraries(hello_bpTimeWriter adios2)
diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c9290c5bc0e521c2366f2525fcf75631876b9017
--- /dev/null
+++ b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp
@@ -0,0 +1,98 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloBPTimeWriter.cpp  example for writing a variable using the Advance
+ * function for time aggregation. Time step is saved as an additional (global)
+ * single value variable, just for tracking purposes.
+ *
+ *  Created on: Feb 16, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include <algorithm> //std::for_each
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <mpi.h>
+#include <stdexcept> //std::invalid_argument std::exception
+#include <vector>
+
+#include <adios2.h>
+
+int main(int argc, char *argv[])
+{
+    MPI_Init(&argc, &argv);
+    int rank, size;
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
+
+    // Application variable
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
+
+    try
+    {
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &bpIO = adios.DeclareIO("BPFile_N2N");
+
+        /** global array: name, { shape (total dimensions) }, { start (local) },
+         * { count (local) }, all are constant dimensions */
+        adios::Variable<float> &bpFloats = bpIO.DefineVariable<float>(
+            "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios::ConstantDims);
+
+        /** global single value variable: name */
+        adios::Variable<unsigned int> &bpTimeStep =
+            bpIO.DefineVariable<unsigned int>("timeStep");
+
+        /** Engine derived class, spawned to start IO operations */
+        auto bpWriter = bpIO.Open("myVector.bp", adios::OpenMode::Write);
+
+        if (!bpWriter)
+        {
+            throw std::ios_base::failure(
+                "ERROR: bpWriter not created at Open\n");
+        }
+
+        for (unsigned int timeStep = 0; timeStep < 10; ++timeStep)
+        {
+            if (rank == 0) // global single value, only saved by rank 0
+            {
+                bpWriter->Write<unsigned int>(bpTimeStep, timeStep);
+            }
+
+            myFloats[0] = timeStep;
+
+            // template type is optional, but recommended
+            bpWriter->Write<float>(bpFloats, myFloats.data());
+            bpWriter->Advance();
+        }
+
+        bpWriter->Close();
+    }
+    catch (std::invalid_argument &e)
+    {
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
+    }
+    catch (std::ios_base::failure &e)
+    {
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
+    }
+    catch (std::exception &e)
+    {
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
+    }
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..84b531107dacd21ab262465773dc96c1355135af
--- /dev/null
+++ b/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp
@@ -0,0 +1,79 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloBPTimeWriter_nompi.cpp  no mpi version of helloBPTimeWriter.cpp
+ *
+ *  Created on: Feb 16, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <stdexcept> //std::invalid_argument std::exception
+#include <vector>
+
+#include <adios2.h>
+
+int main(int argc, char *argv[])
+{
+    // Application variable
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
+
+    try
+    {
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(adios::DebugON);
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &bpIO = adios.DeclareIO("BPFile_N2N");
+
+        /** name, { shape (total dimensions) }, { start (local) }, { count
+         * {local} } */
+        adios::Variable<float> &bpFloats = bpIO.DefineVariable<float>(
+            "bpFloats", {}, {}, {Nx}, adios::ConstantDims);
+
+        adios::Variable<unsigned int> &bpTimeStep =
+            bpIO.DefineVariable<unsigned int>("timeStep");
+
+        /** Engine derived class, spawned to start IO operations */
+        auto bpWriter = bpIO.Open("myVector.bp", adios::OpenMode::Write);
+
+        if (!bpWriter)
+        {
+            throw std::ios_base::failure(
+                "ERROR: bpWriter not created at Open\n");
+        }
+
+        for (unsigned int timeStep = 0; timeStep < 10; ++timeStep)
+        {
+            // template type is optional but recommended
+            bpWriter->Write<unsigned int>(bpTimeStep, timeStep);
+
+            myFloats[0] = timeStep;
+            bpWriter->Write<float>(bpFloats, myFloats.data());
+            bpWriter->Advance();
+        }
+
+        bpWriter->Close();
+    }
+    catch (std::invalid_argument &e)
+    {
+        std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
+        std::cout << e.what() << "\n";
+    }
+    catch (std::ios_base::failure &e)
+    {
+        std::cout << "IO System base failure exception, STOPPING PROGRAM\n";
+        std::cout << e.what() << "\n";
+    }
+    catch (std::exception &e)
+    {
+        std::cout << "Exception, STOPPING PROGRAM from rank\n";
+        std::cout << e.what() << "\n";
+    }
+
+    return 0;
+}
diff --git a/examples/hello/bpWriter/helloBPWriter.cpp b/examples/hello/bpWriter/helloBPWriter.cpp
index 61dcf2854aa0cd3742acc8a584da884491006adf..3d250b3b14912ed494ff8ad34e5ef5877a5dc7d2 100644
--- a/examples/hello/bpWriter/helloBPWriter.cpp
+++ b/examples/hello/bpWriter/helloBPWriter.cpp
@@ -2,122 +2,78 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloWriter.cpp
+ * helloBPWriter.cpp: Simple self-descriptive example of how to write a variable
+ * to a BP File that lives in several MPI processes.
  *
  *  Created on: Feb 16, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#include <iostream>
-#include <vector>
-
+#include <ios>      //std::ios_base::failure
+#include <iostream> //std::cout
 #include <mpi.h>
+#include <stdexcept> //std::invalid_argument std::exception
+#include <vector>
 
 #include <adios2.h>
 
 int main(int argc, char *argv[])
 {
     MPI_Init(&argc, &argv);
-    int rank, nproc;
+    int rank, size;
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
 
-    const bool adiosDebug = true;
-    adios::ADIOS adios("config.xml", MPI_COMM_WORLD, adios::Verbose::INFO,
-                       adiosDebug);
-
-    // Application variable
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    const std::size_t rows = 3;
-    const std::size_t columns = 3;
-
-    std::vector<float> myMatrix;
-    if (rank % 2 == 0) // even rank
-    {
-        myMatrix.reserve(rows * columns);
-        myMatrix.push_back(1);
-        myMatrix.push_back(2), myMatrix.push_back(3);
-        myMatrix.push_back(4);
-        myMatrix.push_back(5), myMatrix.push_back(6);
-        myMatrix.push_back(7);
-        myMatrix.push_back(8), myMatrix.push_back(8);
-    }
-
-    std::vector<float> myMatrix2 = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
+    /** Application variable */
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
 
     try
     {
-        // Define variable and local size
-        adios::Variable<double> &ioMyDoubles = adios.DefineVariable<double>(
-            "myDoubles", {nproc, Nx}, {rank, 0}, {1, Nx});
-        adios::Variable<float> &ioMyMatrix =
-            adios.DefineVariable<float>("myMatrix", {nproc * rows, columns},
-                                        {rank * rows, 0}, {rows, columns});
-        adios::Variable<float> &ioMyMatrix2 =
-            adios.DefineVariable<float>("myMatrix2", {rows, nproc * columns},
-                                        {0, rank * columns}, {rows, columns});
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &bpWriterSettings =
-            adios.DeclareMethod("Output"); // Output is defined in config.xml
-        if (!bpWriterSettings.IsUserDefined())
-        {
-            bpWriterSettings.SetParameters("profile_units=mus");
-            bpWriterSettings.AddTransport(
-                "File", "profile_units=mus",
-                "have_metadata_file=no"); // uses default POSIX library
-        }
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &bpIO = adios.DeclareIO("BPFile_N2N");
 
-        // Create engine smart pointer due to polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // Writer
-        auto bpWriter = adios.Open("myDoubles.bp", "w", bpWriterSettings);
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios::Variable<float> &bpFloats = bpIO.DefineVariable<float>(
+            "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios::ConstantDims);
 
-        if (bpWriter == nullptr)
-            throw std::ios_base::failure(
-                "ERROR: couldn't create bpWriter at Open\n");
-
-        bpWriter->Write<double>(ioMyDoubles,
-                                myDoubles.data()); // Base class Engine
-                                                   // own the Write<T>
-                                                   // that will call
-                                                   // overloaded Write
-                                                   // from Derived
+        /** Engine derived class, spawned to start IO operations */
+        auto bpWriter = bpIO.Open("myVector.bp", adios::OpenMode::Write);
 
-        if (rank % 2 == 0) // even rank
+        if (!bpWriter)
         {
-            bpWriter->Write<float>(ioMyMatrix, myMatrix.data());
-            bpWriter->Write<float>(ioMyMatrix2, myMatrix2.data());
+            throw std::ios_base::failure(
+                "ERROR: bpWriter not created at Open\n");
         }
 
+        /** Write variable for buffering */
+        bpWriter->Write<float>(bpFloats, myFloats.data());
+
+        /** Create bp file, engine becomes unreachable after this*/
         bpWriter->Close();
     }
     catch (std::invalid_argument &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::ios_base::failure &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
     }
 
     MPI_Finalize();
diff --git a/examples/hello/bpWriter/helloBPWriter_nompi.cpp b/examples/hello/bpWriter/helloBPWriter_nompi.cpp
index 9acc0b5a2104db9d6ae27aec68d88a1baa8612b1..b9ba169e39342e8faec177d3c09b4e63f48e0ab2 100644
--- a/examples/hello/bpWriter/helloBPWriter_nompi.cpp
+++ b/examples/hello/bpWriter/helloBPWriter_nompi.cpp
@@ -2,82 +2,53 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloADIOSNoXML_OOP.cpp
+ * helloBPWriter_nompi.cpp sequential non-mpi version of helloBPWriter
  *
  *  Created on: Jan 9, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#include <ios>
-#include <iostream>
-#include <stdexcept>
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <stdexcept> //std::invalid_argument std::exception
 #include <vector>
 
 #include <adios2.h>
 
-int main(int /*argc*/, char ** /*argv*/)
+int main(int argc, char *argv[])
 {
-    const bool adiosDebug = true;
-    adios::ADIOS adios(adios::Verbose::WARN, adiosDebug);
-
-    // Application variable
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    const std::size_t rows = 3;
-    const std::size_t columns = 3;
-    std::vector<float> myMatrix = {1, 2, 3, 4, 5, 6, 7, 8, 9};
-
-    std::vector<float> myMatrix2 = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
+    /** Application variable */
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
 
     try
     {
-        // Define variable and local size
-        adios::Variable<double> &ioMyDoubles =
-            adios.DefineVariable<double>("myDoubles", adios::Dims{Nx});
-        adios::Variable<float> &ioMyMatrix =
-            adios.DefineVariable<float>("myMatrix", adios::Dims{rows, columns});
-        adios::Variable<float> &ioMyMatrix2 = adios.DefineVariable<float>(
-            "myMatrix2", adios::Dims{rows, columns});
-        adios::Variable<float> &ioMyMatrix3 = adios.DefineVariable<float>(
-            "myMatrix3", adios::Dims{rows, columns});
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(adios::DebugON);
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &bpIO = adios.DeclareIO("BPFile_N2N");
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &bpWriterSettings = adios.DeclareMethod(
-            "SinglePOSIXFile"); // default method type is Writer
-        bpWriterSettings.SetParameters("profile_units=mus");
-        bpWriterSettings.AddTransport("File", "have_metadata_file=yes",
-                                      "profile_units=mus");
+        /** global array: name, { shape (total dimensions) }, { start (local) },
+         * { count (local) }, all are constant dimensions */
+        adios::Variable<float> &bpFloats = bpIO.DefineVariable<float>(
+            "bpFloats", {}, {}, {Nx}, adios::ConstantDims);
 
-        // Create engine smart pointer due to polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // Writer
-        auto bpFileWriter =
-            adios.Open("myDoubles_nompi.bp", "w", bpWriterSettings);
+        /** Engine derived class, spawned to start IO operations */
+        auto bpWriter = bpIO.Open("myVector.bp", adios::OpenMode::Write);
 
-        if (bpFileWriter == nullptr)
+        if (!bpWriter)
         {
             throw std::ios_base::failure(
-                "ERROR: couldn't create bpWriter at Open\n");
+                "ERROR: bpWriter not created at Open\n");
         }
 
-        ioMyDoubles.SetSelection({0}, {Nx});
-        adios::SelectionBoundingBox box({0, 0}, {rows, columns});
-        ioMyMatrix.SetSelection(box);
-        ioMyMatrix2.SetSelection(box);
-        ioMyMatrix3.SetSelection(box);
+        /** Write variable for buffering */
+        bpWriter->Write<float>(bpFloats, myFloats.data());
 
-        bpFileWriter->Write<double>(
-            ioMyDoubles,
-            myDoubles.data()); // Base class Engine own the Write<T>
-                               // that will call overloaded Write from
-                               // Derived
-        bpFileWriter->Write<float>(ioMyMatrix, myMatrix.data());   // 2d Example
-        bpFileWriter->Write<float>(ioMyMatrix2, myMatrix2.data()); // 2d Example
-        bpFileWriter->Write<float>(ioMyMatrix3, myMatrix2.data()); // 2d Example
-        bpFileWriter->Close();
-        //
+        /** Create bp file, engine becomes unreachable after this*/
+        bpWriter->Close();
     }
     catch (std::invalid_argument &e)
     {
@@ -86,12 +57,12 @@ int main(int /*argc*/, char ** /*argv*/)
     }
     catch (std::ios_base::failure &e)
     {
-        std::cout << "System exception, STOPPING PROGRAM\n";
+        std::cout << "IO System base failure exception, STOPPING PROGRAM\n";
         std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        std::cout << "Exception, STOPPING PROGRAM\n";
+        std::cout << "Exception, STOPPING PROGRAM from rank\n";
         std::cout << e.what() << "\n";
     }
 
diff --git a/examples/hello/datamanReader/helloDataManReader.cpp b/examples/hello/datamanReader/helloDataManReader.cpp
index 336bc0a779502415cbcc56c8372e113ee56df832..7dc984af37870f05187ff1fbd073a226b11f5d16 100644
--- a/examples/hello/datamanReader/helloDataManReader.cpp
+++ b/examples/hello/datamanReader/helloDataManReader.cpp
@@ -2,26 +2,22 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloDataManReader.cpp
+ * helloDataManReader_nompi.cpp
  *
- *  Created on: Feb 16, 2017
- *      Author: wfg
+ *  Created on: Jan 9, 2017
+ *      Author: Jason Wang
  */
 
-#include <functional> //std::multiplies
-#include <iostream>   //std::cout, std::endl
-#include <numeric>    //std::accumulate
-#include <string>
+#include <iostream>
+#include <numeric>
 #include <vector>
 
-#include <mpi.h>
-
 #include <adios2.h>
 
-void getcb(const void *data, std::string doid, std::string var,
-           std::string dtype, std::vector<std::size_t> varshape)
+void UserCallBack(const void *data, std::string doid, std::string var,
+                  std::string dtype, std::vector<std::size_t> varshape)
 {
-    std::cout << "data object ID = " << doid << "\n"; // do you need to flush?
+    std::cout << "data object ID = " << doid << "\n";
     std::cout << "variable name = " << var << "\n";
     std::cout << "data type = " << dtype << "\n";
 
@@ -35,73 +31,63 @@ void getcb(const void *data, std::string doid, std::string var,
 
 int main(int argc, char *argv[])
 {
+    // Application variable
     MPI_Init(&argc, &argv);
-    int rank;
+    int rank, size;
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-    const bool adiosDebug = true;
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::WARN, adiosDebug);
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
 
     try
     {
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &datamanSettings = adios.DeclareMethod("WAN");
-        if (!datamanSettings.IsUserDefined())
-        {
-            // if not defined by user, we can change the default settings
-            datamanSettings.SetEngine("DataManReader");
-            datamanSettings.SetParameters("peer-to-peer=yes");
-            datamanSettings.AddTransport("Mdtm", "localIP=127.0.0.1",
-                                         "remoteIP=127.0.0.1",
-                                         "tolerances=1,2,3");
-            // datamanSettings.AddTransport( "ZeroMQ", "localIP=127.0.0.1",
-            // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); not yet supported
-            // ,
-            // will throw an exception
-        }
+        adios::ADIOS adios(adios::DebugON);
 
-        // Create engine smart pointer to DataManReader Engine due to
-        // polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // DataManReader
-        auto datamanReader = adios.Open("myDoubles.bp", "r", datamanSettings);
+        adios::IO &dataManIO = adios.DeclareIO("WAN");
+        dataManIO.SetEngine("DataManReader");
+        dataManIO.SetParameters("real_time=yes", "method_type=stream",
+                                "method=dump");
+        auto dataManReader =
+            dataManIO.Open("myDoubles.bp", adios::OpenMode::Read);
 
-        if (datamanReader == nullptr)
+        if (!dataManReader)
+        {
             throw std::ios_base::failure(
                 "ERROR: failed to create DataMan I/O engine at Open\n");
+        }
 
-        datamanReader->SetCallBack(getcb);
+        dataManReader->SetCallBack(UserCallBack);
+
+        for (unsigned int i = 0; i < 3; ++i)
+        {
+            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+        }
 
         adios::Variable<double> *ioMyDoubles =
-            datamanReader->InquireVariableDouble("ioMyDoubles");
+            dataManReader->InquireVariable<double>("ioMyDoubles");
+
         if (ioMyDoubles == nullptr)
+        {
             std::cout << "Variable ioMyDoubles not read...yet\n";
+        }
 
-        datamanReader->Close();
+        dataManReader->Close();
     }
     catch (std::invalid_argument &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::ios_base::failure &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
     }
 
     MPI_Finalize();
diff --git a/examples/hello/datamanReader/helloDataManReader_nompi.cpp b/examples/hello/datamanReader/helloDataManReader_nompi.cpp
index bfbed7b37f062b23a8c452a845a91c93c3aa3022..965e47c364dd527ed287bf45f11d0e62a6cacfeb 100644
--- a/examples/hello/datamanReader/helloDataManReader_nompi.cpp
+++ b/examples/hello/datamanReader/helloDataManReader_nompi.cpp
@@ -2,10 +2,10 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloADIOSNoXML_OOP.cpp
+ * helloDataManReader_nompi.cpp
  *
  *  Created on: Jan 9, 2017
- *      Author: wfg
+ *      Author: Jason Wang
  */
 
 #include <iostream>
@@ -14,10 +14,10 @@
 
 #include <adios2.h>
 
-void getcb(const void *data, std::string doid, std::string var,
-           std::string dtype, std::vector<std::size_t> varshape)
+void UserCallBack(const void *data, std::string doid, std::string var,
+                  std::string dtype, std::vector<std::size_t> varshape)
 {
-    std::cout << "data object ID = " << doid << "\n"; // do you need to flush?
+    std::cout << "data object ID = " << doid << "\n";
     std::cout << "variable name = " << var << "\n";
     std::cout << "data type = " << dtype << "\n";
 
@@ -31,51 +31,40 @@ void getcb(const void *data, std::string doid, std::string var,
 
 int main(int argc, char *argv[])
 {
-    const bool adiosDebug = true;
-    adios::ADIOS adios(adios::Verbose::WARN, adiosDebug);
 
     try
     {
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &datamanSettings = adios.DeclareMethod("WAN");
-        if (!datamanSettings.IsUserDefined())
-        {
-            // if not defined by user, we can change the default settings
-            datamanSettings.SetEngine("DataManReader");
-            datamanSettings.SetParameters("real_time=yes", "method_type=stream",
-                                          "method=dump");
-            // datamanSettings.AddTransport( "Mdtm", "localIP=127.0.0.1",
-            // "remoteIP=127.0.0.1", "tolerances=1,2,3" );
-            // datamanSettings.AddTransport( "ZeroMQ", "localIP=127.0.0.1",
-            // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); not yet supported
-            // ,
-            // will throw an exception
-        }
+        adios::ADIOS adios(adios::DebugON);
 
-        // Create engine smart pointer to DataManReader Engine due to
-        // polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // DataManReader
-        auto datamanReader = adios.Open("myDoubles.bp", "r", datamanSettings);
+        adios::IO &dataManIO = adios.DeclareIO("WAN");
+        dataManIO.SetEngine("DataManReader");
+        dataManIO.SetParameters("real_time=yes", "method_type=stream",
+                                "method=dump");
+        auto dataManReader =
+            dataManIO.Open("myDoubles.bp", adios::OpenMode::Read);
 
-        if (datamanReader == nullptr)
+        if (!dataManReader)
+        {
             throw std::ios_base::failure(
                 "ERROR: failed to create DataMan I/O engine at Open\n");
+        }
 
-        datamanReader->SetCallBack(getcb);
+        dataManReader->SetCallBack(UserCallBack);
 
-        for (int i = 0; i < 3; i++)
+        for (unsigned int i = 0; i < 3; ++i)
         {
             std::this_thread::sleep_for(std::chrono::milliseconds(1000));
         }
 
         adios::Variable<double> *ioMyDoubles =
-            datamanReader->InquireVariableDouble("ioMyDoubles");
+            dataManReader->InquireVariable<double>("ioMyDoubles");
+
         if (ioMyDoubles == nullptr)
+        {
             std::cout << "Variable ioMyDoubles not read...yet\n";
+        }
 
-        datamanReader->Close();
+        dataManReader->Close();
     }
     catch (std::invalid_argument &e)
     {
diff --git a/examples/hello/datamanWriter/helloDataManWriter.cpp b/examples/hello/datamanWriter/helloDataManWriter.cpp
index f74e7e5d8af7978fc690d0f18da14c046c089a38..dcdf4bff7f289f2d4f716e073a7d2221e3059af1 100644
--- a/examples/hello/datamanWriter/helloDataManWriter.cpp
+++ b/examples/hello/datamanWriter/helloDataManWriter.cpp
@@ -2,10 +2,10 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloWriter.cpp
+ * helloDataManWriter.cpp
  *
  *  Created on: Feb 16, 2017
- *      Author: wfg
+ *      Author: Jason Wang
  */
 
 #include <iostream>
@@ -17,100 +17,58 @@
 
 int main(int argc, char *argv[])
 {
+    // Application variable
     MPI_Init(&argc, &argv);
-    int rank;
+    int rank, size;
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-    const bool adiosDebug = true;
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::WARN, adiosDebug);
-
-    // Application variable
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
 
-    std::vector<std::complex<float>> myCFloats;
-    myCFloats.reserve(3);
-    myCFloats.emplace_back(1, 3);
-    myCFloats.emplace_back(2, 2);
-    myCFloats.emplace_back(3, 1);
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
 
     try
     {
-        // Define variable and local size
-        auto ioMyDoubles =
-            adios.DefineLocalArray<double>("myDoubles", false, {Nx});
-        auto ioMyCFloats = adios.DefineLocalArray<std::complex<float>>(
-            "myCFloats", false, {3});
+        adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
+        adios::IO &dataManIO = adios.DeclareIO("WANIO");
+        dataManIO.SetEngine("DataManWriter");
+        dataManIO.SetParameters("peer-to-peer=yes", "real_time=yes",
+                                "compress=no", "method=dump");
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &datamanSettings = adios.DeclareMethod("WAN");
-        if (!datamanSettings.IsUserDefined())
-        {
-            // if not defined by user, we can change the default settings
-            datamanSettings.SetEngine("DataManWriter");
-            datamanSettings.SetParameters("peer-to-peer=yes", "real_time=yes",
-                                          "compress=no", "method=cache");
-            datamanSettings.AddTransport("Mdtm", "localIP=128.0.0.0.1",
-                                         "remoteIP=128.0.0.0.2",
-                                         "tolerances=1,2,3");
-            // datamanSettings.AddTransport( "file", "name=myfile.bp",
-            // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" );
-            // datamanSettings.AddTransport( "file", "name=myfile.bp",
-            // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" );
-            // datamanSettings.AddTransport( "Mdtm", "localIP=128.0.0.0.1",
-            // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" );
-            // datamanSettings.AddTransport( "ZeroMQ", "localIP=128.0.0.0.1",
-            // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" );
-            // datamanSettings.AddTransport( "ZeroMQ", "localIP=128.0.0.0.1.1",
-            // "remoteIP=128.0.0.0.2.1", "tolerances=1,2,3" ); not yet
-            // supported, will
-            // throw an exception
-        }
+        // Define variable and local size
+        auto bpFloats =
+            dataManIO.DefineVariable<float>("bpFloats", {}, {}, {Nx});
 
         // Create engine smart pointer to DataMan Engine due to polymorphism,
         // Open returns a smart pointer to Engine containing the Derived class
-        // DataMan
-
-        // adios::DataManWriter datamanWriter;
-
-        auto datamanWriter = adios.Open("myDoubles.bp", "w", datamanSettings);
+        auto dataManWriter =
+            dataManIO.Open("myFloats.bp", adios::OpenMode::Write);
 
-        if (datamanWriter == nullptr)
+        if (!dataManWriter)
+        {
             throw std::ios_base::failure(
                 "ERROR: failed to create DataMan I/O engine at Open\n");
+        }
 
-        datamanWriter->Write<double>(
-            ioMyDoubles,
-            myDoubles.data()); // Base class Engine own the Write<T>
-                               // that will call overloaded Write from
-                               // Derived
-        datamanWriter->Write<std::complex<float>>(ioMyCFloats,
-                                                  myCFloats.data());
-        datamanWriter->Close();
+        dataManWriter->Write<float>(bpFloats, myFloats.data());
+        dataManWriter->Close();
     }
     catch (std::invalid_argument &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::ios_base::failure &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
     }
 
     MPI_Finalize();
diff --git a/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp b/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp
index c551d955670f6d5620802c848672ce18dc821733..cbc08fb607c34025ce4697fe8de833928234d61b 100644
--- a/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp
+++ b/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp
@@ -2,10 +2,10 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * helloADIOSNoXML_OOP.cpp
+ * helloDataManWriter.cpp
  *
- *  Created on: Jan 9, 2017
- *      Author: wfg
+ *  Created on: Feb 16, 2017
+ *      Author: Jason Wang
  */
 
 #include <iostream>
@@ -15,72 +15,35 @@
 
 int main(int argc, char *argv[])
 {
-    const bool adiosDebug = true;
-    adios::ADIOS adios(adios::Verbose::WARN, adiosDebug);
-
     // Application variable
     std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    std::vector<std::complex<float>> myCFloats;
-    myCFloats.reserve(3);
-    myCFloats.emplace_back(1, 3);
-    myCFloats.emplace_back(2, 2);
-    myCFloats.emplace_back(3, 1);
+    const std::size_t Nx = myFloats.size();
 
     try
     {
-        // Define variable and local size
-        // Define variable and local size
-        auto ioMyFloats =
-            adios.DefineVariable<float>("myfloats", adios::Dims{Nx});
-        auto ioMyFloat = adios.DefineVariable<float>("myfloat", adios::Dims{1});
-        //        auto& ioMyDoubles = adios.DefineVariable<double>( "myDoubles",
-        //        adios::Dims{Nx} );
-        //        auto& ioMyCFloats = adios.DefineVariable<std::complex<float>>(
-        //        "myCFloats", {3} );
+        adios::ADIOS adios(adios::DebugON);
+        adios::IO &dataManIO = adios.DeclareIO("WANIO");
+        dataManIO.SetEngine("DataManWriter");
+        dataManIO.SetParameters("peer-to-peer=yes", "real_time=yes",
+                                "compress=no", "method=dump");
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &datamanSettings = adios.DeclareMethod("WAN");
-        if (!datamanSettings.IsUserDefined())
-        {
-            // if not defined by user, we can change the default settings
-            datamanSettings.SetEngine("DataManWriter");
-            datamanSettings.SetParameters(
-                "real_time=yes", "method_type=stream", "method=cache",
-                "monitoring=yes", "local_ip=127.0.0.1", "remote_ip=127.0.0.1",
-                "local_port=12306", "remote_port=12307");
-            // datamanSettings.AddTransport( "Mdtm", "localIP=127.0.0.1",
-            // "remoteIP=127.0.0.1", "tolerances=1,2,3" );
-            // datamanSettings.AddTransport( "ZeroMQ", "localIP=127.0.0.1",
-            // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); not yet supported
-            // ,
-            // will throw an exception
-        }
+        // Define variable and local size
+        auto bpFloats =
+            dataManIO.DefineVariable<float>("bpFloats", {}, {}, {Nx});
 
         // Create engine smart pointer to DataMan Engine due to polymorphism,
         // Open returns a smart pointer to Engine containing the Derived class
-        // DataMan
-        auto datamanWriter = adios.Open("myDoubles.bp", "w", datamanSettings);
+        auto dataManWriter =
+            dataManIO.Open("myFloats.bp", adios::OpenMode::Write);
 
-        if (datamanWriter == nullptr)
+        if (!dataManWriter)
+        {
             throw std::ios_base::failure(
                 "ERROR: failed to create DataMan I/O engine at Open\n");
+        }
 
-        datamanWriter->Write<float>(
-            ioMyFloats,
-            myFloats.data()); // Base class Engine own the Write<T> that
-                              // will call overloaded Write from Derived
-        const float num = 1.12;
-        datamanWriter->Write<float>(ioMyFloat,
-                                    &num); // Base class Engine own the
-                                           // Write<T> that will call
-                                           // overloaded Write from
-                                           // Derived
-        //        datamanWriter->Write( ioMyCFloats, myCFloats.data() );
-        datamanWriter->Close();
+        dataManWriter->Write<float>(bpFloats, myFloats.data());
+        dataManWriter->Close();
     }
     catch (std::invalid_argument &e)
     {
@@ -89,12 +52,12 @@ int main(int argc, char *argv[])
     }
     catch (std::ios_base::failure &e)
     {
-        std::cout << "System exception, STOPPING PROGRAM\n";
+        std::cout << "IO System base failure exception, STOPPING PROGRAM\n";
         std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        std::cout << "Exception, STOPPING PROGRAM\n";
+        std::cout << "Exception, STOPPING PROGRAM from rank\n";
         std::cout << e.what() << "\n";
     }
 
diff --git a/examples/hello/hdf5Writer/helloHDF5Writer.cpp b/examples/hello/hdf5Writer/helloHDF5Writer.cpp
index da647a8e8571d105c3941f56c2399e3eb3d4cfd7..264ee2b41be90e27d9c82106c9892683cc23e734 100644
--- a/examples/hello/hdf5Writer/helloHDF5Writer.cpp
+++ b/examples/hello/hdf5Writer/helloHDF5Writer.cpp
@@ -1,17 +1,22 @@
 /*
- * HDF5Writer.cpp
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloHDF5Writer.cpp: Simple self-descriptive example of how to write a
+ * variable to a parallel HDF5 File using MPI processes.
  *
  *  Created on: March 20, 2017
  *      Author: Junmin
  */
 
-#include <iostream>
+#include <ios>      //std::ios_base::failure
+#include <iostream> //std::cout
+#include <mpi.h>
+#include <stdexcept> //std::invalid_argument std::exception
 #include <vector>
 
 #include <adios2.h>
 
-#include <mpi.h>
-
 int main(int argc, char *argv[])
 {
     MPI_Init(&argc, &argv);
@@ -19,144 +24,58 @@ int main(int argc, char *argv[])
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
     MPI_Comm_size(MPI_COMM_WORLD, &size);
 
-    const bool adiosDebug = true;
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::INFO, adiosDebug);
-
-    // Application variable
-    const std::size_t intDim1 = 4;
-    const std::size_t intDim2 = 3;
-    std::vector<int> myInts = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
-
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    std::vector<std::complex<float>> myCFloats;
-    const std::size_t ComplexDataSize = 3;
-    myCFloats.reserve(ComplexDataSize);
-    myCFloats.emplace_back(1, 3);
-    myCFloats.emplace_back(2, 2);
-    myCFloats.emplace_back(3, 1);
+    /** Application variable */
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
 
-    std::vector<std::complex<double>> myCDoubles;
-    myCDoubles.reserve(ComplexDataSize);
-    myCDoubles.emplace_back(1.1, -3.3);
-    myCDoubles.emplace_back(2.1, -2.2);
-    myCDoubles.emplace_back(3.1, -1.1);
-
-    std::vector<std::complex<long double>> myCLongDoubles;
-    myCLongDoubles.reserve(ComplexDataSize);
-    myCLongDoubles.emplace_back(1.11, -3.33);
-    myCLongDoubles.emplace_back(2.11, -2.22);
-    myCLongDoubles.emplace_back(3.11, -1.11);
-
-    std::size_t doubleVCount = Nx / size;
-    std::size_t complexCount = ComplexDataSize / size;
-    std::size_t intCountDim1 = intDim1 / size;
-
-    std::size_t doubleVOffset = rank * doubleVCount;
-    std::size_t complexOffset = rank * complexCount;
-    std::size_t intOffsetDim1 = rank * intCountDim1;
-    std::size_t intOffsetDim2 = 0;
-
-    if ((size > 1) && (rank == size - 1))
-    {
-        doubleVCount = Nx - rank * (Nx / size);
-        complexCount = ComplexDataSize - rank * (ComplexDataSize / size);
-        intCountDim1 = intDim1 - rank * (intDim1 / size);
-    }
-
-    std::cout << " rank=" << rank << " of " << size
-              << ",  dim1 count: " << intCountDim1
-              << ", offset: " << intOffsetDim1 << std::endl;
-    std::cout << " intOffsetDim2=" << intOffsetDim2 << " " << intDim2
-              << std::endl;
     try
     {
-        // Define variable and local size
-        auto &ioMyInts = adios.DefineArray<int>("myInts", {4, 3},
-                                                {intOffsetDim1, intOffsetDim2},
-                                                {intCountDim1, intDim2});
-        auto &ioMyDoubles = adios.DefineArray<double>(
-            "myDoubles", {Nx}, {doubleVOffset}, {doubleVCount});
-        auto &ioMyCFloats = adios.DefineArray<std::complex<float>>(
-            "myCFloats", {3}, {complexOffset}, {complexCount});
-        auto &ioMyCDoubles = adios.DefineArray<std::complex<double>>(
-            "myCDoubles", {3}, {complexOffset}, {complexCount});
-        auto &ioMyCLongDoubles = adios.DefineArray<std::complex<long double>>(
-            "myCLongDoubles", {3}, {complexOffset}, {complexCount});
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(MPI_COMM_WORLD, adios::DebugON);
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &HDF5Settings = adios.DeclareMethod("hdf5");
-        HDF5Settings.SetEngine("HDF5Writer");
-        HDF5Settings.SetParameters("chunck=yes", "collectiveIO=yes");
-        // HDF5Settings.AddTransport( "Mdtm", "localIP=128.0.0.0.1",
-        // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" );
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &hdf5IO = adios.DeclareIO("HDFFileIO");
+        hdf5IO.SetEngine("HDF5Writer");
+        hdf5IO.AddTransport("File");
 
-        // Create engine smart pointer to HDF5 Engine due to polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // HDF5
-        auto HDF5Writer = adios.Open("test.h5", "w", HDF5Settings);
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios::Variable<float> &bpFloats = hdf5IO.DefineVariable<float>(
+            "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios::ConstantDims);
 
-        if (HDF5Writer == nullptr)
-            throw std::ios_base::failure(
-                "ERROR: failed to create HDF5 I/O engine at Open\n");
+        /** Engine derived class, spawned to start IO operations */
+        auto hdf5Writer = hdf5IO.Open("myVector.bp", adios::OpenMode::Write);
 
-        int ts = 0;
-        int totalts = 3;
-        while (true)
+        if (!hdf5Writer)
         {
-            if (rank == 0)
-            {
-                std::cout << " total timesteps: " << totalts << " curr: " << ts
-                          << " th" << std::endl;
-            }
-            HDF5Writer->Write(ioMyDoubles,
-                              myDoubles.data() +
-                                  doubleVOffset); // Base class Engine
-            // own the Write<T>
-            // that will call
-            // overloaded Write
-            // from Derived
-            HDF5Writer->Write(ioMyInts,
-                              myInts.data() + (intOffsetDim1 * intDim2));
-
-            HDF5Writer->Write(ioMyCFloats, myCFloats.data() + complexOffset);
-            HDF5Writer->Write(ioMyCDoubles, myCDoubles.data() + complexOffset);
-            HDF5Writer->Write(ioMyCLongDoubles,
-                              myCLongDoubles.data() + complexOffset);
-            ts++;
-            if (ts >= totalts)
-            {
-                break;
-            }
-            HDF5Writer->Advance();
+            throw std::ios_base::failure(
+                "ERROR: hdf5Writer not created at Open\n");
         }
-        HDF5Writer->Close();
+
+        /** Write variable for buffering */
+        hdf5Writer->Write<float>(bpFloats, myFloats.data());
+
+        /** Create bp file, engine becomes unreachable after this*/
+        hdf5Writer->Close();
     }
     catch (std::invalid_argument &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
+                  << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::ios_base::failure &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout
+            << "IO System base failure exception, STOPPING PROGRAM from rank "
+            << rank << "\n";
+        std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
+        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
+        std::cout << e.what() << "\n";
     }
 
     MPI_Finalize();
diff --git a/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp b/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp
index 61ed8f26b344038285c685fcd601ea54456aac28..6222e1eb1bddead70450696820827a4608b58b21 100644
--- a/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp
+++ b/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp
@@ -1,87 +1,56 @@
 /*
- * HDF5Writer.cpp
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloHDF5Writer_nompi.cpp  no mpi version of helloHDF5Writer.cpp
  *
  *  Created on: March 20, 2017
  *      Author: Junmin
  */
 
-#include <iostream>
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <stdexcept> //std::invalid_argument std::exception
 #include <vector>
 
 #include <adios2.h>
 
 int main(int argc, char *argv[])
 {
-    const bool adiosDebug = true;
-    adios::ADIOS adios(adios::Verbose::INFO, adiosDebug);
-
-    // Application variable
-    const std::size_t intDim1 = 4;
-    const std::size_t intDim2 = 3;
-    std::vector<int> myInts = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
-
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    std::vector<std::complex<float>> myCFloats;
-    const std::size_t CFloatSize = 3;
-    myCFloats.reserve(CFloatSize);
-    myCFloats.emplace_back(1, 3);
-    myCFloats.emplace_back(2, 2);
-    myCFloats.emplace_back(3, 1);
-
-    std::vector<std::complex<double>> myCDoubles;
-    const std::size_t CDoubleSize = 3;
-    myCDoubles.reserve(CDoubleSize);
-    myCDoubles.emplace_back(1, 3);
-    myCDoubles.emplace_back(2, 2);
-    myCDoubles.emplace_back(3, 1);
-
-    std::size_t doubleVCount = Nx;
-    std::size_t floatCount = CFloatSize;
-    std::size_t intCountDim1 = intDim1;
-
-    std::size_t doubleVOffset = 0;
-    std::size_t floatOffset = 0;
-    std::size_t intOffsetDim1 = 0;
-    std::size_t intOffsetDim2 = 0;
+    /** Application variable */
+    std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    const std::size_t Nx = myFloats.size();
 
     try
     {
-        // Define variable and local size
-        auto &ioMyDoubles =
-            adios.DefineVariable<double>("myDoubles", {Nx}, {Nx});
-        auto &ioMyCFloats =
-            adios.DefineVariable<std::complex<float>>("myCFloats", {3}, {3});
-        auto &ioMyCDoubles =
-            adios.DefineVariable<std::complex<double>>("myCDoubles", {3}, {3});
-        auto &ioMyInts = adios.DefineVariable<int>("myInts", {4, 3}, {4, 3});
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios::ADIOS adios(adios::DebugON);
 
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &HDF5Settings = adios.DeclareMethod("HDF5Writer");
-        HDF5Settings.SetParameters("chunck=yes", "collectiveIO=yes");
-        // HDF5Settings.AddTransport( "Mdtm", "localIP=128.0.0.0.1",
-        // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" );
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios::IO &hdf5IO = adios.DeclareIO("HDFFileIO");
+        hdf5IO.SetEngine("HDF5Writer");
+        hdf5IO.AddTransport("file");
 
-        // Create engine smart pointer to HDF5 Engine due to polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // HDF5
-        auto HDF5Writer = adios.Open("test.bp", "w", HDF5Settings);
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios::Variable<float> &bpFloats = hdf5IO.DefineVariable<float>(
+            "bpFloats", {}, {}, {Nx}, adios::ConstantDims);
 
-        if (HDF5Writer == nullptr)
+        /** Engine derived class, spawned to start IO operations */
+        auto hdf5Writer = hdf5IO.Open("myVector.bp", adios::OpenMode::Write);
+
+        if (!hdf5Writer)
         {
             throw std::ios_base::failure(
-                "ERROR: failed to create HDF5 I/O engine at Open\n");
+                "ERROR: hdf5Writer not created at Open\n");
         }
 
-        // Base class Engine own the Write<T> that will call overloaded Write
-        // from Derived
-        HDF5Writer->Write(ioMyDoubles, myDoubles.data() + doubleVOffset);
-        HDF5Writer->Write(ioMyInts, myInts.data());
-        HDF5Writer->Write(ioMyCFloats, myCFloats.data());
-        HDF5Writer->Write(ioMyCDoubles, myCDoubles.data());
-        HDF5Writer->Close();
+        /** Write variable for buffering */
+        hdf5Writer->Write<float>(bpFloats, myFloats.data());
+
+        /** Create bp file, engine becomes unreachable after this*/
+        hdf5Writer->Close();
     }
     catch (std::invalid_argument &e)
     {
@@ -90,12 +59,12 @@ int main(int argc, char *argv[])
     }
     catch (std::ios_base::failure &e)
     {
-        std::cout << "System exception, STOPPING PROGRAM\n";
+        std::cout << "IO System base failure exception, STOPPING PROGRAM\n";
         std::cout << e.what() << "\n";
     }
     catch (std::exception &e)
     {
-        std::cout << "Exception, STOPPING PROGRAM\n";
+        std::cout << "Exception, STOPPING PROGRAM from rank\n";
         std::cout << e.what() << "\n";
     }
 
diff --git a/examples/hello/timeBP/timeBPWriter.cpp b/examples/hello/timeBP/timeBPWriter.cpp
deleted file mode 100644
index ea3e8e6f636ede4f6646400b8f34b6bf98307415..0000000000000000000000000000000000000000
--- a/examples/hello/timeBP/timeBPWriter.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * timeBPWriter.cpp  example for time aggregation
- *
- *  Created on: Feb 16, 2017
- *      Author: wfg
- */
-
-#include <iostream>
-#include <vector>
-
-#include <mpi.h>
-
-#include <adios2.h>
-
-int main(int argc, char *argv[])
-{
-    MPI_Init(&argc, &argv);
-    int rank, nproc;
-    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
-    const bool adiosDebug = true;
-    adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::ERROR, adiosDebug);
-
-    // Application variable
-    std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    const std::size_t rows = 3;
-    const std::size_t columns = 3;
-
-    std::vector<float> myMatrix;
-    if (rank % 2 == 0) // even rank
-    {
-        myMatrix.reserve(rows * columns);
-        myMatrix.push_back(1);
-        myMatrix.push_back(2), myMatrix.push_back(3);
-        myMatrix.push_back(4);
-        myMatrix.push_back(5), myMatrix.push_back(6);
-        myMatrix.push_back(7);
-        myMatrix.push_back(8), myMatrix.push_back(8);
-    }
-
-    std::vector<float> myMatrix2 = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
-
-    try
-    {
-        // Define variable and local size
-        adios::Variable<double> &ioMyDoubles = adios.DefineVariable<double>(
-            "myDoubles", {nproc, Nx}, {rank, 0}, {1, Nx});
-        adios::Variable<float> &ioMyMatrix =
-            adios.DefineVariable<float>("myMatrix", {nproc * rows, columns},
-                                        {rank * rows, 0}, {rows, columns});
-        adios::Variable<float> &ioMyMatrix2 =
-            adios.DefineVariable<float>("myMatrix2", {rows, nproc * columns},
-                                        {0, rank * columns}, {rows, columns});
-
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-        adios::Method &bpWriterSettings =
-            adios.DeclareMethod("MyMethod"); // default method type is BPWriter
-        bpWriterSettings.SetParameters("profile_units=mus");
-        bpWriterSettings.AddTransport(
-            "File", "profile_units=mus",
-            "have_metadata_file=no"); // uses default POSIX library
-
-        // Create engine smart pointer due to polymorphism,
-        // Open returns a smart pointer to Engine containing the Derived class
-        // Writer
-        auto bpWriter = adios.Open("time.bp", "w", bpWriterSettings);
-
-        if (bpWriter == nullptr)
-            throw std::ios_base::failure(
-                "ERROR: couldn't create bpWriter at Open\n");
-
-        for (unsigned int t = 0; t < 10; ++t)
-        {
-            myDoubles[0] = t;
-            bpWriter->Write<double>(
-                ioMyDoubles,
-                myDoubles.data()); // Base class Engine own the Write<T>
-                                   // that will call overloaded Write
-                                   // from Derived
-
-            if (rank % 2 == 0) // even rank
-            {
-                myMatrix[0] = t;
-                myMatrix2[0] = t;
-
-                bpWriter->Write<float>(ioMyMatrix, myMatrix.data());
-                bpWriter->Write<float>(ioMyMatrix2, myMatrix2.data());
-            }
-            bpWriter->Advance();
-        }
-
-        bpWriter->Close();
-    }
-    catch (std::invalid_argument &e)
-    {
-        if (rank == 0)
-        {
-            std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
-    }
-    catch (std::ios_base::failure &e)
-    {
-        if (rank == 0)
-        {
-            std::cout << "System exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
-    }
-    catch (std::exception &e)
-    {
-        if (rank == 0)
-        {
-            std::cout << "Exception, STOPPING PROGRAM\n";
-            std::cout << e.what() << "\n";
-        }
-    }
-
-    MPI_Finalize();
-
-    return 0;
-}
diff --git a/examples/hello/timeBP/timeBPWriter_nompi.cpp b/examples/hello/timeBP/timeBPWriter_nompi.cpp
deleted file mode 100644
index 69d3ec71c015729d8b159c367b71564174d7b239..0000000000000000000000000000000000000000
--- a/examples/hello/timeBP/timeBPWriter_nompi.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * timeBPWriter.cpp  example for time aggregation
- *
- *  Created on: Feb 16, 2017
- *      Author: wfg
- */
-
-#include <iostream>
-#include <vector>
-
-#include <adios2.h>
-
-int main(int /*argc*/, char ** /*argv*/)
-{
-    const bool adiosDebug = true;
-    adios::ADIOS adios(adios::Verbose::ERROR, adiosDebug);
-
-    // Application variable
-    std::vector<double> myDoubles = {10, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-    const std::size_t Nx = myDoubles.size();
-
-    const std::size_t rows = 3;
-    const std::size_t columns = 3;
-
-    std::vector<float> myMatrix;
-    myMatrix.reserve(rows * columns);
-    myMatrix.push_back(1);
-    myMatrix.push_back(2), myMatrix.push_back(3);
-    myMatrix.push_back(4);
-    myMatrix.push_back(5), myMatrix.push_back(6);
-    myMatrix.push_back(7);
-    myMatrix.push_back(8), myMatrix.push_back(8);
-
-    std::vector<float> myMatrix2 = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
-
-    try
-    {
-        // Define variable and local size
-        adios::Variable<double> &ioMyDoubles =
-            adios.DefineVariable<double>("myDoubles", {Nx}, {0}, {Nx});
-        adios::Variable<float> &ioMyMatrix = adios.DefineVariable<float>(
-            "myMatrix", {rows, columns}, {0, 0}, {rows, columns});
-        adios::Variable<float> &ioMyMatrix2 = adios.DefineVariable<float>(
-            "myMatrix2", {rows, columns}, {0, 0}, {rows, columns});
-
-        // Define method for engine creation, it is basically straight-forward
-        // parameters
-
-        // default method type is BPWriter
-        adios::Method &bpWriterSettings = adios.DeclareMethod("SingleFile");
-        bpWriterSettings.SetParameters("profile_units=mus");
-
-        // uses default POSIX library
-        bpWriterSettings.AddTransport("File", "profile_units=mus",
-                                      "have_metadata_file=no");
-
-        auto bpWriter = adios.Open("time_nompi.bp", "w", bpWriterSettings);
-
-        for (unsigned int t = 0; t < 3; ++t)
-        {
-            myDoubles[0] = t; // t * -1;
-            myMatrix[0] = t;
-            myMatrix2[0] = t;
-
-            // Base class Engine own the Write<T> that will call overloaded
-            // Write from Derived
-            bpWriter->Write(ioMyDoubles, myDoubles.data());
-            bpWriter->Write(ioMyMatrix, myMatrix.data());
-            bpWriter->Write(ioMyMatrix2, myMatrix2.data());
-            bpWriter->Advance();
-        }
-
-        bpWriter->Close();
-    }
-    catch (std::invalid_argument &e)
-    {
-        std::cout << "Invalid argument exception, STOPPING PROGRAM\n";
-        std::cout << e.what() << "\n";
-    }
-    catch (std::ios_base::failure &e)
-    {
-        std::cout << "System exception, STOPPING PROGRAM\n";
-        std::cout << e.what() << "\n";
-    }
-    catch (std::exception &e)
-    {
-        std::cout << "Exception, STOPPING PROGRAM\n";
-        std::cout << e.what() << "\n";
-    }
-
-    return 0;
-}
diff --git a/source/adios2.h b/source/adios2.h
index 671ea6242aa9a38d8ac06281667fbcf421f345c3..035df18888de4b63ebba0879f6c3783c10de971e 100644
--- a/source/adios2.h
+++ b/source/adios2.h
@@ -8,10 +8,12 @@
 
 #include "adios2/ADIOSConfig.h"
 
-#include "adios2/ADIOS.h"
 #include "adios2/ADIOSTypes.h"
+#include "adios2/core/ADIOS.h"
 #include "adios2/core/Engine.h"
-#include "adios2/core/Method.h"
+#include "adios2/core/IO.h"
+#include "adios2/core/SelectionBoundingBox.h"
+#include "adios2/core/SelectionPoints.h"
 #include "adios2/core/Transform.h"
 
 #endif /* ADIOS2_H_ */
diff --git a/source/adios2/ADIOS.cpp b/source/adios2/ADIOS.cpp
deleted file mode 100644
index 791d106aa26f9e48878de6bf8b2ce276cd332430..0000000000000000000000000000000000000000
--- a/source/adios2/ADIOS.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * ADIOS.cpp
- *
- *  Created on: Sep 29, 2016
- *      Author: William F Godoy
- */
-
-#include "ADIOS.h"
-#include "ADIOS.tcc"
-
-#include <fstream>
-#include <ios> //std::ios_base::failure
-#include <iostream>
-#include <sstream>
-#include <utility>
-
-#include "adios2/ADIOSMPI.h"
-#include "adios2/ADIOSMacros.h"
-#include "adios2/core/adiosFunctions.h"
-#include "adios2/engine/bp/BPFileReader.h"
-#include "adios2/engine/bp/BPFileWriter.h"
-
-#ifdef ADIOS2_HAVE_DATAMAN // external dependencies
-#include "adios2/engine/dataman/DataManReader.h"
-#include "adios2/engine/dataman/DataManWriter.h"
-#endif
-
-#ifdef ADIOS2_HAVE_ADIOS1 // external dependencies
-#include "adios2/engine/adios1/ADIOS1Reader.h"
-#include "adios2/engine/adios1/ADIOS1Writer.h"
-#endif
-
-#ifdef ADIOS2_HAVE_HDF5 // external dependencies
-#include "adios2/engine/hdf5/HDF5ReaderP.h"
-#include "adios2/engine/hdf5/HDF5WriterP.h"
-#endif
-
-namespace adios
-{
-
-ADIOS::ADIOS(const Verbose verbose, const bool debugMode)
-: ADIOS("", MPI_COMM_SELF, verbose, debugMode)
-{
-}
-
-ADIOS::ADIOS(const std::string config, const Verbose verbose,
-             const bool debugMode)
-: ADIOS(config, MPI_COMM_SELF, verbose, debugMode)
-{
-}
-
-ADIOS::ADIOS(const std::string configFile, MPI_Comm mpiComm,
-             const Verbose verbose, const bool debugMode)
-: m_MPIComm(mpiComm), m_ConfigFile(configFile), m_DebugMode(debugMode)
-{
-    InitMPI();
-    // InitXML( m_XMLConfigFile, m_MPIComm, m_DebugMode, m_HostLanguage,
-    // m_Transforms, m_Groups );
-}
-
-ADIOS::ADIOS(MPI_Comm mpiComm, const Verbose verbose, const bool debugMode)
-: ADIOS("", mpiComm, verbose, debugMode)
-{
-}
-
-// ADIOS::~ADIOS() {}
-
-void ADIOS::InitMPI()
-{
-    if (m_DebugMode == true)
-    {
-        if (m_MPIComm == MPI_COMM_NULL)
-        {
-            throw std::ios_base::failure(
-                "ERROR: engine communicator is MPI_COMM_NULL,"
-                " in call to ADIOS Open or Constructor\n");
-        }
-    }
-
-    MPI_Comm_rank(m_MPIComm, &m_RankMPI);
-    MPI_Comm_size(m_MPIComm, &m_SizeMPI);
-}
-
-Method &ADIOS::DeclareMethod(const std::string methodName)
-{
-    if (m_DebugMode == true)
-    {
-        if (m_Methods.count(methodName) == 1)
-        {
-            throw std::invalid_argument(
-                "ERROR: method " + methodName +
-                " already declared, from DeclareMethod\n");
-        }
-    }
-    m_Methods.emplace(methodName, Method(methodName, m_DebugMode));
-    return m_Methods.at(methodName);
-}
-
-std::shared_ptr<Engine> ADIOS::Open(const std::string &name,
-                                    const std::string accessMode,
-                                    MPI_Comm mpiComm, const Method &method)
-{
-    if (m_DebugMode == true)
-    {
-        if (m_EngineNames.count(name) == 1) // Check if Engine already exists
-        {
-            throw std::invalid_argument(
-                "ERROR: engine name " + name +
-                " already created by Open, in call from Open.\n");
-        }
-    }
-
-    m_EngineNames.insert(name);
-
-    const std::string type(method.m_Type);
-
-    const bool isDefaultWriter =
-        (accessMode == "w" || accessMode == "write" || accessMode == "a" ||
-         accessMode == "append") &&
-                type.empty()
-            ? true
-            : false;
-
-    const bool isDefaultReader =
-        (accessMode == "r" || accessMode == "read") && type.empty() ? true
-                                                                    : false;
-
-    if (isDefaultWriter || type == "BPFileWriter" || type == "bpfilewriter")
-    {
-        return std::make_shared<BPFileWriter>(*this, name, accessMode, mpiComm,
-                                              method);
-    }
-    else if (isDefaultReader || type == "BPReader" || type == "bpreader")
-    {
-        return std::make_shared<BPFileReader>(*this, name, accessMode, mpiComm,
-                                              method);
-    }
-    else if (type == "SIRIUS" || type == "sirius" || type == "Sirius")
-    {
-        // not yet supported
-        // return std::make_shared<engine::DataMan>( *this, name, accessMode,
-        // mpiComm, method, iomode, timeout_sec, m_DebugMode, method.m_nThreads
-        // );
-    }
-    else if (type == "DataManWriter")
-    {
-#ifdef ADIOS2_HAVE_DATAMAN
-        return std::make_shared<DataManWriter>(*this, name, accessMode, mpiComm,
-                                               method);
-#else
-        throw std::invalid_argument(
-            "ERROR: this version didn't compile with "
-            "Dataman library, can't Open DataManWriter\n");
-#endif
-    }
-    else if (type == "DataManReader")
-    {
-#ifdef ADIOS2_HAVE_DATAMAN
-        return std::make_shared<DataManReader>(*this, name, accessMode, mpiComm,
-                                               method);
-#else
-        throw std::invalid_argument(
-            "ERROR: this version didn't compile with "
-            "Dataman library, can't Open DataManReader\n");
-#endif
-    }
-    else if (type == "ADIOS1Writer")
-    {
-#ifdef ADIOS2_HAVE_ADIOS1
-        return std::make_shared<ADIOS1Writer>(*this, name, accessMode, mpiComm,
-                                              method);
-#else
-        throw std::invalid_argument(
-            "ERROR: this version didn't compile with ADIOS "
-            "1.x library, can't Open ADIOS1Writer\n");
-#endif
-    }
-    else if (type == "ADIOS1Reader")
-    {
-#ifdef ADIOS2_HAVE_ADIOS1
-        return std::make_shared<ADIOS1Reader>(*this, name, accessMode, mpiComm,
-                                              method);
-#else
-        throw std::invalid_argument(
-            "ERROR: this version didn't compile with ADIOS "
-            "1.x library, can't Open ADIOS1Reader\n");
-#endif
-    }
-    else if (type == "Vis")
-    {
-        // return std::make_shared<Vis>( *this, name, accessMode, mpiComm,
-        // method,
-        // iomode, timeout_sec, m_DebugMode, method.m_nThreads );
-    }
-    else if (type == "HDF5Writer") // -junmin
-    {
-#ifdef ADIOS2_HAVE_HDF5
-        return std::make_shared<HDF5Writer>(*this, name, accessMode, mpiComm,
-                                            method);
-#else
-        throw std::invalid_argument("ERROR: this version didn't compile with "
-                                    "HDF5 library, can't use HDF5\n");
-#endif
-    }
-    else if (type == "HDF5Reader") // -Junmin
-    {
-#ifdef ADIOS2_HAVE_HDF5
-        return std::make_shared<HDF5Reader>(*this, name, accessMode, mpiComm,
-                                            method);
-#else
-        throw std::invalid_argument("ERROR: this version didn't compile with "
-                                    "HDF5 library, can't use HDF5\n");
-#endif
-    }
-    else
-    {
-        if (m_DebugMode == true)
-        {
-            throw std::invalid_argument("ERROR: method type " + type +
-                                        " not supported for " + name +
-                                        ", in call to Open\n");
-        }
-    }
-
-    return nullptr; // if debug mode is off
-}
-
-std::shared_ptr<Engine> ADIOS::Open(const std::string &name,
-                                    const std::string accessMode,
-                                    const Method &method)
-{
-    return Open(name, accessMode, m_MPIComm, method);
-}
-
-std::shared_ptr<Engine> ADIOS::Open(const std::string &name,
-                                    const std::string accessMode,
-                                    MPI_Comm mpiComm,
-                                    const std::string methodName)
-{
-    auto itMethod = m_Methods.find(methodName);
-
-    if (m_DebugMode == true)
-    {
-        CheckMethod(itMethod, methodName, " in call to Open\n");
-    }
-
-    return Open(name, accessMode, mpiComm, itMethod->second);
-}
-
-std::shared_ptr<Engine> ADIOS::Open(const std::string &name,
-                                    const std::string accessMode,
-                                    const std::string methodName)
-{
-    return Open(name, accessMode, m_MPIComm, methodName);
-}
-
-std::shared_ptr<Engine> ADIOS::OpenFileReader(const std::string &fileName,
-                                              MPI_Comm mpiComm,
-                                              const Method &method)
-
-{
-    return Open(fileName, "r", mpiComm, method);
-}
-
-std::shared_ptr<Engine> ADIOS::OpenFileReader(const std::string &name,
-                                              MPI_Comm mpiComm,
-                                              const std::string methodName)
-
-{
-    auto itMethod = m_Methods.find(methodName);
-
-    if (m_DebugMode == true)
-    {
-        CheckMethod(itMethod, methodName, " in call to Open\n");
-    }
-
-    return Open(name, "r", m_MPIComm, itMethod->second);
-}
-
-VariableCompound &ADIOS::GetVariableCompound(const std::string &name)
-{
-    return m_Compound.at(GetVariableIndex<void>(name));
-}
-
-void ADIOS::MonitorVariables(std::ostream &logStream)
-{
-    logStream << "\tVariable \t Type\n";
-
-    for (auto &variablePair : m_Variables)
-    {
-        const std::string name(variablePair.first);
-        const std::string type(variablePair.second.first);
-
-        if (type == GetType<char>())
-        {
-            GetVariable<char>(name).Monitor(logStream);
-        }
-        else if (type == GetType<unsigned char>())
-        {
-            GetVariable<unsigned char>(name).Monitor(logStream);
-        }
-        else if (type == GetType<short>())
-        {
-            GetVariable<short>(name).Monitor(logStream);
-        }
-        else if (type == GetType<unsigned short>())
-        {
-            GetVariable<unsigned short>(name).Monitor(logStream);
-        }
-        else if (type == GetType<int>())
-        {
-            GetVariable<int>(name).Monitor(logStream);
-        }
-        else if (type == GetType<unsigned int>())
-        {
-            GetVariable<unsigned int>(name).Monitor(logStream);
-        }
-        else if (type == GetType<long int>())
-        {
-            GetVariable<long int>(name).Monitor(logStream);
-        }
-        else if (type == GetType<unsigned long int>())
-        {
-            GetVariable<unsigned long int>(name).Monitor(logStream);
-        }
-        else if (type == GetType<long long int>())
-        {
-            GetVariable<long long int>(name).Monitor(logStream);
-        }
-        else if (type == GetType<unsigned long long int>())
-        {
-            GetVariable<unsigned long long int>(name).Monitor(logStream);
-        }
-        else if (type == GetType<float>())
-        {
-            GetVariable<float>(name).Monitor(logStream);
-        }
-        else if (type == GetType<double>())
-        {
-            GetVariable<double>(name).Monitor(logStream);
-        }
-        else if (type == GetType<long double>())
-        {
-            GetVariable<long double>(name).Monitor(logStream);
-        }
-        else if (type == GetType<std::complex<float>>())
-        {
-            GetVariable<std::complex<float>>(name).Monitor(logStream);
-        }
-        else if (type == GetType<std::complex<double>>())
-        {
-            GetVariable<std::complex<double>>(name).Monitor(logStream);
-        }
-        else if (type == GetType<std::complex<long double>>())
-        {
-            GetVariable<std::complex<long double>>(name).Monitor(logStream);
-        }
-    }
-}
-
-// PRIVATE FUNCTIONS BELOW
-void ADIOS::CheckVariableInput(const std::string &name,
-                               const Dims &dimensions) const
-{
-    if (m_DebugMode == true)
-    {
-        if (m_Variables.count(name) == 1)
-        {
-            throw std::invalid_argument(
-                "ERROR: variable " + name +
-                " already exists, in call to DefineVariable\n");
-        }
-
-        if (dimensions.empty() == true)
-        {
-            throw std::invalid_argument(
-                "ERROR: variable " + name +
-                " dimensions can't be empty, in call to DefineVariable\n");
-        }
-    }
-}
-
-void ADIOS::CheckVariableName(
-    std::map<std::string, std::pair<std::string, unsigned int>>::const_iterator
-        itVariable,
-    const std::string &name, const std::string hint) const
-{
-    if (m_DebugMode == true)
-    {
-        if (itVariable == m_Variables.end())
-        {
-            throw std::invalid_argument("ERROR: variable " + name +
-                                        " does not exist " + hint + "\n");
-        }
-    }
-}
-
-void ADIOS::CheckMethod(std::map<std::string, Method>::const_iterator itMethod,
-                        const std::string methodName,
-                        const std::string hint) const
-{
-    if (itMethod == m_Methods.end())
-    {
-        throw std::invalid_argument("ERROR: method " + methodName +
-                                    " not found " + hint + "\n");
-    }
-}
-
-//------------------------------------------------------------------------------
-
-// Explicitly instantiate the necessary template implementations
-#define define_template_instantiation(T)                                       \
-    template Variable<T> &ADIOS::DefineVariable<T>(                            \
-        const std::string &, const Dims, const Dims, const Dims,               \
-        bool constantShape);                                                   \
-                                                                               \
-    template Variable<T> &ADIOS::GetVariable<T>(const std::string &);
-
-ADIOS_FOREACH_TYPE_1ARG(define_template_instantiation)
-template unsigned int ADIOS::GetVariableIndex<void>(const std::string &);
-#undef define_template_instatiation
-
-//------------------------------------------------------------------------------
-
-} // end namespace adios
diff --git a/source/adios2/ADIOS.h b/source/adios2/ADIOS.h
deleted file mode 100644
index 7baca649e921e489468badb322008f9994e3ba7c..0000000000000000000000000000000000000000
--- a/source/adios2/ADIOS.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * ADIOS.h
- *  Created on: Oct 3, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_ADIOS_H_
-#define ADIOS2_ADIOS_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <complex>
-#include <map>
-#include <memory> //std::shared_ptr
-#include <ostream>
-#include <set>
-#include <string>
-#include <vector>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/ADIOSMPICommOnly.h"
-#include "adios2/ADIOSMacros.h"
-#include "adios2/ADIOSTypes.h"
-#include "adios2/core/Method.h"
-#include "adios2/core/Support.h"
-#include "adios2/core/Transform.h"
-#include "adios2/core/Variable.h"
-#include "adios2/core/VariableCompound.h"
-
-namespace adios
-{
-
-class Engine;
-
-/**
- * @brief Unique class interface between user application and ADIOS library
- */
-class ADIOS
-{
-public:
-    /**
-     * Passed from parallel constructor, MPI_Comm is a pointer itself.
-     *  Public as called from C
-     */
-    MPI_Comm m_MPIComm;
-
-    int m_RankMPI = 0; ///< current MPI rank process
-    int m_SizeMPI = 1; ///< current MPI processes size
-
-    std::string m_HostLanguage = "C++"; ///< changed by language bindings
-
-    /**
-     * @brief ADIOS empty constructor. Used for non XML config file API calls.
-     */
-    ADIOS(const Verbose verbose = Verbose::WARN, const bool debugMode = false);
-
-    /**
-     * @brief Serial constructor for config file, only allowed and compiled in
-     * libadios_nompi.a
-     * @param configFile XML config file (maybe support different formats in the
-     * future?)
-     * @param debugMode true: on throws exceptions and do additional checks,
-     * false: off (faster, but unsafe)
-     */
-    ADIOS(const std::string configFile, const Verbose verbose = Verbose::WARN,
-          const bool debugMode = false);
-
-    /**
-     * @brief Parallel constructor for XML config file and MPI
-     * @param config XML config file (maybe support different formats in the
-     * future?)
-     * @param mpiComm MPI communicator ...const to be discussed
-     * @param debugMode true: on, false: off (faster, but unsafe)
-     */
-    ADIOS(const std::string configFile, MPI_Comm mpiComm,
-          const Verbose verbose = Verbose::WARN, const bool debugMode = false);
-
-    /**
-     * @brief Parallel MPI communicator without XML config file
-     * @param mpiComm MPI communicator passed to m_MPIComm*
-     * @param debugMode true: on, false: off (faster)
-     */
-    ADIOS(MPI_Comm mpiComm, const Verbose verbose = Verbose::WARN,
-          const bool debugMode = false);
-
-    ~ADIOS() = default;
-
-    void InitMPI(); ///< sets rank and size in m_rank and m_Size, respectively.
-
-    /**
-     * Define a Variable for I/O. Default is a local scalar to be compatible
-     * with ADIOS1
-     * @param name variable name, must be unique
-     * @param dimensions
-     * @param selections
-     * @param offsets
-     * @constantShape true if dimensions, offsets and local sizes don't change
-     * over time
-     * @return reference to Variable object
-     */
-    template <class T>
-    Variable<T> &DefineVariable(const std::string &name, const Dims shape = {},
-                                const Dims start = {}, const Dims count = {},
-                                const bool constantShape = false);
-
-    template <class T>
-    Variable<T> &DefineLocalValue(const std::string &name)
-    {
-        return DefineVariable<T>(name, {LocalValueDim}, {}, {}, false);
-    }
-
-    template <class T>
-    Variable<T> &DefineLocalArray(const std::string &name, bool isJoined,
-                                  Dims shape = {})
-    {
-        return DefineVariable<T>(name, shape, {}, {}, false);
-    }
-
-    template <class T>
-    Variable<T> &DefineArray(const std::string &name, Dims shape = {},
-                             Dims start = {}, Dims count = {})
-    {
-        return DefineVariable<T>(name, shape, start, count, false);
-    }
-
-    template <class T>
-    Variable<T> &GetVariable(const std::string &name);
-
-    template <class T>
-    VariableCompound &DefineVariableCompound(
-        const std::string &name, const Dims globalDimensions = Dims{},
-        const Dims localDimensions = Dims{1}, const Dims offsets = Dims{});
-
-    VariableCompound &GetVariableCompound(const std::string &name);
-
-    /**
-     * Declares a new method. If the method is defined in the user config file,
-     * it will be already created during processing the config file,
-     * the method is set up with the user settings and this function just
-     * returns
-     * that method.
-     * Otherwise it will create and return a new Method with default settings.
-     * Use method.isUserDefined() to distinguish between the two cases.
-     * @param methodName must be unique
-     */
-    Method &DeclareMethod(const std::string methodName);
-
-    /**
-     * @brief Open to Write, Read. Creates a new engine from previously defined
-     * method
-     * @param streamName unique stream or file name
-     * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or
-     * "update"
-     * @param mpiComm option to modify communicator from ADIOS class constructor
-     * @param method looks for corresponding Method object in ADIOS to
-     * initialize
-     * the engine
-     * @param iomode Independent or collective open/advance by writers/readers?
-     * Write() operations are always independent.
-     * @param timeout_sec Wait some time before reporting on missing stream
-     * (i.e.
-     * wait for it for a while)
-      * @return Derived class of base Engine depending on Method parameters,
-     * shared_ptr for potential flexibility
-     */
-    std::shared_ptr<Engine> Open(const std::string &streamName,
-                                 const std::string accessMode, MPI_Comm mpiComm,
-                                 const Method &method);
-
-    /**
-     * @brief Open to Write, Read. Creates a new engine from previously defined
-     * method.
-     * Reuses MPI communicator from ADIOS constructor.
-     * @param streamName unique stream or file name
-     * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or
-     * "update"
-     * @param method contains engine parameters
-     * @param iomode Independent or collective open/advance by writers/readers?
-     * Write() operations are always independent.
-     * @param timeout_sec Wait some time before reporting on missing stream
-     * (i.e.
-     * wait for it for a while)
-      * @return Derived class of base Engine depending on Method parameters,
-     * shared_ptr for potential flexibility
-     */
-    std::shared_ptr<Engine> Open(const std::string &streamName,
-                                 const std::string accessMode,
-                                 const Method &method);
-
-    /**
-     * Version required by the XML config file implementation, searches method
-     * inside ADIOS through a unique name
-     * @param streamName unique stream or file name
-     * @param accessMode "w" or "write", "r" or "read", "a" or "append"
-     * @param mpiComm mpi Communicator
-     * @param methodName used to search method object inside ADIOS object
-     * @param iomode Independent or collective open/advance by writers/readers?
-     * Write() operations are always independent.
-     * @param timeout_sec Wait some time before reporting on missing stream
-     * (i.e.
-     * wait for it for a while)
-     * @return Derived class of base Engine depending on Method parameters,
-     * shared_ptr for potential flexibility
-     */
-    std::shared_ptr<Engine> Open(const std::string &streamName,
-                                 const std::string accessMode, MPI_Comm mpiComm,
-                                 const std::string methodName);
-
-    /**
-     * Version required by the XML config file implementation, searches method
-     * inside ADIOS through a unique name.
-     * Reuses ADIOS MPI Communicator from constructor.
-     * @param streamName unique stream or file name
-     * @param accessMode "w" or "write", "r" or "read", "a" or "append"
-     * @param methodName used to search method object inside ADIOS object
-     * @param iomode Independent or collective open/advance by writers/readers?
-     * Write() operations are always independent.
-     * @param timeout_sec Wait some time before reporting on missing stream
-     * (i.e.
-     * wait for it for a while)
-     * @return Derived class of base Engine depending on Method parameters,
-     * shared_ptr for potential flexibility
-     */
-    std::shared_ptr<Engine> Open(const std::string &streamName,
-                                 const std::string accessMode,
-                                 const std::string methodName);
-
-    /**
-     * @brief Open to Read all steps from a file. No streaming, advancing is
-     * possible here. All steps in the file
-     * are immediately available for reading. Creates a new engine from
-     * previously
-     * defined method.
-     * @param fileName file name
-     * @param mpiComm option to modify communicator from ADIOS class constructor
-     * @param method looks for corresponding Method object in ADIOS to
-     * initialize
-     * the engine
-     * @param iomode Independent or collective open/advance by writers/readers?
-     * Write() operations are always independent.
-     * @return Derived class of base Engine depending on Method parameters,
-     * shared_ptr for potential flexibility
-     */
-    std::shared_ptr<Engine> OpenFileReader(const std::string &fileName,
-                                           MPI_Comm mpiComm,
-                                           const Method &method);
-
-    /**
-     * @brief Open to Read all steps from a file. No streaming, advancing is
-     * possible here. All steps in the file
-     * are immediately available for reading. Creates a new engine from
-     * previously
-     * defined method.
-     * Version required by the XML config file implementation, searches method
-     * inside ADIOS through a unique name.
-     * @param fileName file name
-     * @param mpiComm option to modify communicator from ADIOS class constructor
-     * @param methodName used to search method object inside ADIOS object
-      * @param iomode Independent or collective open/advance by writers/readers?
-     * Write() operations are always independent.
-     * @return Derived class of base Engine depending on Method parameters,
-     * shared_ptr for potential flexibility
-     */
-    std::shared_ptr<Engine> OpenFileReader(const std::string &fileName,
-                                           MPI_Comm mpiComm,
-                                           const std::string methodName);
-
-    /**
-     * @brief Dumps groups information to a file stream or standard output.
-     * Note that either the user closes this fileStream or it's closed at the
-     * end.
-     * @param logStream either std::cout standard output, or a std::ofstream
-     * file
-     */
-    void MonitorVariables(std::ostream &logStream);
-
-protected: // no const to allow default empty and copy constructors
-    std::map<unsigned int, Variable<char>> m_Char;
-    std::map<unsigned int, Variable<unsigned char>> m_UChar;
-    std::map<unsigned int, Variable<short>> m_Short;
-    std::map<unsigned int, Variable<unsigned short>> m_UShort;
-    std::map<unsigned int, Variable<int>> m_Int;
-    std::map<unsigned int, Variable<unsigned int>> m_UInt;
-    std::map<unsigned int, Variable<long int>> m_LInt;
-    std::map<unsigned int, Variable<unsigned long int>> m_ULInt;
-    std::map<unsigned int, Variable<long long int>> m_LLInt;
-    std::map<unsigned int, Variable<unsigned long long int>> m_ULLInt;
-    std::map<unsigned int, Variable<float>> m_Float;
-    std::map<unsigned int, Variable<double>> m_Double;
-    std::map<unsigned int, Variable<long double>> m_LDouble;
-    std::map<unsigned int, Variable<std::complex<float>>> m_CFloat;
-    std::map<unsigned int, Variable<std::complex<double>>> m_CDouble;
-    std::map<unsigned int, Variable<std::complex<long double>>> m_CLDouble;
-    std::map<unsigned int, VariableCompound> m_Compound;
-
-    ///< XML File to be read containing configuration information
-    std::string m_ConfigFile;
-
-    ///< if true will do more checks, exceptions, warnings, expect slower code
-    bool m_DebugMode = false;
-
-    // Variables
-    ///< Makes variable name unique, key: variable name,value: pair.first =
-    /// type, pair.second = index in corresponding vector of Variable
-    std::map<std::string, std::pair<std::string, unsigned int>> m_Variables;
-
-    ///< transforms associated with ADIOS run
-    std::vector<std::shared_ptr<Transform>> m_Transforms;
-
-    /**
-     * @brief List of Methods (engine metadata) defined from either ADIOS XML
-     * configuration file or the DeclareMethod function.
-     * <pre>
-     *     Key: std::string unique method name
-     *     Value: Method class
-     * </pre>
-     */
-    std::map<std::string, Method> m_Methods;
-
-    ///< set used to check Engine name uniqueness in debug mode
-    std::set<std::string> m_EngineNames;
-
-    /**
-     * @brief Checks for group existence in m_Groups, if failed throws
-     * std::invalid_argument exception
-     * @param itGroup m_Groups iterator, usually from find function
-     * @param groupName unique name, passed for thrown exception only
-     * @param hint adds information to thrown exception
-     */
-    void CheckVariableInput(const std::string &name,
-                            const Dims &dimensions) const;
-
-    /**
-     * Checks for variable name, if not found throws an invalid exception
-     * @param itVariable iterator pointing to the variable name in m_Variables
-     * @param name variable name
-     * @param hint message to be thrown for debugging purporses
-     */
-    void CheckVariableName(
-        std::map<std::string,
-                 std::pair<std::string, unsigned int>>::const_iterator
-            itVariable,
-        const std::string &name, const std::string hint) const;
-
-    /**
-     * @brief Checks for method existence in m_Methods, if failed throws
-     * std::invalid_argument exception
-     * @param itMethod m_Methods iterator, usually from find function
-     * @param methodName unique name, passed for thrown exception only
-     * @param hint adds information to thrown exception
-     */
-    void CheckMethod(std::map<std::string, Method>::const_iterator itMethod,
-                     const std::string methodName,
-                     const std::string hint) const;
-
-    template <class T>
-    unsigned int GetVariableIndex(const std::string &name);
-
-    // Helper function for DefineVariable
-    template <class T>
-    std::map<unsigned int, Variable<T>> &GetVariableMap();
-};
-
-//------------------------------------------------------------------------------
-
-// Explicit declaration of the template methods
-#define declare_template_instantiation(T)                                      \
-    extern template Variable<T> &ADIOS::DefineVariable<T>(                     \
-        const std::string &name, const Dims, const Dims, const Dims,           \
-        const bool constantShape);                                             \
-                                                                               \
-    extern template Variable<T> &ADIOS::GetVariable<T>(const std::string &);
-
-ADIOS_FOREACH_TYPE_1ARG(declare_template_instantiation)
-extern template unsigned int ADIOS::GetVariableIndex<void>(const std::string &);
-#undef declare_template_instantiation
-
-} // end namespace adios
-
-// Include the inline implementations for the public interface
-#include "adios2/ADIOS.inl"
-
-#endif /* ADIOS2_ADIOS_H_ */
diff --git a/source/adios2/ADIOS.inl b/source/adios2/ADIOS.inl
deleted file mode 100644
index 8b82f2e85e94b1dcc15c08f841284670a57549cf..0000000000000000000000000000000000000000
--- a/source/adios2/ADIOS.inl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * ADIOS.tcc
- *   This contains the template implementations for the ADIOS class
- */
-
-#ifndef ADIOS2_ADIOS_INL_
-#define ADIOS2_ADIOS_INL_
-#ifndef ADIOS2_ADIOS_H_
-#error "Inline file should only be included from it's header, never on it's own"
-#endif
-
-namespace adios
-{
-
-template <class T>
-VariableCompound &ADIOS::DefineVariableCompound(const std::string &name,
-                                                const Dims dimensions,
-                                                const Dims globalDimensions,
-                                                const Dims globalOffsets)
-{
-    CheckVariableInput(name, dimensions);
-    const unsigned int size = m_Compound.size();
-    m_Compound.emplace(size, VariableCompound(name, sizeof(T), dimensions,
-                                              globalDimensions, globalOffsets,
-                                              false, m_DebugMode));
-    m_Variables.emplace(name, std::make_pair(GetType<T>(), size));
-    return m_Compound.at(size);
-}
-
-} // end namespace adios
-
-#endif /* ADIOS2_ADIOS_INL_ */
diff --git a/source/adios2/ADIOS.tcc b/source/adios2/ADIOS.tcc
deleted file mode 100644
index c6262014bec86553c5157487b5c97a4a559c950d..0000000000000000000000000000000000000000
--- a/source/adios2/ADIOS.tcc
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * ADIOS.tcc
- *   This contains the template specializatios for the ADIOS class
- */
-
-#ifndef ADIOS2_ADIOS_TCC_
-#define ADIOS2_ADIOS_TCC_
-
-#include "adios2/ADIOS.h"
-#include "adios2/ADIOSMacros.h"
-
-namespace adios
-{
-
-// -----------------------------------------------------------------------------
-// template specializations of GetVarMap helper function
-// -----------------------------------------------------------------------------
-
-template <>
-std::map<unsigned int, Variable<char>> &ADIOS::GetVariableMap()
-{
-    return m_Char;
-}
-
-template <>
-std::map<unsigned int, Variable<unsigned char>> &ADIOS::GetVariableMap()
-{
-    return m_UChar;
-}
-
-template <>
-std::map<unsigned int, Variable<short>> &ADIOS::GetVariableMap()
-{
-    return m_Short;
-}
-
-template <>
-std::map<unsigned int, Variable<unsigned short>> &ADIOS::GetVariableMap()
-{
-    return m_UShort;
-}
-
-template <>
-std::map<unsigned int, Variable<int>> &ADIOS::GetVariableMap()
-{
-    return m_Int;
-}
-
-template <>
-std::map<unsigned int, Variable<unsigned int>> &ADIOS::GetVariableMap()
-{
-    return m_UInt;
-}
-
-template <>
-std::map<unsigned int, Variable<long int>> &ADIOS::GetVariableMap()
-{
-    return m_LInt;
-}
-
-template <>
-std::map<unsigned int, Variable<unsigned long int>> &ADIOS::GetVariableMap()
-{
-    return m_ULInt;
-}
-
-template <>
-std::map<unsigned int, Variable<long long int>> &ADIOS::GetVariableMap()
-{
-    return m_LLInt;
-}
-
-template <>
-std::map<unsigned int, Variable<unsigned long long int>> &
-ADIOS::GetVariableMap()
-{
-    return m_ULLInt;
-}
-
-template <>
-std::map<unsigned int, Variable<float>> &ADIOS::GetVariableMap()
-{
-    return m_Float;
-}
-
-template <>
-std::map<unsigned int, Variable<double>> &ADIOS::GetVariableMap()
-{
-    return m_Double;
-}
-
-template <>
-std::map<unsigned int, Variable<long double>> &ADIOS::GetVariableMap()
-{
-    return m_LDouble;
-}
-
-template <>
-std::map<unsigned int, Variable<std::complex<float>>> &ADIOS::GetVariableMap()
-{
-    return m_CFloat;
-}
-
-template <>
-std::map<unsigned int, Variable<std::complex<double>>> &ADIOS::GetVariableMap()
-{
-    return m_CDouble;
-}
-
-template <>
-std::map<unsigned int, Variable<std::complex<long double>>> &
-ADIOS::GetVariableMap()
-{
-    return m_CLDouble;
-}
-
-// -----------------------------------------------------------------------------
-
-template <typename T>
-Variable<T> &ADIOS::DefineVariable(const std::string &name, const Dims shape,
-                                   const Dims start, const Dims count,
-                                   const bool constantShape)
-{
-    auto &variableMap = GetVariableMap<T>();
-    CheckVariableInput(name, shape);
-    const unsigned int size = variableMap.size();
-    variableMap.emplace(size, Variable<T>(name, shape, start, count,
-                                          constantShape, m_DebugMode));
-    m_Variables.emplace(name, std::make_pair(GetType<T>(), size));
-    return variableMap.at(size);
-}
-
-// -----------------------------------------------------------------------------
-
-template <class T>
-unsigned int ADIOS::GetVariableIndex(const std::string &name)
-{
-    auto itVariable = m_Variables.find(name);
-    CheckVariableName(
-        itVariable, name,
-        "in call to GetVariable<" + GetType<T>() +
-            ">, or call to GetVariableCompound if <T> = <compound>\n");
-    return itVariable->second.second;
-}
-
-template <typename T>
-Variable<T> &ADIOS::GetVariable(const std::string &name)
-{
-    return GetVariableMap<T>().at(GetVariableIndex<T>(name));
-}
-
-} // end namespace adios
-
-#endif // ADIOS2_ADIOS_TCC_
diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h
index 0a15f131de7c3c715807482830179a9692eac3ed..8f1471a4a7067ea274f5620ba439320856679df0 100644
--- a/source/adios2/ADIOSMacros.h
+++ b/source/adios2/ADIOSMacros.h
@@ -8,6 +8,7 @@
 #ifndef ADIOS2_ADIOSMACROS_H
 #define ADIOS2_ADIOSMACROS_H
 
+#include "adios2/ADIOSTypes.h"
 // The ADIOS_FOREACH_TYPE_1ARG macro assumes the given argument is a macro which
 // takes a single argument that is a type and then inserts the given MACRO for
 // each of the known primitive types
@@ -21,7 +22,7 @@
 //   ADIOS_FOREACH_TYPE_1ARG(instantiate_foo)
 //   #undef instantiate_foo
 //
-#define ADIOS_FOREACH_TYPE_1ARG(MACRO)                                         \
+#define ADIOS2_FOREACH_TYPE_1ARG(MACRO)                                        \
     MACRO(char)                                                                \
     MACRO(unsigned char)                                                       \
     MACRO(short)                                                               \
@@ -29,8 +30,8 @@
     MACRO(int)                                                                 \
     MACRO(unsigned int)                                                        \
     MACRO(long int)                                                            \
-    MACRO(unsigned long int)                                                   \
     MACRO(long long int)                                                       \
+    MACRO(unsigned long int)                                                   \
     MACRO(unsigned long long int)                                              \
     MACRO(float)                                                               \
     MACRO(double)                                                              \
@@ -39,7 +40,7 @@
     MACRO(std::complex<double>)                                                \
     MACRO(std::complex<long double>)
 
-#define ADIOS_FOREACH_PRIMITIVE_TYPE_1ARG(MACRO)                               \
+#define ADIOS2_FOREACH_PRIMITIVE_TYPE_1ARG(MACRO)                              \
     MACRO(char)                                                                \
     MACRO(unsigned char)                                                       \
     MACRO(short)                                                               \
@@ -48,15 +49,11 @@
     MACRO(unsigned int)                                                        \
     MACRO(long int)                                                            \
     MACRO(unsigned long int)                                                   \
-    MACRO(long long int)                                                       \
-    MACRO(unsigned long long int)                                              \
     MACRO(float)                                                               \
-    MACRO(double)                                                              \
-    MACRO(long double)
+    MACRO(double)
 
-#define ADIOS_FOREACH_COMPLEX_TYPE_1ARG(MACRO)                                 \
+#define ADIOS2_FOREACH_COMPLEX_TYPE_1ARG(MACRO)                                \
     MACRO(float)                                                               \
-    MACRO(double)                                                              \
-    MACRO(long double)
+    MACRO(double)
 
 #endif /* ADIOS2_ADIOSMACROS_H */
diff --git a/source/adios2/ADIOSTypes.h b/source/adios2/ADIOSTypes.h
index b460d41f4e5932e4c3fe4180e968e1a99e1bd664..455b7a42b7715de48a93f0eb5fe4e93dd2ddb554 100644
--- a/source/adios2/ADIOSTypes.h
+++ b/source/adios2/ADIOSTypes.h
@@ -2,45 +2,182 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * ADIOS_Types.h
+ * ADIOSTypes.h
  *
  *  Created on: Mar 23, 2017
- *      Author: pnb
+ *      Author: Chuck Atkins chuck.atkins@kitware.com
+ *              Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
+ *
  */
 
 #ifndef ADIOS2_ADIOSTYPES_H_
 #define ADIOS2_ADIOSTYPES_H_
 
-#include <complex>
+/// \cond EXCLUDE_FROM_DOXYGEN
 #include <cstddef>
 #include <cstdint>
+
+#include <complex>
 #include <limits>
+#include <map>
+#include <string>
 #include <type_traits>
+#include <vector>
+/// \endcond
 
 #include "adios2/ADIOSConfig.h"
 
 namespace adios
 {
 
-// Alias the fixed sized typed into the adios namespace to make sure we're
-// always using the right ones.
+/** Variable shape type identifier */
+enum class ShapeID
+{
+    GlobalValue, ///< single global value, common case
+    GlobalArray, ///< global (across MPI_Comm) array, common case
+    JoinedArray, ///< global array with a common (joinable) dimension
+    LocalValue,  ///< special case, local independent value
+    LocalArray   ///< special case, local independent array
+};
+
+/** Used to set IO class */
+enum class IOMode
+{
+    Independent, ///< all I/O operations are independent per rank
+    Collective   ///< expect collective I/O operations
+};
+
+/** OpenMode in IO Open */
+enum class OpenMode
+{
+    Undefined,
+    Write,
+    Read,
+    Append,
+    ReadWrite,
+};
+
+enum class ReadMultiplexPattern
+{
+    GlobalReaders,
+    RoundRobin,
+    FirstInFirstOut,
+    OpenAllSteps
+};
+
+enum class StreamOpenMode
+{
+    Wait,
+    NoWait
+};
+
+enum class TransformType
+{
+    BZip2,
+    Zfp
+};
+
+enum class TransportType
+{
+    File,
+    WAN
+};
+
+/** Just for info purposes */
+enum class IOEngine
+{
+    Unknown,
+    BPFileWriter, ///< produces bp files
+    BPFileReader, ///< read bp files
+    HDF5Writer,   ///<
+    HDF5Reader,   ///<
+    ADIOS1Writer,
+    ADIOS1Reader,
+    DataManWriter,
+    DataManReader
+};
+
+enum class ReadMode
+{
+    NonBlocking,
+    Blocking
+};
+
+enum class AdvanceMode
+{
+    Append,
+    Update, // writer advance mode
+    NextAvailable,
+    LatestAvailable // reader advance mode
+};
+
+enum class AdvanceStatus
+{
+    OK,
+    StepNotReady,
+    EndOfStream,
+    OtherError
+};
+
+enum class TimeUnit
+{
+    Microseconds,
+    Milliseconds,
+    Seconds,
+    Minutes,
+    Hours
+};
+
+/** Type of selection */
+enum class SelectionType
+{
+    BoundingBox, ///< Contiguous block of data defined by offsets and counts per
+                 /// dimension
+    Points,      ///< List of individual points
+    WriteBlock,  ///< Selection of an individual block written by a writer
+                 /// process
+    Auto         ///< Let the engine decide what to return
+};
+
+// adios defaults
+const std::string DefaultFileLibrary("POSIX");
+const std::string DefaultTimeUnit("Microseconds");
+constexpr TimeUnit DefaultTimeUnitEnum(TimeUnit::Microseconds);
+constexpr size_t DefaultBufferSize(16384); ///< in bytes
+
+// adios alias values and types
+constexpr bool DebugON = true;
+constexpr bool DebugOFF = false;
+constexpr size_t UnknownDim = 0;
+constexpr size_t JoinedDim = std::numeric_limits<size_t>::max() - 1;
+constexpr size_t LocalValueDim = std::numeric_limits<size_t>::max() - 2;
+constexpr size_t IrregularDim = std::numeric_limits<size_t>::max() - 3;
+constexpr bool ConstantDims = true;
+constexpr bool ReadIn = true;
+
 using std::size_t;
 
+using Dims = std::vector<size_t>;
+using Params = std::map<std::string, std::string>;
+
+// Primitives
+// using schar = signed char;
 using std::int8_t;
-using std::uint8_t;
 using std::int16_t;
-using std::uint16_t;
 using std::int32_t;
-using std::uint32_t;
 using std::int64_t;
+
+// using uchar = unsigned char;
+using std::uint8_t;
+using std::uint16_t;
+using std::uint32_t;
 using std::uint64_t;
 
-// Not sure if we're really use these ones but we'll round it out for
-// completion
-using real32_t = float;
-using real64_t = double;
-using complex32_t = std::complex<real32_t>;
-using complex64_t = std::complex<real64_t>;
+// Complex
+using cfloat = std::complex<float>;
+using cdouble = std::complex<double>;
+using cldouble = std::complex<long double>;
 
 // Get a fixed width integer type from a size specification
 template <size_t Bytes, bool Signed>
@@ -115,35 +252,6 @@ struct TypeInfo<T, typename std::enable_if<std::is_same<
     using ValueType = typename T::value_type;
 };
 
-const size_t UnknownDim = 0;
-const size_t JoinedDim = std::numeric_limits<size_t>::max() - 1;
-const size_t LocalValueDim = JoinedDim - 1;
-const size_t IrregularDim = JoinedDim - 2;
-const bool ConstantShape = true;
-
-enum class VarClass
-{
-    GlobalValue,
-    LocalValue,
-    GlobalArray,
-    JoinedArray,
-    LocalArray
-};
-
-enum class Verbose
-{
-    ERROR = 0,
-    WARN = 1,
-    INFO = 2,
-    DEBUG = 3
-};
-
-enum class IOMode
-{
-    INDEPENDENT = 0,
-    COLLECTIVE = 1
-};
-
 } // end namespace adios
 
 #endif /* ADIOS2_ADIOSTYPES_H_ */
diff --git a/source/adios2/CMakeLists.txt b/source/adios2/CMakeLists.txt
index cdaa1eaacef41b863687a1bde37a8821c4299ad2..30c544588c2e48b2d3e6aedbcbd9a7ee0488d3f3 100644
--- a/source/adios2/CMakeLists.txt
+++ b/source/adios2/CMakeLists.txt
@@ -4,35 +4,44 @@
 #------------------------------------------------------------------------------#
   
 add_library(adios2
-  ADIOS.cpp ADIOS.tcc
-  
-  capsule/heap/STLVector.cpp
-  capsule/shmem/ShmSystemV.cpp
-  
-  core/Capsule.cpp
+  core/ADIOS.cpp
   core/Engine.cpp
-  core/Method.cpp
-  core/Support.cpp
-  core/Timer.cpp
+  core/IO.cpp core/IO.tcc
+  core/Selection.cpp
+  core/SelectionBoundingBox.cpp
+  core/SelectionPoints.cpp
   core/Transform.cpp
-  core/Transport.cpp
-  core/adiosFunctions.cpp
+  core/VariableBase.cpp
+  core/VariableCompound.cpp core/VariableCompound.tcc
+  
+#helper
+  helper/adiosMath.cpp
+  helper/adiosMemory.cpp
+  helper/adiosString.cpp
+  helper/adiosSystem.cpp
+  helper/adiosType.cpp
+  helper/adiosXML.cpp
   
-  engine/bp/BPFileReader.cpp
-  engine/bp/BPFileWriter.cpp
+#  engine/bp/BPFileReader.cpp
+  engine/bp/BPFileWriter.cpp engine/bp/BPFileWriter.tcc
 
-  utilities/format/bp1/BP1Base.cpp
-  utilities/format/bp1/BP1Aggregator.cpp
-  utilities/format/bp1/BP1Writer.cpp
-    
-  transport/file/FStream.cpp
-  transport/file/FileDescriptor.cpp
-  transport/file/FilePointer.cpp
-    
-  utilities/format/bp1/BP1Base.cpp
-  utilities/format/bp1/BP1Aggregator.cpp
-  utilities/format/bp1/BP1Writer.cpp
-  utilities/format/bp1/BP1Writer.tcc
+  toolkit/capsule/Capsule.cpp
+  toolkit/capsule/heap/STLVector.cpp 
+  toolkit/capsule/shmem/ShmSystemV.cpp
+
+  toolkit/format/bp1/BP1Base.cpp toolkit/format/bp1/BP1Base.tcc
+  toolkit/format/bp1/BP1Aggregator.cpp
+  toolkit/format/bp1/BP1Writer.cpp toolkit/format/bp1/BP1Writer.tcc
+
+  toolkit/profiling/iochrono/Timer.cpp
+
+  toolkit/transport/Transport.cpp
+  toolkit/transport/file/FileDescriptor.cpp
+  toolkit/transport/file/FilePointer.cpp
+  toolkit/transport/file/FileStream.cpp
+  
+  toolkit/transportman/TransportMan.cpp
+  
 )
 target_include_directories(adios2
   PUBLIC
@@ -49,7 +58,6 @@ if(ADIOS_USE_DataMan)
   target_sources(adios2 PRIVATE
     engine/dataman/DataManReader.cpp
     engine/dataman/DataManWriter.cpp
-    transport/wan/MdtmMan.cpp
   )
   target_link_libraries(adios2 PRIVATE dataman)
 endif()
@@ -85,6 +93,9 @@ if(ADIOS_USE_ADIOS1)
   target_sources(adios2 PRIVATE
     engine/adios1/ADIOS1Reader.cpp
     engine/adios1/ADIOS1Writer.cpp
+    
+    toolkit/interop/adios1/ADIOS1Common.cpp toolkit/interop/adios1/ADIOS1Common.tcc
+    
   )
   target_link_libraries(adios2 PRIVATE adios1::adios)
 endif()
@@ -110,13 +121,13 @@ if(ADIOS_USE_HDF5)
   target_sources(adios2 PRIVATE
     engine/hdf5/HDF5ReaderP.cpp
     engine/hdf5/HDF5WriterP.cpp
-    engine/hdf5/HDF5Common.cpp
+    toolkit/interop/hdf5/HDF5Common.cpp toolkit/interop/hdf5/HDF5Common.tcc
   )
   target_link_libraries(adios2 PRIVATE ${HDF5_C_LIBRARIES})
 endif()
 
 install(
-  FILES ADIOS.h ADIOS.inl ADIOSMacros.h ADIOSTypes.h ADIOSMPICommOnly.h
+  FILES ADIOSMacros.h ADIOSTypes.h ADIOSMPICommOnly.h
   DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/adios2
 )
 install(
diff --git a/source/adios2/core/ADIOS.cpp b/source/adios2/core/ADIOS.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ee373fb869ae75a4d98457b0624646fbfb31af55
--- /dev/null
+++ b/source/adios2/core/ADIOS.cpp
@@ -0,0 +1,86 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * ADIOS.cpp
+ *
+ *  Created on: Sep 29, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "ADIOS.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <fstream>
+#include <ios> //std::ios_base::failure
+#include <iostream>
+#include <sstream>
+#include <utility>
+/// \endcond
+
+#include "adios2/ADIOSMPI.h"
+
+namespace adios
+{
+
+ADIOS::ADIOS(const std::string configFile, MPI_Comm mpiComm,
+             const bool debugMode)
+: m_MPIComm(mpiComm), m_ConfigFile(configFile), m_DebugMode(debugMode)
+{
+    if (m_DebugMode)
+    {
+        CheckMPI();
+    }
+    // XML to be implemented later
+    // InitXML( m_XMLConfigFile, m_MPIComm, m_DebugMode, m_HostLanguage,
+    // m_Transforms, m_Groups );
+}
+
+ADIOS::ADIOS(const std::string configFile, const bool debugMode)
+: ADIOS(configFile, MPI_COMM_SELF, debugMode)
+{
+}
+
+ADIOS::ADIOS(MPI_Comm mpiComm, const bool debugMode)
+: ADIOS("", mpiComm, debugMode)
+{
+}
+
+ADIOS::ADIOS(const bool debugMode) : ADIOS("", MPI_COMM_SELF, debugMode) {}
+
+IO &ADIOS::DeclareIO(const std::string ioName)
+{
+    auto itIO = m_IOs.find(ioName);
+
+    if (itIO != m_IOs.end()) // exists
+    {
+        if (m_DebugMode)
+        {
+            if (itIO->second.InConfigFile())
+            {
+                throw std::invalid_argument(
+                    "ERROR: IO class object with name " + ioName +
+                    " previously declared, name must be unique "
+                    " , in call to DeclareIO\n");
+            }
+        }
+        return itIO->second;
+    }
+
+    // doesn't exist, then create new pair
+    auto ioPair =
+        m_IOs.emplace(ioName, IO(ioName, m_MPIComm, false, m_DebugMode));
+    return ioPair.first->second;
+}
+
+// PRIVATE FUNCTIONS
+void ADIOS::CheckMPI() const
+{
+    if (m_MPIComm == MPI_COMM_NULL)
+    {
+        throw std::ios_base::failure("ERROR: MPI communicator is MPI_COMM_NULL,"
+                                     " in call to ADIOS constructor\n");
+    }
+}
+
+} // end namespace adios
diff --git a/source/adios2/core/ADIOS.h b/source/adios2/core/ADIOS.h
new file mode 100644
index 0000000000000000000000000000000000000000..f13ae4974c21ea90985c081a144f1695a0db1fb8
--- /dev/null
+++ b/source/adios2/core/ADIOS.h
@@ -0,0 +1,110 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * ADIOS.h : ADIOS library starting point, factory class for IO and
+ * (polymorphic) Engines
+ *  Created on: Oct 3, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_ADIOS_H_
+#define ADIOS2_CORE_ADIOS_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <map>
+#include <memory> //std::shared_ptr
+#include <string>
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSMPICommOnly.h"
+#include "adios2/core/IO.h"
+#include "adios2/core/Transform.h"
+
+namespace adios
+{
+
+/** @brief Point of entry class for an application.
+ *         Serves as factory of IO class objects and Transforms */
+class ADIOS
+{
+public:
+    /** Passed from parallel constructor, MPI_Comm is a pointer itself. */
+    MPI_Comm m_MPIComm;
+    std::string m_HostLanguage = "C++"; ///< changed by language bindings
+
+    /**
+     * @brief Constructor for MPI applications WITH a XML config file
+     * @param configFile XML format (maybe support different formats in the
+     * future?)
+     * @param mpiComm MPI communicator from application
+     * @param debugMode true: extra exception checks (recommended)
+     */
+    ADIOS(const std::string configFile, MPI_Comm mpiComm,
+          const bool debugMode = false);
+
+    /**
+     * @brief Constructor for non-MPI applications WITH a XML config file
+     * @param configFile XML format (maybe support different formats in the
+     * future?)
+     * @param debugMode true: extra exception checks (recommended)
+     */
+    ADIOS(const std::string configFile, const bool debugMode = false);
+
+    /**
+     * @brief Constructor for MPI apps WITHOUT a XML config file
+     * @param mpiComm MPI communicator from application
+     * @param debugMode true: extra exception checks (recommended)
+     */
+    ADIOS(MPI_Comm mpiComm, const bool debugMode = false);
+
+    /**
+     *  @brief ADIOS no-MPI default empty constructor
+     *  @param debugMode true: extra exception checks (recommended)
+     */
+    ADIOS(const bool debugMode = false);
+
+    ~ADIOS() = default;
+
+    /**
+     * Declares a new IO class object. If IO object is defined in the user
+     * config file, by name, it will be already created during the processing
+     * the config file. So this function returns a reference to that object.
+     * Otherwise it will create and return a new IO object with default
+     * settings.
+     * Use function InConfigFile() to distinguish between the two cases.
+     * @param ioName must be unique
+     * @return reference to existing (or newly created) method inside ADIOS
+     */
+    IO &DeclareIO(const std::string ioName);
+
+protected: // no const member to allow default empty and copy constructors
+    /** XML File to be read containing configuration information */
+    std::string m_ConfigFile;
+
+    /** if true will do more checks, exceptions, warnings, expect slower code */
+    bool m_DebugMode = false;
+
+    /** transforms associated with ADIOS run */
+    std::vector<std::shared_ptr<Transform>> m_Transforms;
+
+    /**
+     * @brief List of IO class objects defined from either ADIOS
+     * configuration file (XML) or the DeclareIO function explicitly.
+     * Using map (binary tree) to preserve references returned by DeclareIO.
+     * <pre>
+     *     Key: unique method name
+     *     Value: IO class object
+     * </pre>
+     */
+    std::map<std::string, IO> m_IOs;
+
+    /** throws exception if m_MPIComm = MPI_COMM_NULL */
+    void CheckMPI() const;
+};
+
+} // end namespace adios
+
+#endif /* ADIOS2_ADIOS_H_ */
diff --git a/source/adios2/core/Attribute.h b/source/adios2/core/Attribute.h
deleted file mode 100644
index 146e72486ae4da7275af68b45f2a447a01c8558d..0000000000000000000000000000000000000000
--- a/source/adios2/core/Attribute.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Attribute.h
- *
- *  Created on: Oct 5, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_ATTRIBUTE_H_
-#define ADIOS2_CORE_ATTRIBUTE_H_
-
-#include <string>
-
-#include "adios2/ADIOSConfig.h"
-
-namespace adios
-{
-
-/**
- * Plain-old data struct that defines an attribute in an ADIOS group in Group.h
- */
-struct Attribute
-{
-    const char TypeID;       ///< '0': string, '1': numeric
-    const std::string Value; ///< information about the attribute
-};
-
-} // end namespace
-
-#endif /* ADIOS2_CORE_ATTRIBUTE_H_ */
diff --git a/source/adios2/core/Engine.cpp b/source/adios2/core/Engine.cpp
index af390ee594eeb1be3f0123d1575a39ea58f5978f..8595d6db4441c0cc400374a670ec10658f09875b 100644
--- a/source/adios2/core/Engine.cpp
+++ b/source/adios2/core/Engine.cpp
@@ -5,525 +5,209 @@
  * Engine.cpp
  *
  *  Created on: Dec 19, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "Engine.h"
+#include "Engine.tcc"
 
+/// \cond EXCLUDE_FROM_DOXYGEN
 #include <ios> //std::ios_base::failure
-
-#include "adios2/ADIOSMPI.h"
-#include "adios2/core/Support.h"
-#include "adios2/core/adiosFunctions.h"
+#include <set>
+/// \endcond
 
 namespace adios
 {
 
-Engine::Engine(ADIOS &adios, const std::string engineType,
-               const std::string &name, const std::string accessMode,
-               MPI_Comm mpiComm, const Method &method,
-               const std::string endMessage)
-: m_MPIComm(mpiComm), m_EngineType(engineType), m_Name(name),
-  m_AccessMode(accessMode), m_Method(method), m_ADIOS(adios),
-  m_DebugMode(m_Method.m_DebugMode), m_EndMessage(endMessage)
+Engine::Engine(const std::string engineType, IO &io, const std::string &name,
+               const OpenMode openMode, MPI_Comm mpiComm)
+: m_EngineType(engineType), m_IO(io), m_Name(name), m_OpenMode(openMode),
+  m_MPIComm(mpiComm), m_DebugMode(io.m_DebugMode)
 {
-    if (m_DebugMode == true)
-    {
-        if (m_MPIComm == MPI_COMM_NULL)
-        {
-            throw std::ios_base::failure(
-                "ERROR: engine communicator is MPI_COMM_NULL,"
-                " in call to ADIOS Open or Constructor\n");
-        }
-    }
-
-    MPI_Comm_rank(m_MPIComm, &m_RankMPI);
-    MPI_Comm_size(m_MPIComm, &m_SizeMPI);
 }
 
-void Engine::SetCallBack(std::function<void(const void *, std::string,
-                                            std::string, std::string, Dims)>
-                             callback)
+void Engine::SetCallBack(
+    std::function<void(const void *, std::string, std::string, std::string,
+                       std::vector<size_t>)>
+        callback)
 {
 }
 
-static void EngineThrowUp(const std::string &engineType,
-                          const std::string &func)
-{
-    throw std::invalid_argument(
-        "ERROR: Engine bass class " + func + "() called. " + engineType +
-        " child class is not implementing this function\n");
-}
-
 // should these functions throw an exception?
-void Engine::Write(Variable<char> & /*variable*/, const char * /*values*/) {}
-void Engine::Write(Variable<unsigned char> & /*variable*/,
-                   const unsigned char * /*values*/)
-{
-}
-void Engine::Write(Variable<short> & /*variable*/, const short * /*values*/) {}
-void Engine::Write(Variable<unsigned short> & /*variable*/,
-                   const unsigned short * /*values*/)
-{
-}
-void Engine::Write(Variable<int> & /*variable*/, const int * /*values*/) {}
-void Engine::Write(Variable<unsigned int> & /*variable*/,
-                   const unsigned int * /*values*/)
-{
-}
-void Engine::Write(Variable<long int> & /*variable*/,
-                   const long int * /*values*/)
-{
-}
-void Engine::Write(Variable<unsigned long int> & /*variable*/,
-                   const unsigned long int * /*values*/)
-{
-}
-void Engine::Write(Variable<long long int> & /*variable*/,
-                   const long long int * /*values*/)
-{
-}
-void Engine::Write(Variable<unsigned long long int> & /*variable*/,
-                   const unsigned long long int * /*values*/)
-{
-}
-void Engine::Write(Variable<float> & /*variable*/, const float * /*values*/) {}
-void Engine::Write(Variable<double> & /*variable*/, const double * /*values*/)
-{
-}
-void Engine::Write(Variable<long double> & /*variable*/,
-                   const long double * /*values*/)
-{
-}
-void Engine::Write(Variable<std::complex<float>> & /*variable*/,
-                   const std::complex<float> * /*values*/)
-{
-}
-void Engine::Write(Variable<std::complex<double>> & /*variable*/,
-                   const std::complex<double> * /*values*/)
-{
-}
-void Engine::Write(Variable<std::complex<long double>> & /*variable*/,
-                   const std::complex<long double> * /*values*/)
-{
-}
-void Engine::Write(VariableCompound & /*variable*/, const void * /*values*/) {}
 
-void Engine::Write(const std::string & /*variableName*/,
-                   const char * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const unsigned char * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const short * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const unsigned short * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/, const int * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const unsigned int * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const long int * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const unsigned long int * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const long long int * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const unsigned long long int * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const float * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const double * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const long double * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const std::complex<float> * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const std::complex<double> * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const std::complex<long double> * /*values*/)
-{
-}
-void Engine::Write(const std::string & /*variableName*/,
-                   const void * /*values*/)
-{
-}
-
-void Engine::Advance(float /*timeout_sec*/) {}
-void Engine::Advance(AdvanceMode /*mode*/, float /*timeout_sec*/) {}
+void Engine::Advance(const float /*timeout_sec*/) {}
+void Engine::Advance(const AdvanceMode /*mode*/, const float /*timeout_sec*/) {}
 void Engine::AdvanceAsync(
     AdvanceMode /*mode*/,
     std::function<void(std::shared_ptr<adios::Engine>)> /*callback*/)
 {
 }
 
+AdvanceStatus Engine::GetAdvanceStatus() { return m_AdvanceStatus; }
+
 void Engine::Close(const int /*transportIndex*/) {}
 
 // READ
-Variable<void> *Engine::InquireVariable(const std::string & /*name*/,
-                                        const bool /*readIn*/)
-{
-    return nullptr;
+void Engine::Release() {}
+void Engine::PerformReads(ReadMode /*mode*/){};
+
+// PROTECTED
+void Engine::Init() {}
+
+void Engine::InitParameters() {}
+
+void Engine::InitTransports() {}
+
+// DoWrite
+#define declare_type(T)                                                        \
+    void Engine::DoWrite(Variable<T> &variable, const T *values)               \
+    {                                                                          \
+        ThrowUp("Write");                                                      \
+    }
+ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
+
+void Engine::DoWrite(VariableCompound &variable, const void *values)
+{ // TODO
 }
-Variable<char> *Engine::InquireVariableChar(const std::string & /*name*/,
-                                            const bool /*readIn*/)
+
+void Engine::DoWrite(const std::string &variableName, const void *values)
 {
-    return nullptr;
-}
-Variable<unsigned char> *
-Engine::InquireVariableUChar(const std::string & /*name*/,
-                             const bool /*readIn*/)
+    const std::string type(m_IO.GetVariableType(variableName));
+    if (m_DebugMode)
+    {
+        if (type.empty())
+        {
+            throw std::invalid_argument(
+                "ERROR: variable " + variableName +
+                " was not created with IO.DefineVariable for Engine " + m_Name +
+                ", in call to Write\n");
+        }
+    }
+
+    if (type == "compound")
+    {
+        DoWrite(m_IO.GetVariableCompound(variableName), values);
+    }
+#define declare_type(T)                                                        \
+    else if (type == GetType<T>())                                             \
+    {                                                                          \
+        DoWrite(m_IO.GetVariable<T>(variableName),                             \
+                reinterpret_cast<const T *>(values));                          \
+    }
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
+} // end DoWrite
+
+// READ
+VariableBase *Engine::InquireVariableUnknown(const std::string &name,
+                                             const bool readIn)
 {
     return nullptr;
 }
-Variable<short> *Engine::InquireVariableShort(const std::string & /*name*/,
-                                              const bool /*readIn*/)
+Variable<char> *Engine::InquireVariableChar(const std::string &name,
+                                            const bool readIn)
 {
     return nullptr;
 }
-Variable<unsigned short> *
-Engine::InquireVariableUShort(const std::string & /*name*/,
-                              const bool /*readIn*/)
+Variable<unsigned char> *Engine::InquireVariableUChar(const std::string &name,
+                                                      const bool readIn)
 {
     return nullptr;
 }
-Variable<int> *Engine::InquireVariableInt(const std::string & /*name*/,
-                                          const bool /*readIn*/)
+Variable<short> *Engine::InquireVariableShort(const std::string &name,
+                                              const bool readIn)
 {
     return nullptr;
 }
-Variable<unsigned int> *
-Engine::InquireVariableUInt(const std::string & /*name*/, const bool /*readIn*/)
+Variable<unsigned short> *Engine::InquireVariableUShort(const std::string &name,
+                                                        const bool readIn)
 {
-    EngineThrowUp(m_EngineType, "InquireVariableUInt");
     return nullptr;
 }
-Variable<long int> *Engine::InquireVariableLInt(const std::string & /*name*/,
-                                                const bool /*readIn*/)
+Variable<int> *Engine::InquireVariableInt(const std::string &name,
+                                          const bool readIn)
 {
     return nullptr;
 }
-Variable<unsigned long int> *
-Engine::InquireVariableULInt(const std::string & /*name*/,
-                             const bool /*readIn*/)
+Variable<unsigned int> *Engine::InquireVariableUInt(const std::string &name,
+                                                    const bool readIn)
 {
     return nullptr;
 }
-Variable<long long int> *
-Engine::InquireVariableLLInt(const std::string & /*name*/,
-                             const bool /*readIn*/)
+Variable<long int> *Engine::InquireVariableLInt(const std::string &name,
+                                                const bool readIn)
 {
     return nullptr;
 }
-Variable<unsigned long long int> *
-Engine::InquireVariableULLInt(const std::string & /*name*/,
-                              const bool /*readIn*/)
+Variable<unsigned long int> *
+Engine::InquireVariableULInt(const std::string &name, const bool readIn)
 {
     return nullptr;
 }
-Variable<float> *Engine::InquireVariableFloat(const std::string & /*name*/,
-                                              const bool /*readIn*/)
+Variable<long long int> *Engine::InquireVariableLLInt(const std::string &name,
+                                                      const bool readIn)
 {
     return nullptr;
 }
-Variable<double> *Engine::InquireVariableDouble(const std::string & /*name*/,
-                                                const bool /*readIn*/)
+Variable<unsigned long long int> *
+Engine::InquireVariableULLInt(const std::string &name, const bool readIn)
 {
     return nullptr;
 }
-Variable<long double> *
-Engine::InquireVariableLDouble(const std::string & /*name*/,
-                               const bool /*readIn*/)
+
+Variable<float> *Engine::InquireVariableFloat(const std::string &name,
+                                              const bool readIn)
 {
     return nullptr;
 }
-Variable<std::complex<float>> *
-Engine::InquireVariableCFloat(const std::string & /*name*/,
-                              const bool /*readIn*/)
+Variable<double> *Engine::InquireVariableDouble(const std::string &name,
+                                                const bool readIn)
 {
     return nullptr;
 }
-Variable<std::complex<double>> *
-Engine::InquireVariableCDouble(const std::string & /*name*/,
-                               const bool /*readIn*/)
+Variable<long double> *Engine::InquireVariableLDouble(const std::string &name,
+                                                      const bool readIn)
 {
     return nullptr;
 }
-Variable<std::complex<long double>> *
-Engine::InquireVariableCLDouble(const std::string & /*name*/,
-                                const bool /*readIn*/)
+Variable<cfloat> *Engine::InquireVariableCFloat(const std::string &name,
+                                                const bool readIn)
 {
     return nullptr;
 }
-VariableCompound *Engine::InquireVariableCompound(const std::string & /*name*/,
-                                                  const bool /*readIn*/)
+Variable<cdouble> *Engine::InquireVariableCDouble(const std::string &name,
+                                                  const bool readIn)
 {
     return nullptr;
 }
 
-void Engine::ScheduleRead(Variable<char> &variable, char *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<unsigned char> &variable,
-                          unsigned char *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<short> &variable, short *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<unsigned short> &variable,
-                          unsigned short *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<int> &variable, int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<unsigned int> &variable,
-                          unsigned int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<long int> &variable, long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<unsigned long int> &variable,
-                          unsigned long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<long long int> &variable,
-                          long long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<unsigned long long int> &variable,
-                          unsigned long long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<float> &variable, float *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<double> &variable, double *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<long double> &variable, long double *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<std::complex<float>> &variable,
-                          std::complex<float> *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<std::complex<double>> &variable,
-                          std::complex<double> *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(Variable<std::complex<long double>> &variable,
-                          std::complex<long double> *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-
-void Engine::ScheduleRead(const std::string &variableName, char *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          unsigned char *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName, short *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          unsigned short *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName, int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName, unsigned int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName, long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          unsigned long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          long long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          unsigned long long int *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName, float *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName, double *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName, long double *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          std::complex<float> *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          std::complex<double> *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-void Engine::ScheduleRead(const std::string &variableName,
-                          std::complex<long double> *values)
-{
-    EngineThrowUp(m_EngineType, "ScheduleRead");
-}
-
-void Engine::ScheduleRead(const std::string & /*variableName*/)
+Variable<cldouble> *Engine::InquireVariableCLDouble(const std::string &name,
+                                                    const bool readIn)
 {
-    EngineThrowUp(m_EngineType, "ScheduleRead");
+    return nullptr;
 }
-void Engine::ScheduleRead() { EngineThrowUp(m_EngineType, "ScheduleRead"); }
-void Engine::Release() {}
-void Engine::PerformReads(PerformReadMode /*mode*/){};
-
-// PROTECTED
-void Engine::Init() {}
 
-void Engine::InitParameters() {}
-
-void Engine::InitTransports() {}
-
-void Engine::CheckParameter(
-    const std::map<std::string, std::string>::const_iterator itParameter,
-    const std::map<std::string, std::string> &parameters,
-    const std::string parameterName, const std::string hint) const
-{
-    if (itParameter == parameters.end())
-    {
-        {
-            throw std::invalid_argument("ERROR: parameter name " +
-                                        parameterName + " not found " + hint);
-        }
+#define declare_type(T)                                                        \
+    void Engine::DoScheduleRead(Variable<T> &variable, const T *values)        \
+    {                                                                          \
+        ThrowUp("ScheduleRead");                                               \
+    }                                                                          \
+                                                                               \
+    void Engine::DoScheduleRead(const std::string &variableName,               \
+                                const T *values)                               \
+    {                                                                          \
+        ThrowUp("ScheduleRead");                                               \
     }
-}
-
-bool Engine::TransportNamesUniqueness() const
-{
-    auto lf_CheckTransportsType =
-        [&](const std::set<std::string> &specificType) -> bool
-
-    {
-        std::set<std::string> transportNames;
+ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
-        for (const auto &parameters : m_Method.m_TransportParameters)
-        {
-            auto itTransport = parameters.find("transport");
-            if (m_DebugMode == true)
-            {
-                if (itTransport == parameters.end())
-                {
-                    throw std::invalid_argument("ERROR: transport not defined "
-                                                "in Method input to Engine " +
-                                                m_Name);
-                }
-            }
-
-            const std::string type(itTransport->second);
-            if (specificType.count(type) == 1) // file transports type
-            {
-                std::string name(m_Name);
-                auto itName = parameters.find("name");
-                if (itName != parameters.end())
-                {
-                    name = itName->second;
-                }
-
-                if (transportNames.count(name) == 0)
-                {
-                    transportNames.insert(name);
-                }
-                else
-                {
-                    return false;
-                }
-            }
-        }
-        return true;
-    };
-
-    return lf_CheckTransportsType(Support::FileTransports);
-}
-
-void Engine::CheckTransportIndex(const int transportIndex)
+// PRIVATE
+void Engine::ThrowUp(const std::string function) const
 {
-    if (m_DebugMode == true)
-    {
-        if (transportIndex >= static_cast<int>(m_Transports.size()) ||
-            transportIndex < -1)
-        {
-            throw std::invalid_argument(
-                "ERROR: transport index " + std::to_string(transportIndex) +
-                " is out of range, in call to " + m_Name + "Close \n");
-        }
-    }
+    throw std::invalid_argument("ERROR: Engine derived class " + m_EngineType +
+                                " doesn't implement function " + function +
+                                "\n");
 }
 
 } // end namespace adios
diff --git a/source/adios2/core/Engine.h b/source/adios2/core/Engine.h
index 60f32d1bde14582270813f9034a0615ed6ee693c..f18e561df28e38dc610c09bff8646f443bdafc69 100644
--- a/source/adios2/core/Engine.h
+++ b/source/adios2/core/Engine.h
@@ -2,128 +2,54 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * Engine.h
+ * Engine.h Base abstract class for the core Open, Write/Read, Advance, Close
+ * functionality. Use toolkit components to build your own Engine extending this
+ * class.
+ * Examples of derived classes in: adios2/engine/
  *
  *  Created on: Nov 7, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_CORE_ENGINE_H_
 #define ADIOS2_CORE_ENGINE_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
-#include <complex>    //std::complex
 #include <functional> //std::function
 #include <map>
 #include <memory> //std::shared_ptr
 #include <string>
-#include <utility> //std::pair
 #include <vector>
 /// \endcond
 
-#include "adios2/ADIOS.h"
 #include "adios2/ADIOSConfig.h"
 #include "adios2/ADIOSMPICommOnly.h"
 #include "adios2/ADIOSTypes.h"
-#include "adios2/core/Capsule.h"
-#include "adios2/core/Method.h"
-#include "adios2/core/Transform.h"
-#include "adios2/core/Transport.h"
+#include "adios2/core/IO.h"
 #include "adios2/core/Variable.h"
 #include "adios2/core/VariableCompound.h"
 
 namespace adios
 {
 
-typedef enum { NONBLOCKINGREAD = 0, BLOCKINGREAD = 1 } PerformReadMode;
-
-typedef enum {
-    APPEND = 0,
-    UPDATE = 1, // writer advance modes
-    NEXT_AVAILABLE = 2,
-    LATEST_AVAILABLE = 3, // reader advance modes
-} AdvanceMode;
-
-enum class AdvanceStatus
-{
-    OK = 0,
-    STEP_NOT_READY = 1,
-    END_OF_STREAM = 2,
-    OTHER_ERROR = 3
-};
-
-/**
- * Base class for Engine operations managing shared-memory, and buffer and
- * variables transform and transport operations
- */
+/** Base Abstract class for IO operations:  Read/Write, Schedule, Advance and
+ * Close */
 class Engine
 {
 
 public:
-    MPI_Comm m_MPIComm;
-
-    const std::string m_EngineType; ///< from derived class
-    const std::string m_Name;       ///< name used for this engine
-    const std::string
-        m_AccessMode;       ///< accessMode for buffers used by this engine
-    const Method &m_Method; ///< associated method containing engine metadata
-
-    int m_RankMPI = 0; ///< current MPI rank process
-    int m_SizeMPI = 1; ///< current MPI processes size
-
-    const std::string m_HostLanguage = "C++"; ///< default host language
-
     /**
-     * Unique constructor
-     * @param adios
-     * @param engineType
-     * @param name
-     * @param accessMode
-     * @param mpiComm
-     * @param method
-     * @param endMessage
+     * Unique Base class constructor
+     * @param io object that generates this Engine
+     * @param name unique engine name within IO class object
+     * @param openMode  open mode from ADIOSTypes.h OpenMode
+     * @param mpiComm new communicator passed at Open or from ADIOS class
      */
-    Engine(ADIOS &adios, const std::string engineType, const std::string &name,
-           const std::string accessMode, MPI_Comm mpiComm, const Method &method,
-           const std::string endMessage);
+    Engine(const std::string engineType, IO &io, const std::string &name,
+           const OpenMode openMode, MPI_Comm mpiComm);
 
     virtual ~Engine() = default;
 
-    /** @brief Let ADIOS allocate memory for a variable, which can be used by
-     * the user.
-     * To decrease the cost of copying memory, a user may let ADIOS allocate the
-     * memory for a user-variable,
-     * according to the definition of an ADIOS-variable. The memory will be part
-     * of the ADIOS buffer used
-     * by the engine and it lives until the engine (file, stream) is closed.
-     * A variable that has been allocated this way (cannot have its local
-     * dimensions changed, and AdvanceAsync() should be
-     * used instead of Advance() and the user-variable must not be modified by
-     * the application until the notification arrives.
-     * This is required so that any reader can access the written data before
-     * the application overwrites it.
-     * @param var Variable with defined local dimensions and offsets in global
-     * space
-     * @param fillValue Fill the allocated array with this value
-     * @return A constant pointer to the non-constant allocated array. User
-     * should
-     * not deallocate this pointer.
-     */
-    template <class T>
-    inline T *const AllocateVariable(Variable<T> &var, T fillValue = 0)
-    {
-        throw std::invalid_argument("ERROR: type not supported for variable " +
-                                    var->name + " in call to GetVariable\n");
-    }
-
-    /**
-     * Needed for DataMan Engine
-     * @param callback function passed from the user
-     */
-    virtual void SetCallBack(std::function<void(const void *, std::string,
-                                                std::string, std::string, Dims)>
-                                 callback);
-
     /**
      * Write function that adds static checking on the variable to be passed by
      * values
@@ -133,10 +59,7 @@ public:
      * @param values pointer passed from the application
      */
     template <class T>
-    void Write(Variable<T> &variable, const T *values)
-    {
-        Write(variable, values);
-    }
+    void Write(Variable<T> &variable, const T *values);
 
     /**
      * String version
@@ -144,10 +67,7 @@ public:
      * @param values
      */
     template <class T>
-    void Write(const std::string &variableName, const T *values)
-    {
-        Write(variableName, values);
-    }
+    void Write(const std::string &variableName, const T *values);
 
     /**
      * Single value version
@@ -155,11 +75,7 @@ public:
      * @param values
      */
     template <class T>
-    void Write(Variable<T> &variable, const T values)
-    {
-        const T val = values;
-        Write(variable, &val);
-    }
+    void Write(Variable<T> &variable, const T values);
 
     /**
      * Single value version using string as variable handlers, allows rvalues to
@@ -168,77 +84,18 @@ public:
      * @param values
      */
     template <class T>
-    void Write(const std::string &variableName, const T values)
-    {
-        const T val = values;
-        Write(variableName, &val);
-    }
-
-    virtual void Write(Variable<char> &variable, const char *values);
-    virtual void Write(Variable<unsigned char> &variable,
-                       const unsigned char *values);
-    virtual void Write(Variable<short> &variable, const short *values);
-    virtual void Write(Variable<unsigned short> &variable,
-                       const unsigned short *values);
-    virtual void Write(Variable<int> &variable, const int *values);
-    virtual void Write(Variable<unsigned int> &variable,
-                       const unsigned int *values);
-    virtual void Write(Variable<long int> &variable, const long int *values);
-    virtual void Write(Variable<unsigned long int> &variable,
-                       const unsigned long int *values);
-    virtual void Write(Variable<long long int> &variable,
-                       const long long int *values);
-    virtual void Write(Variable<unsigned long long int> &variable,
-                       const unsigned long long int *values);
-    virtual void Write(Variable<float> &variable, const float *values);
-    virtual void Write(Variable<double> &variable, const double *values);
-    virtual void Write(Variable<long double> &variable,
-                       const long double *values);
-    virtual void Write(Variable<std::complex<float>> &variable,
-                       const std::complex<float> *values);
-    virtual void Write(Variable<std::complex<double>> &variable,
-                       const std::complex<double> *values);
-    virtual void Write(Variable<std::complex<long double>> &variable,
-                       const std::complex<long double> *values);
-    virtual void Write(VariableCompound &variable, const void *values);
+    void Write(const std::string &variableName, const T values);
+
+    /// Read API
 
     /**
-     * @brief Write functions can be overridden by derived classes. Base class
-     * behavior is to:
-     * 1) Write to Variable values (m_Values) using the pointer to default group
-     * *m_Group set with SetDefaultGroup function
-     * 2) Transform the data
-     * 3) Write to all capsules -> data and metadata
+     *
      * @param variableName
-     * @param values coming from user app
+     * @return
      */
-    virtual void Write(const std::string &variableName, const char *values);
-    virtual void Write(const std::string &variableName,
-                       const unsigned char *values);
-    virtual void Write(const std::string &variableName, const short *values);
-    virtual void Write(const std::string &variableName,
-                       const unsigned short *values);
-    virtual void Write(const std::string &variableName, const int *values);
-    virtual void Write(const std::string &variableName,
-                       const unsigned int *values);
-    virtual void Write(const std::string &variableName, const long int *values);
-    virtual void Write(const std::string &variableName,
-                       const unsigned long int *values);
-    virtual void Write(const std::string &variableName,
-                       const long long int *values);
-    virtual void Write(const std::string &variableName,
-                       const unsigned long long int *values);
-    virtual void Write(const std::string &variableName, const float *values);
-    virtual void Write(const std::string &variableName, const double *values);
-    virtual void Write(const std::string &variableName,
-                       const long double *values);
-    virtual void Write(const std::string &variableName,
-                       const std::complex<float> *values);
-    virtual void Write(const std::string &variableName,
-                       const std::complex<double> *values);
-    virtual void Write(const std::string &variableName,
-                       const std::complex<long double> *values);
-    virtual void Write(const std::string &variableName, const void *values);
+    template <class T>
+    Variable<T> *InquireVariable(const std::string &variableName,
+                                 const bool readIn = false);
 
     /**
      * Read function that adds static checking on the variable to be passed by
@@ -250,11 +107,7 @@ public:
      * must use Read(variable) instead intentionally
      */
     template <class T>
-    void Read(Variable<T> &variable, T *values)
-    {
-        ScheduleRead(variable, values);
-        PerformReads(PerformReadMode::BLOCKINGREAD);
-    }
+    void Read(Variable<T> &variable, T *values);
 
     /**
      * String version
@@ -262,11 +115,7 @@ public:
      * @param values
      */
     template <class T>
-    void Read(const std::string &variableName, T *values)
-    {
-        ScheduleRead(variableName, values);
-        PerformReads(PerformReadMode::BLOCKINGREAD);
-    }
+    void Read(const std::string &variableName, T *values);
 
     /**
      * Single value version
@@ -274,11 +123,7 @@ public:
      * @param values
      */
     template <class T>
-    void Read(Variable<T> &variable, T &values)
-    {
-        ScheduleRead(variable, &values);
-        PerformReads(PerformReadMode::BLOCKINGREAD);
-    }
+    void Read(Variable<T> &variable, T &values);
 
     /**
      * Single value version using string as variable handlers
@@ -286,33 +131,21 @@ public:
      * @param values
      */
     template <class T>
-    void Read(const std::string &variableName, T &values)
-    {
-        ScheduleRead(variableName, &values);
-        PerformReads(PerformReadMode::BLOCKINGREAD);
-    }
+    void Read(const std::string &variableName, T &values);
 
     /**
      * Unallocated version, ADIOS will allocate space for incoming data
      * @param variable
      */
     template <class T>
-    void Read(Variable<T> &variable)
-    {
-        ScheduleRead(variable);
-        PerformReads(PerformReadMode::BLOCKINGREAD);
-    }
+    void Read(Variable<T> &variable);
 
     /**
      * Unallocated version, ADIOS will allocate space for incoming data
      * @param variableName
      */
     template <class T>
-    void Read(const std::string &variableName)
-    {
-        ScheduleRead(variableName);
-        PerformReads(PerformReadMode::BLOCKINGREAD);
-    }
+    void Read(const std::string &variableName);
 
     /**
      * Read function that adds static checking on the variable to be passed by
@@ -323,10 +156,7 @@ public:
      * @param values pointer passed from the application
      */
     template <class T>
-    void ScheduleRead(Variable<T> &variable, T *values)
-    {
-        ScheduleRead(variable, values);
-    }
+    void ScheduleRead(Variable<T> &variable, T *values);
 
     /**
      * String version
@@ -334,10 +164,7 @@ public:
      * @param values
      */
     template <class T>
-    void ScheduleRead(const std::string &variableName, T *values)
-    {
-        ScheduleRead(variableName, values);
-    }
+    void ScheduleRead(const std::string &variableName, T *values);
 
     /**
      * Single value version
@@ -345,10 +172,7 @@ public:
      * @param values
      */
     template <class T>
-    void ScheduleRead(Variable<T> &variable, T &values)
-    {
-        ScheduleRead(variable, &values);
-    }
+    void ScheduleRead(Variable<T> &variable, T &values);
 
     /**
      * Single value version using string as variable handlers
@@ -356,77 +180,19 @@ public:
      * @param values
      */
     template <class T>
-    void ScheduleRead(const std::string &variableName, T &values)
-    {
-        ScheduleRead(variableName, &values);
-    }
+    void ScheduleRead(const std::string &variableName, T &values);
 
     /**
      * Unallocated version, ADIOS will allocate space for incoming data
      * @param variableName
      */
-    virtual void ScheduleRead(const std::string &variableName);
+    // virtual void ScheduleRead(const std::string &variableName);
 
     /**
      * Unallocated unspecified version, ADIOS will receive any variable and will
      * allocate space for incoming data
      */
-    virtual void ScheduleRead();
-
-    virtual void ScheduleRead(Variable<char> &variable, char *values);
-    virtual void ScheduleRead(Variable<unsigned char> &variable,
-                              unsigned char *values);
-    virtual void ScheduleRead(Variable<short> &variable, short *values);
-    virtual void ScheduleRead(Variable<unsigned short> &variable,
-                              unsigned short *values);
-    virtual void ScheduleRead(Variable<int> &variable, int *values);
-    virtual void ScheduleRead(Variable<unsigned int> &variable,
-                              unsigned int *values);
-    virtual void ScheduleRead(Variable<long int> &variable, long int *values);
-    virtual void ScheduleRead(Variable<unsigned long int> &variable,
-                              unsigned long int *values);
-    virtual void ScheduleRead(Variable<long long int> &variable,
-                              long long int *values);
-    virtual void ScheduleRead(Variable<unsigned long long int> &variable,
-                              unsigned long long int *values);
-    virtual void ScheduleRead(Variable<float> &variable, float *values);
-    virtual void ScheduleRead(Variable<double> &variable, double *values);
-    virtual void ScheduleRead(Variable<long double> &variable,
-                              long double *values);
-    virtual void ScheduleRead(Variable<std::complex<float>> &variable,
-                              std::complex<float> *values);
-    virtual void ScheduleRead(Variable<std::complex<double>> &variable,
-                              std::complex<double> *values);
-    virtual void ScheduleRead(Variable<std::complex<long double>> &variable,
-                              std::complex<long double> *values);
-
-    virtual void ScheduleRead(const std::string &variableName, char *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              unsigned char *values);
-    virtual void ScheduleRead(const std::string &variableName, short *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              unsigned short *values);
-    virtual void ScheduleRead(const std::string &variableName, int *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              unsigned int *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              long int *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              unsigned long int *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              long long int *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              unsigned long long int *values);
-    virtual void ScheduleRead(const std::string &variableName, float *values);
-    virtual void ScheduleRead(const std::string &variableName, double *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              long double *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              std::complex<float> *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              std::complex<double> *values);
-    virtual void ScheduleRead(const std::string &variableName,
-                              std::complex<long double> *values);
+    // virtual void ScheduleRead();
 
     /**
      * Perform all scheduled reads, either blocking until all reads completed,
@@ -434,7 +200,7 @@ public:
      * return immediately.
      * @param mode Blocking or non-blocking modes
      */
-    virtual void PerformReads(PerformReadMode mode);
+    virtual void PerformReads(ReadMode mode);
 
     /**
      * Reader application indicates that no more data will be read from the
@@ -447,7 +213,7 @@ public:
      * Indicates that a new step is going to be written as new variables come
      * in.
      */
-    virtual void Advance(const float timeout_sec = 0.0);
+    virtual void Advance(const float timeoutSeconds = 0.0);
 
     /**
      * Indicates that a new step is going to be written as new variables come
@@ -455,7 +221,8 @@ public:
      * @param mode Advance mode, there are different options for writers and
      * readers
      */
-    virtual void Advance(AdvanceMode mode, const float timeout_sec = 0.0);
+    virtual void Advance(const AdvanceMode mode,
+                         const float timeoutSeconds = 0.0);
 
     /** @brief Advance asynchronously and get a callback when readers release
      * access to the buffered step.
@@ -467,141 +234,167 @@ public:
      * @param callback Will be called when advance is completed.
      */
     virtual void
-    AdvanceAsync(AdvanceMode mode,
+    AdvanceAsync(const AdvanceMode mode,
                  std::function<void(std::shared_ptr<adios::Engine>)> callback);
 
-    AdvanceStatus GetAdvanceStatus() { return m_AdvanceStatus; }
+    AdvanceStatus GetAdvanceStatus();
 
-    // Read API
     /**
-     * Inquires and (optionally) allocates and copies the contents of a variable
-     * If success: it returns a pointer to the internal stored variable object
-     * in
-     * ADIOS class.
-     * If failure: it returns nullptr
-     * @param name variable name to look for
-     * @param readIn if true: reads the full variable and payload, allocating
-     * values in memory, if false: internal payload is nullptr
-     * @return success: it returns a pointer to the internal stored variable
-     * object in ADIOS class, failure: nullptr
+     * @brief Let ADIOS allocate memory for a variable in the buffer (bp),
+     * to be populated by the user. Variable dimensions are fixed.
+     * To decrease the cost of copying memory, a user may let ADIOS allocate
+     * the memory for a user-variable,
+     * according to the definition of an ADIOS-variable. The memory will be
+     * part
+     * of the ADIOS buffer used
+     * by the engine and it lives until the engine (file, stream) is closed.
+     * A variable that has been allocated this way (cannot have its local
+     * dimensions changed, and AdvanceAsync() should be
+     * used instead of Advance() and the user-variable must not be modified
+     * by
+     * the application until the notification arrives.
+     * This is required so that any reader can access the written data
+     * before
+     * the application overwrites it.
+     * @param var Variable with defined local dimensions and offsets in
+     * global
+     * space
+     * @param fillValue Fill the allocated array with this value
+     * @return A constant pointer reference to the allocated array.
      */
-    virtual Variable<void> *InquireVariable(const std::string &variableName,
-                                            const bool readIn = true);
-    virtual Variable<char> *InquireVariableChar(const std::string &variableName,
-                                                const bool readIn = true);
-    virtual Variable<unsigned char> *
-    InquireVariableUChar(const std::string &variableName,
-                         const bool readIn = true);
-    virtual Variable<short> *
-    InquireVariableShort(const std::string &variableName,
-                         const bool readIn = true);
-
-    virtual Variable<unsigned short> *
-    InquireVariableUShort(const std::string &variableName,
-                          const bool readIn = true);
-
-    virtual Variable<int> *InquireVariableInt(const std::string &variableName,
-                                              const bool readIn = true);
-    virtual Variable<unsigned int> *
-    InquireVariableUInt(const std::string &variableName,
-                        const bool readIn = true);
-
-    virtual Variable<long int> *
-    InquireVariableLInt(const std::string &variableName,
-                        const bool readIn = true);
-
-    virtual Variable<unsigned long int> *
-    InquireVariableULInt(const std::string &variableName,
-                         const bool readIn = true);
-
-    virtual Variable<long long int> *
-    InquireVariableLLInt(const std::string &variableName,
-                         const bool readIn = true);
-
-    virtual Variable<unsigned long long int> *
-    InquireVariableULLInt(const std::string &variableName,
-                          const bool readIn = true);
-
-    virtual Variable<float> *
-    InquireVariableFloat(const std::string &variableName,
-                         const bool readIn = true);
-
-    virtual Variable<double> *
-    InquireVariableDouble(const std::string &variableName,
-                          const bool readIn = true);
-
-    virtual Variable<long double> *
-    InquireVariableLDouble(const std::string &variableName,
-                           const bool readIn = true);
-
-    virtual Variable<std::complex<float>> *
-    InquireVariableCFloat(const std::string &variableName,
-                          const bool readIn = true);
-
-    virtual Variable<std::complex<double>> *
-    InquireVariableCDouble(const std::string &variableName,
-                           const bool readIn = true);
-
-    virtual Variable<std::complex<long double>> *
-    InquireVariableCLDouble(const std::string &variableName,
-                            const bool readIn = true);
+    template <class T>
+    T *AllocateVariable(Variable<T> &var, T fillValue = 0);
 
-    virtual VariableCompound *
-    InquireVariableCompound(const std::string &variableName,
-                            const bool readIn = true);
+    /**
+     * Needed for DataMan Engine
+     * @param callback function passed from the user
+     */
+    virtual void
+    SetCallBack(std::function<void(const void *, std::string, std::string,
+                                   std::string, std::vector<size_t>)>
+                    callback);
 
     /** Return the names of all variables present in a stream/file opened for
      * reading
-     *
      * @return a vector of strings
      */
     std::vector<std::string> VariableNames();
 
     /**
      * Closes a particular transport, or all if -1
-     * @param transportIndex order from Method AddTransport
+     * @param transportIndex order from IO AddTransport
      */
     virtual void Close(const int transportIndex = -1) = 0;
 
 protected:
-    ADIOS &m_ADIOS; ///< creates Engine at Open
-    std::vector<std::shared_ptr<Transport>>
-        m_Transports;               ///< transports managed
-    const bool m_DebugMode = false; ///< true: additional exceptions checks
-    unsigned int m_nThreads = 0;    ///< from Method nthreads
-    const std::string
-        m_EndMessage; ///< added to exceptions to improve debugging
+    /** from derived class */
+    const std::string m_EngineType;
+
+    /** IO class object that creates this Engine at Open */
+    IO &m_IO;
+
+    /** Unique name for this Engine within m_IO */
+    const std::string &m_Name;
+
+    /** open mode from ADIOSTypes.h OpenMode */
+    const OpenMode m_OpenMode;
+
+    /** from ADIOS class passed to Engine created with Open
+     *  if no new communicator is passed */
+    MPI_Comm m_MPIComm;
+
+    /** true: additional exceptions */
+    const bool m_DebugMode = false;
+
+    /** added to exceptions to improve debugging */
+    std::string m_EndMessage;
+
+    /** Tracks written variables */
     std::set<std::string> m_WrittenVariables;
+
     AdvanceStatus m_AdvanceStatus = AdvanceStatus::OK;
 
-    virtual void Init();           ///< Initialize m_Capsules and m_Transports
-    virtual void InitParameters(); ///< Initialize parameters from Method
-    virtual void InitTransports(); ///< Initialize transports from Method
+    /** Called from constructors */
+    virtual void Init();
 
-    /**
-     * Used to verify parameters in m_Method containers
-     * @param itParameter iterator to a certain parameter
-     * @param parameters map of parameters, from m_Method
-     * @param parameterName used if exception is thrown to provide debugging
-     * information
-     * @param hint used if exception is thrown to provide debugging information
-     */
-    void CheckParameter(
-        const std::map<std::string, std::string>::const_iterator itParameter,
-        const std::map<std::string, std::string> &parameters,
-        const std::string parameterName, const std::string hint) const;
+    /** From IO SetParameters */
+    virtual void InitParameters();
+
+    /** From IO AddTransport */
+    virtual void InitTransports();
+
+// Known-type
+#define declare_type(T)                                                        \
+    virtual void DoWrite(Variable<T> &variable, const T *values);
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
-    bool TransportNamesUniqueness() const; ///< checks if transport names are
-                                           /// unique among the same types (file
-                                           /// I/O)
+    virtual void DoWrite(VariableCompound &variable, const void *values);
 
     /**
-     * Throws an exception in debug mode if transport index is out of range.
-     * @param transportIndex must be in the range [ -1 , m_Transports.size()-1 ]
+     * Finds the variable and call the corresponding DoWrite by
+     * type
+     * @param variableName
+     * @param values application values
      */
-    void CheckTransportIndex(const int transportIndex);
+    void DoWrite(const std::string &variableName, const void *values);
+
+    // READ
+    virtual VariableBase *InquireVariableUnknown(const std::string &name,
+                                                 const bool readIn);
+    virtual Variable<char> *InquireVariableChar(const std::string &name,
+                                                const bool readIn);
+    virtual Variable<unsigned char> *
+    InquireVariableUChar(const std::string &name, const bool readIn);
+    virtual Variable<short> *InquireVariableShort(const std::string &name,
+                                                  const bool readIn);
+    virtual Variable<unsigned short> *
+    InquireVariableUShort(const std::string &name, const bool readIn);
+    virtual Variable<int> *InquireVariableInt(const std::string &name,
+                                              const bool readIn);
+    virtual Variable<unsigned int> *InquireVariableUInt(const std::string &name,
+                                                        const bool readIn);
+    virtual Variable<long int> *InquireVariableLInt(const std::string &name,
+                                                    const bool readIn);
+    virtual Variable<unsigned long int> *
+    InquireVariableULInt(const std::string &name, const bool readIn);
+    virtual Variable<long long int> *
+    InquireVariableLLInt(const std::string &name, const bool readIn);
+    virtual Variable<unsigned long long int> *
+    InquireVariableULLInt(const std::string &name, const bool readIn);
+
+    virtual Variable<float> *InquireVariableFloat(const std::string &name,
+                                                  const bool readIn);
+    virtual Variable<double> *InquireVariableDouble(const std::string &name,
+                                                    const bool readIn);
+    virtual Variable<long double> *
+    InquireVariableLDouble(const std::string &name, const bool readIn);
+
+    virtual Variable<cfloat> *InquireVariableCFloat(const std::string &name,
+                                                    const bool readIn);
+    virtual Variable<cdouble> *InquireVariableCDouble(const std::string &name,
+                                                      const bool readIn);
+    virtual Variable<cldouble> *InquireVariableCLDouble(const std::string &name,
+                                                        const bool readIn);
+
+// Known-type
+#define declare_type(T)                                                        \
+    virtual void DoScheduleRead(Variable<T> &variable, const T *values);       \
+    virtual void DoScheduleRead(const std::string &variableName,               \
+                                const T *values);
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
+
+    void DoScheduleRead(const std::string &variableName, void *values);
+
+private:
+    /** Throw exception by Engine virtual functions not implemented by a derived
+     * class */
+    void ThrowUp(const std::string function) const;
 };
 
-} // end namespace
+} // end namespace adios
+
+#include "Engine.inl"
 
 #endif /* ADIOS2_CORE_ENGINE_H_ */
diff --git a/source/adios2/core/Engine.inl b/source/adios2/core/Engine.inl
new file mode 100644
index 0000000000000000000000000000000000000000..e4e76bda9a287a7bd88139350aabb3b55007bfca
--- /dev/null
+++ b/source/adios2/core/Engine.inl
@@ -0,0 +1,127 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Engine.inl
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_ENGINE_INL_
+#define ADIOS2_CORE_ENGINE_INL_
+#ifndef ADIOS2_CORE_ENGINE_H_
+#error "Inline file should only be included from it's header, never on it's own"
+#endif
+
+namespace adios
+{
+
+template <class T>
+T *Engine::AllocateVariable(Variable<T> &variable, T fillValue)
+{
+    throw std::invalid_argument("ERROR: type not supported for variable " +
+                                variable.m_Name + " in call to \n");
+}
+
+template <class T>
+void Engine::Write(Variable<T> &variable, const T *values)
+{
+    if (m_DebugMode)
+    {
+        variable.CheckDims("in call to Write");
+    }
+
+    DoWrite(variable, values);
+}
+
+template <class T>
+void Engine::Write(const std::string &variableName, const T *values)
+{
+    Write(m_IO.GetVariable<T>(variableName), values);
+}
+
+template <class T>
+void Engine::Write(Variable<T> &variable, const T values)
+{
+    const T val = values; // need an address for memory copy
+    Write(variable, &values);
+}
+
+template <class T>
+void Engine::Write(const std::string &variableName, const T values)
+{
+    const T val = values; // need an address for memory copy
+    Write(m_IO.GetVariable<T>(variableName), &values);
+}
+
+template <class T>
+void Engine::Read(Variable<T> &variable, T *values)
+{
+    DoScheduleRead(variable, values);
+    PerformReads(ReadMode::Blocking);
+}
+
+template <class T>
+void Engine::Read(const std::string &variableName, T *values)
+{
+    DoScheduleRead(variableName, values);
+    PerformReads(ReadMode::Blocking);
+}
+
+template <class T>
+void Engine::Read(Variable<T> &variable, T &values)
+{
+    DoScheduleRead(variable, &values);
+    PerformReads(ReadMode::Blocking);
+}
+
+template <class T>
+void Engine::Read(const std::string &variableName, T &values)
+{
+    DoScheduleRead(variableName, &values);
+    PerformReads(ReadMode::Blocking);
+}
+
+template <class T>
+void Engine::Read(Variable<T> &variable)
+{
+    DoScheduleRead(variable);
+    PerformReads(ReadMode::Blocking);
+}
+
+template <class T>
+void Engine::Read(const std::string &variableName)
+{
+    // TODO
+    // DoScheduleRead(variableName);
+    // PerformReads(PerformReadMode::BLOCKINGREAD);
+}
+
+template <class T>
+void Engine::ScheduleRead(Variable<T> &variable, T *values)
+{
+    DoScheduleRead(variable, values);
+}
+
+template <class T>
+void Engine::ScheduleRead(const std::string &variableName, T *values)
+{
+    DoScheduleRead(variableName, values);
+}
+
+template <class T>
+void Engine::ScheduleRead(Variable<T> &variable, T &values)
+{
+    DoScheduleRead(variable, &values);
+}
+
+template <class T>
+void Engine::ScheduleRead(const std::string &variableName, T &values)
+{
+    DoScheduleRead(variableName, &values);
+}
+
+} // end namespace adios
+
+#endif /* ADIOS2_CORE_ENGINE_INL_ */
diff --git a/source/adios2/core/Engine.tcc b/source/adios2/core/Engine.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..f370a64bf06cdbc7ca61ae505cef2944f64e7610
--- /dev/null
+++ b/source/adios2/core/Engine.tcc
@@ -0,0 +1,145 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Engine.tcc
+ *
+ *  Created on: Jun 2, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_ENGINE_TCC_
+#define ADIOS2_CORE_ENGINE_TCC_
+
+#include "Engine.h"
+
+namespace adios
+{
+
+template <>
+Variable<char> *Engine::InquireVariable<char>(const std::string &variableName,
+                                              const bool readIn)
+{
+    return InquireVariableChar(variableName, readIn);
+}
+
+template <>
+Variable<unsigned char> *
+Engine::InquireVariable<unsigned char>(const std::string &variableName,
+                                       const bool readIn)
+{
+    return InquireVariableUChar(variableName, readIn);
+}
+
+template <>
+Variable<short> *Engine::InquireVariable<short>(const std::string &variableName,
+                                                const bool readIn)
+{
+    return InquireVariableShort(variableName, readIn);
+}
+
+template <>
+Variable<unsigned short> *
+Engine::InquireVariable<unsigned short>(const std::string &variableName,
+                                        const bool readIn)
+{
+    return InquireVariableUShort(variableName, readIn);
+}
+
+template <>
+Variable<int> *Engine::InquireVariable<int>(const std::string &variableName,
+                                            const bool readIn)
+{
+    return InquireVariableInt(variableName, readIn);
+}
+
+template <>
+Variable<unsigned int> *
+Engine::InquireVariable<unsigned int>(const std::string &variableName,
+                                      const bool readIn)
+{
+    return InquireVariableUInt(variableName, readIn);
+}
+
+template <>
+Variable<long int> *
+Engine::InquireVariable<long int>(const std::string &variableName,
+                                  const bool readIn)
+{
+    return InquireVariableLInt(variableName, readIn);
+}
+
+template <>
+Variable<long long int> *
+Engine::InquireVariable<long long int>(const std::string &variableName,
+                                       const bool readIn)
+{
+    return InquireVariableLLInt(variableName, readIn);
+}
+
+template <>
+Variable<unsigned long int> *
+Engine::InquireVariable<unsigned long int>(const std::string &variableName,
+                                           const bool readIn)
+{
+    return InquireVariableULInt(variableName, readIn);
+}
+
+template <>
+Variable<unsigned long long int> *
+Engine::InquireVariable<unsigned long long int>(const std::string &variableName,
+                                                const bool readIn)
+{
+    return InquireVariableULLInt(variableName, readIn);
+}
+
+template <>
+Variable<float> *Engine::InquireVariable<float>(const std::string &variableName,
+                                                const bool readIn)
+{
+    return InquireVariableFloat(variableName, readIn);
+}
+
+template <>
+Variable<double> *
+Engine::InquireVariable<double>(const std::string &variableName,
+                                const bool readIn)
+{
+    return InquireVariableDouble(variableName, readIn);
+}
+
+template <>
+Variable<long double> *
+Engine::InquireVariable<long double>(const std::string &variableName,
+                                     const bool readIn)
+{
+    return InquireVariableLDouble(variableName, readIn);
+}
+
+template <>
+Variable<cfloat> *
+Engine::InquireVariable<cfloat>(const std::string &variableName,
+                                const bool readIn)
+{
+    return InquireVariableCFloat(variableName, readIn);
+}
+
+template <>
+Variable<cdouble> *
+Engine::InquireVariable<cdouble>(const std::string &variableName,
+                                 const bool readIn)
+{
+    return InquireVariableCDouble(variableName, readIn);
+}
+
+template <>
+Variable<cldouble> *
+Engine::InquireVariable<cldouble>(const std::string &variableName,
+                                  const bool readIn)
+{
+    return InquireVariableCLDouble(variableName, readIn);
+}
+
+} // end namespace adios
+
+#endif /** ADIOS2_CORE_ENGINE_TCC_ */
diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9753acc3aa3a178605d8eb2ef2eadb06b7b791e
--- /dev/null
+++ b/source/adios2/core/IO.cpp
@@ -0,0 +1,288 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * IO.cpp
+ *
+ *  Created on: Jan 6, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "IO.h"
+#include "IO.tcc"
+
+#include "adios2/ADIOSMPI.h"
+#include "adios2/helper/adiosFunctions.h" //BuildParametersMap
+
+#include "adios2/engine/bp/BPFileWriter.h"
+
+#ifdef ADIOS2_HAVE_DATAMAN // external dependencies
+#include "adios2/engine/dataman/DataManReader.h"
+#include "adios2/engine/dataman/DataManWriter.h"
+#endif
+
+#ifdef ADIOS2_HAVE_ADIOS1 // external dependencies
+#include "adios2/engine/adios1/ADIOS1Reader.h"
+#include "adios2/engine/adios1/ADIOS1Writer.h"
+#endif
+
+#ifdef ADIOS2_HAVE_HDF5 // external dependencies
+#include "adios2/engine/hdf5/HDF5ReaderP.h"
+#include "adios2/engine/hdf5/HDF5WriterP.h"
+#endif
+
+namespace adios
+{
+
+IO::IO(const std::string name, MPI_Comm mpiComm, const bool inConfigFile,
+       const bool debugMode)
+: m_Name(name), m_MPIComm(mpiComm), m_InConfigFile(inConfigFile),
+  m_DebugMode(debugMode)
+{
+}
+
+void IO::SetEngine(const std::string engineType) { m_EngineType = engineType; }
+void IO::SetIOMode(const IOMode ioMode) { m_IOMode = ioMode; };
+
+VariableCompound &IO::GetVariableCompound(const std::string &name)
+{
+    return m_Compound.at(GetVariableIndex(name));
+}
+
+std::string IO::GetVariableType(const std::string &name) const
+{
+    std::string type;
+
+    auto itVariable = m_Variables.find(name);
+    if (itVariable != m_Variables.end())
+    {
+        type = itVariable->second.first;
+    }
+
+    return type;
+}
+
+bool IO::InConfigFile() const { return m_InConfigFile; };
+
+bool IO::RemoveVariable(const std::string &name) noexcept
+{
+    bool isRemoved = false;
+    auto itVariable = m_Variables.find(name);
+    // variable exists
+    if (itVariable != m_Variables.end())
+    {
+        // first remove the Variable object
+        const std::string type(itVariable->second.first);
+        const unsigned int index(itVariable->second.second);
+
+        if (type == "compound")
+        {
+            auto variableMap = m_Compound;
+            variableMap.erase(index);
+        }
+#define declare_type(T)                                                        \
+    else if (type == GetType<T>())                                             \
+    {                                                                          \
+        auto variableMap = GetVariableMap<T>();                                \
+        variableMap.erase(index);                                              \
+    }
+        ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
+
+        isRemoved = true;
+    }
+
+    if (isRemoved)
+    {
+        m_Variables.erase(name);
+    }
+
+    return isRemoved;
+}
+
+std::shared_ptr<Engine> IO::Open(const std::string &name,
+                                 const OpenMode openMode, MPI_Comm mpiComm)
+{
+    if (m_DebugMode)
+    {
+        // Check if Engine already exists
+        if (m_EngineNames.count(name) == 1)
+        {
+            throw std::invalid_argument(
+                "ERROR: IO Engine with name " + name +
+                " already created by Open, in call from Open.\n");
+        }
+    }
+
+    std::shared_ptr<Engine> engine;
+    m_EngineNames.insert(name);
+
+    const bool isDefaultWriter =
+        m_EngineType.empty() &&
+                (openMode == OpenMode::Write || openMode == OpenMode::Append)
+            ? true
+            : false;
+
+    const bool isDefaultReader =
+        m_EngineType.empty() &&
+                (openMode == OpenMode::Read || openMode == OpenMode::ReadWrite)
+            ? true
+            : false;
+
+    if (isDefaultWriter || m_EngineType == "BPFileWriter")
+    {
+        engine = std::make_shared<BPFileWriter>(*this, name, openMode, mpiComm);
+    }
+    else if (isDefaultReader || m_EngineType == "BPFileReader")
+    {
+        // engine = std::make_shared<BPFileReader>(*this, name, openMode,
+        // mpiComm);
+    }
+    else if (m_EngineType == "DataManWriter")
+    {
+#ifdef ADIOS2_HAVE_DATAMAN
+        engine =
+            std::make_shared<DataManWriter>(*this, name, openMode, mpiComm);
+#else
+        throw std::invalid_argument(
+            "ERROR: this version didn't compile with "
+            "DataMan library, can't Open DataManWriter\n");
+#endif
+    }
+    else if (m_EngineType == "DataManReader")
+    {
+#ifdef ADIOS2_HAVE_DATAMAN
+        engine =
+            std::make_shared<DataManReader>(*this, name, openMode, mpiComm);
+#else
+        throw std::invalid_argument(
+            "ERROR: this version didn't compile with "
+            "DataMan library, can't Open DataManReader\n");
+#endif
+    }
+    else if (m_EngineType == "ADIOS1Writer")
+    {
+#ifdef ADIOS2_HAVE_ADIOS1
+        engine = std::make_shared<ADIOS1Writer>(*this, name, openMode, mpiComm);
+#else
+        throw std::invalid_argument(
+            "ERROR: this version didn't compile with ADIOS "
+            "1.x library, can't Open ADIOS1Writer\n");
+#endif
+    }
+    else if (m_EngineType == "ADIOS1Reader")
+    {
+#ifdef ADIOS2_HAVE_ADIOS1
+        engine = std::make_shared<ADIOS1Reader>(*this, name, openMode, mpiComm);
+#else
+        throw std::invalid_argument(
+            "ERROR: this version didn't compile with ADIOS "
+            "1.x library, can't Open ADIOS1Reader\n");
+#endif
+    }
+    else if (m_EngineType == "HDF5Writer")
+    {
+#ifdef ADIOS2_HAVE_HDF5
+        engine = std::make_shared<HDF5WriterP>(*this, name, openMode, mpiComm);
+#else
+        throw std::invalid_argument("ERROR: this version didn't compile with "
+                                    "HDF5 library, can't use HDF5\n");
+#endif
+    }
+    else if (m_EngineType == "HDF5Reader")
+    {
+#ifdef ADIOS2_HAVE_HDF5
+        engine = std::make_shared<HDF5ReaderP>(*this, name, openMode, mpiComm);
+#else
+        throw std::invalid_argument("ERROR: this version didn't compile with "
+                                    "HDF5 library, can't use HDF5\n");
+#endif
+    }
+    else
+    {
+        if (m_DebugMode)
+        {
+            throw std::invalid_argument("ERROR: engine " + m_EngineType +
+                                        " not supported, IO SetEngine must add "
+                                        "a supported engine, in call to "
+                                        "Open\n");
+        }
+    }
+
+    return engine;
+}
+
+std::shared_ptr<Engine> IO::Open(const std::string &name,
+                                 const OpenMode openMode)
+{
+    return Open(name, openMode, m_MPIComm);
+}
+
+// PRIVATE Functions
+unsigned int
+IO::AddTransportParameters(const std::string type,
+                           const std::vector<std::string> &parameters)
+{
+    if (m_DebugMode)
+    {
+        if (type.empty() || type.find("=") != type.npos)
+        {
+            throw std::invalid_argument(
+                "ERROR: first argument in AddTransport must "
+                "be a single word for transport\n");
+        }
+    }
+
+    Params mapParameters = BuildParametersMap(parameters, m_DebugMode);
+
+    if (m_DebugMode)
+    {
+        if (mapParameters.count("transport") == 1)
+        {
+            std::invalid_argument("ERROR: transport can't be redefined with "
+                                  "\"transport=type\", "
+                                  "type must be the first argument\n");
+        }
+    }
+
+    mapParameters["transport"] = type;
+    m_TransportsParameters.push_back(std::move(mapParameters));
+    return static_cast<unsigned int>(m_TransportsParameters.size() - 1);
+}
+
+unsigned int IO::GetVariableIndex(const std::string &name) const
+{
+    if (m_DebugMode)
+    {
+        if (!VariableExists(name))
+        {
+            throw std::invalid_argument(
+                "ERROR: variable " + m_Name +
+                " wasn't created with DefineVariable, in call to IO object " +
+                m_Name + " GetVariable\n");
+        }
+    }
+    auto itVariable = m_Variables.find(name);
+    return itVariable->second.second;
+}
+
+bool IO::VariableExists(const std::string &name) const
+{
+    bool exists = false;
+    if (m_Variables.count(name) == 1)
+    {
+        exists = true;
+    }
+    return exists;
+}
+
+// Explicitly instantiate the necessary public template implementations
+#define define_template_instantiation(T)                                       \
+    template Variable<T> &IO::DefineVariable<T>(                               \
+        const std::string &, const Dims, const Dims, const Dims, const bool);  \
+    template Variable<T> &IO::GetVariable<T>(const std::string &);
+
+ADIOS2_FOREACH_TYPE_1ARG(define_template_instantiation)
+#undef define_template_instatiation
+
+} // end namespace adios
diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h
new file mode 100644
index 0000000000000000000000000000000000000000..87df704d816b8d62df8180bfb7c72eac1b0399e0
--- /dev/null
+++ b/source/adios2/core/IO.h
@@ -0,0 +1,284 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * IO.h factory class of Parameters, Variables, Transports to Engines
+ *
+ *  Created on: Dec 16, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_IO_H_
+#define ADIOS2_CORE_IO_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <map>
+#include <string>
+#include <utility> //std::pair
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSMPICommOnly.h"
+#include "adios2/ADIOSMacros.h"
+#include "adios2/ADIOSTypes.h"
+#include "adios2/core/Variable.h"
+#include "adios2/core/VariableCompound.h"
+
+namespace adios
+{
+
+// forward declaration needed as IO is passed to Engine derived
+// classes
+class Engine;
+
+/** Factory class IO for settings, variables, and transports to an engine */
+class IO
+{
+
+public:
+    /** unique identifier */
+    const std::string m_Name;
+
+    /** from ADIOS class passed to Engine created with Open
+     *  if no new communicator is passed */
+    MPI_Comm m_MPIComm;
+
+    /** true: extra exceptions checks */
+    const bool m_DebugMode = false;
+
+    /** from ADIOS class passed to Engine created with Open */
+    const std::string m_HostLanguage = "C++";
+
+    /** From SetParameter, parameters for a particular engine from m_Type */
+    Params m_Parameters;
+
+    /** From AddTransport, parameters in map for each transport in vector */
+    std::vector<Params> m_TransportsParameters;
+
+    /**
+     * Constructor called from ADIOS factory class
+     * @param name unique identifier for this IO object
+     * @param mpiComm MPI communicator from ADIOS factory class
+     * @param inConfigFile IO defined in config file (XML)
+     * @param debugMode true: extra exception checks (recommended)
+     */
+    IO(const std::string name, MPI_Comm mpiComm, const bool inConfigFile,
+       const bool debugMode);
+
+    ~IO() = default;
+
+    /**
+     * Sets the engine type for this IO class object
+     * @param engine
+     */
+    void SetEngine(const std::string engine);
+
+    /** Set the IO mode (collective or independent)
+     * @param IO mode */
+    void SetIOMode(const IOMode mode);
+
+    /**
+     * Sets parameters for the method in "parameter=value" format
+     * @param args list of parameters with format "parameter1=value1", ...,
+     * "parameterN=valueN"
+     */
+    template <class... Args>
+    void SetParameters(Args... args);
+
+    /**
+     * Adds a transport and its parameters for the method
+     * @param type must be a supported transport type under /include/transport
+     * @param args list of parameters for a transport with format
+     * "parameter1=value1", ..., "parameterN=valueN"
+     */
+    template <class... Args>
+    unsigned int AddTransport(const std::string type, Args... args);
+
+    /**
+     * Define a Variable of primitive data type for I/O.
+     * Default (name only) is a local single value,
+     * in order to be compatible with ADIOS1.
+     * @param name variable name, must be unique within Method
+     * @param shape overall dimensions e.g. {Nx*size, Ny*size, Nz*size}
+     * @param start point (offset) for MPI rank e.g. {Nx*rank, Ny*rank, Nz*rank}
+     * @param count length for MPI rank e.g. {Nx, Ny, Nz}
+     * @param constantShape true if dimensions, offsets and local sizes don't
+     * change over time
+     * @return reference to Variable object
+     */
+    template <class T>
+    Variable<T> &DefineVariable(const std::string &name, const Dims shape = {},
+                                const Dims start = {}, const Dims count = {},
+                                const bool constantShape = false);
+
+    /**
+     * Define a Variable of primitive data type for I/O.
+     * Default (name only) is a local single value,
+     * in order to be compatible with ADIOS1.
+     * @param name variable name, must be unique within Method
+     * @param shape overall dimensions e.g. {Nx*size, Ny*size, Nz*size}
+     * @param start point (offset) for MPI rank e.g. {Nx*rank, Ny*rank, Nz*rank}
+     * @param count length for MPI rank e.g. {Nx, Ny, Nz}
+     * @param constantShape true if dimensions, offsets and local sizes don't
+     * change over time
+     * @return reference to Variable object
+     */
+    template <class T>
+    VariableCompound &
+    DefineVariableCompound(const std::string &name, const Dims shape = Dims{},
+                           const Dims start = Dims{}, const Dims count = Dims{},
+                           const bool constantShape = false);
+
+    /**
+     * Removes an existing Variable previously created with DefineVariable or
+     * DefineVariableCompound
+     * @param name
+     * @return true: found and removed variable, false: not found, nothing to
+     * remove
+     */
+    bool RemoveVariable(const std::string &name) noexcept;
+
+    /**
+     * Gets an existing variable of primitive type by name
+     * @param name of variable to be retrieved
+     * @return reference to an existing variable created with DefineVariable
+     * throws an exception if Variable is not found
+     */
+    template <class T>
+    Variable<T> &GetVariable(const std::string &name);
+
+    /**
+     * Gets an existing variable of compound type by name
+     * @param name of variable to be retrieved
+     * @return reference to an existing variable created with DefineVariable
+     * throws an exception if VariableCompound is not found
+     */
+    VariableCompound &GetVariableCompound(const std::string &name);
+
+    /**
+     * Get the type if variable (by name id) exists
+     * @param name input id
+     * @return type as string, if not found returns an empty string
+     */
+    std::string GetVariableType(const std::string &name) const;
+
+    /**
+     * Check existence in config file passed to ADIOS class
+     * @return true: defined in config file
+     */
+    bool InConfigFile() const;
+
+    /**
+     * Creates a polymorphic object that derives the Engine class,
+     * based on the SetEngine function or config file input
+     * @param name unique engine identifier within IO object
+     * (file name in case of File transports)
+     * @param openMode write, read, append from ADIOSTypes.h OpenMode
+     * @param mpiComm assigns a new communicator to the Engine
+     * @return a smart pointer to a derived object of the Engine class
+     */
+    std::shared_ptr<Engine> Open(const std::string &name,
+                                 const OpenMode openMode, MPI_Comm mpiComm);
+
+    /**
+     * Overloaded version that reuses the MPI_Comm object passed
+     * from the ADIOS class to the IO class
+     * @param name unique engine identifier within IO object
+     * (file name in case of File transports)
+     * @param openMode write, read, append from ADIOSTypes.h OpenMode
+     * @return a smart pointer to a derived object of the Engine class
+     */
+    std::shared_ptr<Engine> Open(const std::string &name,
+                                 const OpenMode openMode);
+
+    // READ FUNCTIONS:
+    void SetReadMultiplexPattern(const ReadMultiplexPattern pattern);
+    void SetStreamOpenMode(const StreamOpenMode mode);
+
+private:
+    /** true: exist in config file (XML) */
+    const bool m_InConfigFile = false;
+
+    /** BPFileWriter engine default if unknown */
+    std::string m_EngineType;
+
+    /** Independent (default) or Collective */
+    adios::IOMode m_IOMode = adios::IOMode::Independent;
+
+    // Variables
+    /**
+     * Map holding variable identifiers
+     * <pre>
+     * key: unique variable name,
+     * value: pair.first = type as string GetType<T> from adiosTemplates.h
+     *        pair.second = index in fixed size map (e.g. m_Int8, m_Double)
+     * </pre>
+     */
+    std::map<std::string, std::pair<std::string, unsigned int>> m_Variables;
+
+    /** Variable containers based on fixed-size type */
+    std::map<unsigned int, Variable<char>> m_Char;
+    std::map<unsigned int, Variable<unsigned char>> m_UChar;
+    std::map<unsigned int, Variable<short>> m_Short;
+    std::map<unsigned int, Variable<unsigned short>> m_UShort;
+    std::map<unsigned int, Variable<int>> m_Int;
+    std::map<unsigned int, Variable<unsigned int>> m_UInt;
+    std::map<unsigned int, Variable<long int>> m_LInt;
+    std::map<unsigned int, Variable<unsigned long int>> m_ULInt;
+    std::map<unsigned int, Variable<long long int>> m_LLInt;
+    std::map<unsigned int, Variable<unsigned long long int>> m_ULLInt;
+    std::map<unsigned int, Variable<float>> m_Float;
+    std::map<unsigned int, Variable<double>> m_Double;
+    std::map<unsigned int, Variable<long double>> m_LDouble;
+    std::map<unsigned int, Variable<cfloat>> m_CFloat;
+    std::map<unsigned int, Variable<cdouble>> m_CDouble;
+    std::map<unsigned int, Variable<cldouble>> m_CLDouble;
+    std::map<unsigned int, VariableCompound> m_Compound;
+
+    std::map<std::string, std::string> m_AttributesString;
+    std::map<std::string, double> m_AttributesNumeric;
+
+    std::set<std::string> m_EngineNames;
+
+    /**
+     * Called from AddTransport to transform parameter to a map
+     * @param type
+     * @param parameters
+     * @return transport index
+     */
+    unsigned int
+    AddTransportParameters(const std::string type,
+                           const std::vector<std::string> &parameters);
+
+    /** Gets the internal reference to a variable map for type T
+     *  This function is specialized in IO.tcc */
+    template <class T>
+    std::map<unsigned int, Variable<T>> &GetVariableMap();
+
+    /** Gets the internal index in variable map for an existing variable */
+    unsigned int GetVariableIndex(const std::string &name) const;
+
+    /**
+     * Checks if variable exists by checking its name
+     * @param name unique variable name to be checked against existing variables
+     * @return true: variable name exists, false: variable name doesn't exist
+     */
+    bool VariableExists(const std::string &name) const;
+};
+
+// Explicit declaration of the public template methods
+#define declare_template_instantiation(T)                                      \
+    extern template Variable<T> &IO::DefineVariable<T>(                        \
+        const std::string &name, const Dims, const Dims, const Dims,           \
+        const bool constantShape);                                             \
+    extern template Variable<T> &IO::GetVariable<T>(const std::string &name);
+
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
+} // end namespace adios
+
+#include "adios2/core/IO.inl"
+
+#endif /* ADIOS2_CORE_IO_H_ */
diff --git a/source/adios2/core/IO.inl b/source/adios2/core/IO.inl
new file mode 100644
index 0000000000000000000000000000000000000000..d7a8505442911b709dcaa079c624cc42daae98e2
--- /dev/null
+++ b/source/adios2/core/IO.inl
@@ -0,0 +1,62 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * IO.inl inline template functions implementation of IO class
+ *
+ *  Created on: May 15, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_IO_INL_
+#define ADIOS2_CORE_IO_INL_
+#ifndef ADIOS2_CORE_IO_H_
+#error "Inline file should only be included from it's header, never on it's own"
+#endif
+
+#include "adios2/ADIOSMacros.h"
+#include "adios2/helper/adiosFunctions.h" //BuildParametersMap
+
+namespace adios
+{
+
+template <class... Args>
+void IO::SetParameters(Args... args)
+{
+    std::vector<std::string> parameters = {args...};
+    m_Parameters = BuildParametersMap(parameters, m_DebugMode);
+}
+
+template <class... Args>
+unsigned int IO::AddTransport(const std::string type, Args... args)
+{
+    std::vector<std::string> parameters = {args...};
+    return AddTransportParameters(type, parameters);
+}
+
+template <class T>
+VariableCompound &IO::DefineVariableCompound(const std::string &name,
+                                             const Dims shape, const Dims start,
+                                             const Dims count,
+                                             const bool constantShape)
+{
+    if (m_DebugMode)
+    {
+        if (VariableExists(name))
+        {
+            std::invalid_argument("ERROR: variable " + name +
+                                  " exists in IO object " + m_Name +
+                                  ", in call to DefineVariable\n");
+        }
+    }
+    const unsigned int size = m_Compound.size();
+    auto itVariableCompound = m_Compound.emplace(
+        size, VariableCompound(name, sizeof(T), shape, start, count,
+                               constantShape, m_DebugMode));
+    m_Variables.emplace(name, std::make_pair(GetType<T>(), size));
+    return itVariableCompound.first->second;
+}
+
+} // end namespace adios
+
+#endif /* ADIOS2_CORE_IO_INL_ */
diff --git a/source/adios2/core/IO.tcc b/source/adios2/core/IO.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..335e257ae50ae73f6e1275412ae456cfb5b37081
--- /dev/null
+++ b/source/adios2/core/IO.tcc
@@ -0,0 +1,157 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * IO.tcc template implementations with fix types and specializations
+ *
+ *  Created on: May 15, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_IO_TCC_
+#define ADIOS2_CORE_IO_TCC_
+
+#include "IO.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <iostream>
+#include <stdexcept> //std::invalid_argument
+/// \endcond
+
+#include "adios2/ADIOSMPI.h"
+#include "adios2/ADIOSMacros.h"
+
+namespace adios
+{
+
+template <class T>
+Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape,
+                                const Dims start, const Dims count,
+                                const bool constantShape)
+{
+    if (m_DebugMode)
+    {
+        if (VariableExists(name))
+        {
+            throw std::invalid_argument("ERROR: variable " + name +
+                                        " exists in IO object " + m_Name +
+                                        ", in call to DefineVariable\n");
+        }
+    }
+
+    auto &variableMap = GetVariableMap<T>();
+    const unsigned int size = variableMap.size();
+    auto itVariablePair =
+        variableMap.emplace(size, Variable<T>(name, shape, start, count,
+                                              constantShape, m_DebugMode));
+
+    m_Variables.emplace(name, std::make_pair(GetType<T>(), size));
+    return itVariablePair.first->second;
+}
+
+template <class T>
+Variable<T> &IO::GetVariable(const std::string &name)
+{
+    return GetVariableMap<T>().at(GetVariableIndex(name));
+}
+
+// PRIVATE
+template <>
+std::map<unsigned int, Variable<char>> &IO::GetVariableMap()
+{
+    return m_Char;
+}
+
+template <>
+std::map<unsigned int, Variable<unsigned char>> &IO::GetVariableMap()
+{
+    return m_UChar;
+}
+
+template <>
+std::map<unsigned int, Variable<short>> &IO::GetVariableMap()
+{
+    return m_Short;
+}
+
+template <>
+std::map<unsigned int, Variable<unsigned short>> &IO::GetVariableMap()
+{
+    return m_UShort;
+}
+
+template <>
+std::map<unsigned int, Variable<int>> &IO::GetVariableMap()
+{
+    return m_Int;
+}
+
+template <>
+std::map<unsigned int, Variable<unsigned int>> &IO::GetVariableMap()
+{
+    return m_UInt;
+}
+
+template <>
+std::map<unsigned int, Variable<long int>> &IO::GetVariableMap()
+{
+    return m_LInt;
+}
+
+template <>
+std::map<unsigned int, Variable<unsigned long int>> &IO::GetVariableMap()
+{
+    return m_ULInt;
+}
+
+template <>
+std::map<unsigned int, Variable<long long int>> &IO::GetVariableMap()
+{
+    return m_LLInt;
+}
+
+template <>
+std::map<unsigned int, Variable<unsigned long long int>> &IO::GetVariableMap()
+{
+    return m_ULLInt;
+}
+
+template <>
+std::map<unsigned int, Variable<float>> &IO::GetVariableMap()
+{
+    return m_Float;
+}
+
+template <>
+std::map<unsigned int, Variable<double>> &IO::GetVariableMap()
+{
+    return m_Double;
+}
+
+template <>
+std::map<unsigned int, Variable<long double>> &IO::GetVariableMap()
+{
+    return m_LDouble;
+}
+
+template <>
+std::map<unsigned int, Variable<cfloat>> &IO::GetVariableMap()
+{
+    return m_CFloat;
+}
+
+template <>
+std::map<unsigned int, Variable<cdouble>> &IO::GetVariableMap()
+{
+    return m_CDouble;
+}
+
+template <>
+std::map<unsigned int, Variable<cldouble>> &IO::GetVariableMap()
+{
+    return m_CLDouble;
+}
+
+} // end namespace adios
+
+#endif /* ADIOS2_CORE_IO_TCC_ */
diff --git a/source/adios2/core/IOChrono.h b/source/adios2/core/IOChrono.h
deleted file mode 100644
index 2f17b497fccf281fcd53e2aa7f8fa49b43c02aa4..0000000000000000000000000000000000000000
--- a/source/adios2/core/IOChrono.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * IOChrono.h
- *
- *  Created on: Mar 9, 2017
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_IOCHRONO_H_
-#define ADIOS2_CORE_IOCHRONO_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <vector>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Timer.h"
-
-namespace adios
-{
-namespace profiling
-{
-
-/**
- * Struct used to track
- */
-struct IOChrono
-{
-    ///< one timer for each process (open, write, buffering, etc.)
-    std::vector<Timer> Timers;
-
-    ///< tracks bytes for buffering
-    std::vector<unsigned long long int> TotalBytes;
-
-    ///< flag to determine if profiling is used
-    bool IsActive = false;
-};
-
-} // end namespace profiling
-} // end namespace adios
-
-#endif /* ADIOS2_CORE_IOCHRONO_H_ */
diff --git a/source/adios2/core/Method.cpp b/source/adios2/core/Method.cpp
deleted file mode 100644
index 083e19135c5fe100f4b0d02b309c106892d6bd74..0000000000000000000000000000000000000000
--- a/source/adios2/core/Method.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Method.cpp
- *
- *  Created on: Jan 6, 2017
- *      Author: wfg
- */
-
-#include "Method.h"
-
-#include <utility>
-
-#include "adios2/core/adiosFunctions.h"
-
-namespace adios
-{
-
-Method::Method(const std::string name, const bool debugMode)
-: m_Name{name}, m_DebugMode{debugMode}
-{
-}
-
-Method::~Method() {}
-
-bool Method::IsUserDefined()
-{
-    return false; // TODO(wfg): check if XML has the method defined
-}
-
-void Method::SetEngine(const std::string type) { m_Type = type; }
-void Method::SetIOMode(const IOMode mode) { m_IOMode = mode; };
-
-void Method::AllowThreads(const unsigned int nThreads)
-{
-    if (nThreads > 1)
-    {
-        m_nThreads = nThreads;
-    }
-    else
-    {
-        m_nThreads = 1;
-    }
-}
-
-// PRIVATE Functions
-void Method::AddTransportParameters(const std::string type,
-                                    const std::vector<std::string> &parameters)
-{
-    if (m_DebugMode == true)
-    {
-        if (type.empty() || type.find("=") != type.npos)
-        {
-            throw std::invalid_argument(
-                "ERROR: first argument in AddTransport must "
-                "be a single word for transport\n");
-        }
-    }
-
-    std::map<std::string, std::string> mapParameters =
-        BuildParametersMap(parameters, m_DebugMode);
-    if (m_DebugMode == true)
-    {
-        if (mapParameters.count("transport") == 1)
-        {
-            std::invalid_argument("ERROR: transport can't be redefined with "
-                                  "\"transport=type\", "
-                                  "type must be the first argument\n");
-        }
-    }
-
-    mapParameters["transport"] = type;
-    m_TransportParameters.push_back(mapParameters);
-}
-
-} // end namespace adios
diff --git a/source/adios2/core/Method.h b/source/adios2/core/Method.h
deleted file mode 100644
index 26ab2ffe0c62efc7cd1cadb1953797eba75123f5..0000000000000000000000000000000000000000
--- a/source/adios2/core/Method.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Method.h
- *
- *  Created on: Dec 16, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_METHOD_H_
-#define ADIOS2_CORE_METHOD_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <map>
-#include <string>
-#include <vector>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/ADIOSTypes.h"
-#include "adios2/core/adiosFunctions.h"
-
-namespace adios
-{
-
-typedef enum {
-    GLOBAL_READERS = 2,
-    ROUNDROBIN_READERS = 3,
-    FIFO_READERS = 4,
-    OPEN_ALL_STEPS = 5
-} ReadMultiplexPattern;
-
-typedef enum {
-    NOWAITFORSTREAM = 0,
-    WAITFORSTREAM = 1
-} StreamOpenMode; // default: wait for stream
-
-/**
- * Serves as metadata to define an engine
- */
-class Method
-{
-
-public:
-    const std::string m_Name;       ///< Method name (as defined in XML)
-    const bool m_DebugMode = false; ///< true: on, throws exceptions and do
-                                    /// additional checks, false: off, faster
-    /// unsafe
-    std::string m_Type; ///< Method's engine type
-    unsigned int m_nThreads = 1;
-
-    std::map<std::string, std::string> m_Parameters; ///< method parameters
-    std::vector<std::map<std::string, std::string>>
-        m_TransportParameters; ///< each is a separate Transport containing
-                               /// their
-                               /// own parameters
-
-    /**
-     * Constructor
-     * @param name is a label that can be used in the config file to set up the
-     * method at runtime
-     */
-    Method(const std::string name, const bool debugMode = false);
-
-    ~Method();
-
-    /** Check if the method was defined by the user in the config file.
-     * @return true if the method was user-defined, false otherwise when method
-     * is
-     * set with default parameters
-     */
-    bool IsUserDefined();
-
-    /**
-     * Define the engine type
-     * @param type must be a valid engine type
-     */
-    void SetEngine(const std::string type);
-
-    /**
-     * Set the IO mode (collective or independent)
-     * @param IO mode
-     */
-    void SetIOMode(const IOMode mode);
-
-    /**
-     * Set how many threads the engine can use for its operations (e.g. file io,
-     * compression, staging).
-     * If 1 is allowed, no extra threads will be created during the ADIOS calls
-     * for asynchronous operations.
-     * Note that some transports may require and use extra thread(s). See their
-     * documentation for their
-     * requirements. E.g. some staging transports always create an extra thread
-     * for communication.
-     * Set this parameter like you set it for OpenMP, i.e. count one thread for
-     * the main process that calls
-     * ADIOS functions.
-     * @param nThreads, minimum 1 is required
-     */
-    void AllowThreads(const unsigned int nThreads);
-
-    /**
-     * Sets parameters for the method in "parameter=value" format
-     * @param args list of parameters with format "parameter1=value1", ...,
-     * "parameterN=valueN"
-     */
-    template <class... Args>
-    void SetParameters(Args... args)
-    {
-        std::vector<std::string> parameters = {args...};
-        m_Parameters = BuildParametersMap(parameters, m_DebugMode);
-    }
-
-    /**
-     * Adds a transport and its parameters for the method
-     * @param type must be a supported transport type under /include/transport
-     * @param args list of parameters for a transport with format
-     * "parameter1=value1", ..., "parameterN=valueN"
-     */
-    template <class... Args>
-    void AddTransport(const std::string type, Args... args)
-    {
-        std::vector<std::string> parameters = {args...};
-        AddTransportParameters(type, parameters);
-    }
-
-    void SetReadMultiplexPattern(
-        const ReadMultiplexPattern
-            pattern); // How to split stream content among readers
-    void SetStreamOpenMode(const StreamOpenMode mode); // In Read mode, should
-                                                       // Open() wait for the
-                                                       // first step appear
-                                                       // (default)
-
-    void SetVerbose(const Verbose verbose = Verbose::WARN)
-    {
-        m_Verbose = verbose;
-    };
-    Verbose GetVerbose() { return m_Verbose; };
-
-private:
-    Verbose m_Verbose = Verbose::WARN;
-    adios::IOMode m_IOMode = adios::IOMode::INDEPENDENT;
-
-    void AddTransportParameters(const std::string type,
-                                const std::vector<std::string> &parameters);
-};
-
-} // end namespace adios
-
-#endif /* ADIOS2_CORE_METHOD_H_ */
diff --git a/source/adios2/core/Selection.cpp b/source/adios2/core/Selection.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1eb98987cdb6fb888915de0c7d73f019aaed3ad2
--- /dev/null
+++ b/source/adios2/core/Selection.cpp
@@ -0,0 +1,22 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Selection.cpp
+ *
+ *  Created on: May 19, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
+ */
+
+#include "Selection.h"
+
+namespace adios
+{
+
+Selection::Selection(const SelectionType type, const bool debugMode)
+: m_Type(type), m_DebugMode(debugMode)
+{
+}
+
+} // end namespace adios
diff --git a/source/adios2/core/Selection.h b/source/adios2/core/Selection.h
index b5e7e01280f8f4971c4391a78473e568193561c9..8ef27634d3f4f78d0606237ef0b7c1ae579f2e3a 100644
--- a/source/adios2/core/Selection.h
+++ b/source/adios2/core/Selection.h
@@ -1,6 +1,10 @@
 /*
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
+ *
+ *  Created on: May 17, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
  */
 
 /*
@@ -35,32 +39,28 @@
 #define ADIOS2_CORE_SELECTION_H_
 
 #include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSTypes.h"
 
 namespace adios
 {
-
-/* Type of selection */
-enum class SelectionType
-{
-    // Contiguous block of data defined by offsets and counts in each
-    // dimension
-    BoundingBox,
-
-    // List of individual points
-    Points,
-
-    // Selection of an individual block written by a writer process
-    WriteBlock,
-
-    // Let the method decide what to return
-    Auto
-};
-
+/** Base class for Selection (query) types */
 class Selection
 {
 public:
-    Selection(const SelectionType t) : m_Type(t){};
+    /** from derived class */
     const SelectionType m_Type;
+
+    /**
+     * Unique constructor
+     * @param type derived class type
+     */
+    Selection(const SelectionType type, const bool debugMode = false);
+
+    virtual ~Selection() = default;
+
+protected:
+    /** true: extra checks (recommended) */
+    const bool m_DebugMode;
 };
 
 } // namespace adios
diff --git a/source/adios2/core/SelectionBoundingBox.cpp b/source/adios2/core/SelectionBoundingBox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccb0ff709deefc514736eb2e915c22143e063e79
--- /dev/null
+++ b/source/adios2/core/SelectionBoundingBox.cpp
@@ -0,0 +1,60 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * SelectionBoundingBox.cpp
+ *
+ *  Created on: May 17, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
+ *
+ */
+
+#include "SelectionBoundingBox.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <stdexcept>
+/// \endcond
+
+#include "adios2/helper/adiosFunctions.h" //Uint64VectorToSizetVector
+
+namespace adios
+{
+
+SelectionBoundingBox::SelectionBoundingBox(const Dims start, const Dims count,
+                                           const bool debugMode)
+: Selection(SelectionType::BoundingBox, debugMode), m_Start(start),
+  m_Count(count)
+{
+    if (m_DebugMode)
+    {
+        CheckBoundingBox();
+    }
+}
+
+void SelectionBoundingBox::CheckBoundingBox() const
+{
+
+    auto lf_Throw = [](const std::string &message) {
+        throw std::invalid_argument(
+            "ERROR: " + message +
+            ", in call to SelectionBoundingBox constructor\n");
+    };
+
+    if (m_Start.size() != m_Count.size())
+    {
+        lf_Throw("start and count must have the same size");
+    }
+
+    if (m_Start.empty())
+    {
+        lf_Throw("start is empty");
+    }
+
+    if (m_Count.empty())
+    {
+        lf_Throw("count is empty");
+    }
+}
+
+} // end namespace adios
diff --git a/source/adios2/core/SelectionBoundingBox.h b/source/adios2/core/SelectionBoundingBox.h
index 6e8cdd1cc0547a0537f02499d745d7820f4cfdf9..280ec8df1105da8ec7d0f77ef79d615131457532 100644
--- a/source/adios2/core/SelectionBoundingBox.h
+++ b/source/adios2/core/SelectionBoundingBox.h
@@ -1,14 +1,20 @@
 /*
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
+ *
+ * SelectionBoundingBox.h
+ *
+ *  Created on: May 17, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_CORE_SELECTIONBOUNDINGBOX_H_
 #define ADIOS2_CORE_SELECTIONBOUNDINGBOX_H_
 
-#include <cstdint>
-
+/// \cond EXCLUDE_FROM_DOXYGEN
 #include <vector>
+/// \endcond
 
 #include "adios2/ADIOSConfig.h"
 #include "adios2/core/Selection.h"
@@ -16,23 +22,42 @@
 namespace adios
 {
 
-/** Boundingbox selection to read a subset of a non-scalar variable.
+/** Bounding box selection to read a subset of a non-scalar variable.
  *  @param start     array of offsets to start reading in each dimension
  *  @param count     number of data elements to read in each dimension
  */
 class SelectionBoundingBox : public Selection
 {
 public:
-    SelectionBoundingBox(const std::vector<std::uint64_t> start,
-                         const std::vector<std::uint64_t> count)
-    : Selection(SelectionType::BoundingBox), m_Start(start), m_Count(count)
-    {
-    }
-
-    std::vector<std::uint64_t> m_Start;
-    std::vector<std::uint64_t> m_Count;
+    /** Starting coodinates of bounding box */
+    Dims m_Start;
+    /** From start of bounding box */
+    Dims m_Count;
+
+    /**
+     * Constructor using uint64_t vectors
+     * @param start of bounding box
+     * @param count from start of bounding box
+     */
+    //    SelectionBoundingBox(const std::vector<uint64_t> start,
+    //                         const std::vector<uint64_t> count,
+    //                         const bool debugMode = false);
+
+    /**
+     * Constructor using size_t vectors
+     * @param start of bounding box
+     * @param count from start of bounding box
+     */
+    SelectionBoundingBox(const Dims start, const Dims count,
+                         const bool debugMode = false);
+
+    ~SelectionBoundingBox() = default;
+
+private:
+    /** Check in debug mode to make sure bounding box is valid */
+    void CheckBoundingBox() const;
 };
 
-} // namespace adios
+} // end namespace adios
 
 #endif /* ADIOS2_CORE_SELECTIONBOUNDINGBOX_H_ */
diff --git a/source/adios2/core/SelectionPoints.cpp b/source/adios2/core/SelectionPoints.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b86f134f65698572857760d089287954047c158a
--- /dev/null
+++ b/source/adios2/core/SelectionPoints.cpp
@@ -0,0 +1,31 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * SelectionPoints.cpp
+ *
+ *  Created on: May 17, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
+ */
+
+#include "SelectionPoints.h"
+
+namespace adios
+{
+
+SelectionPoints::SelectionPoints(size_t dimensionsSize,
+                                 std::vector<uint64_t> &points)
+: Selection(SelectionType::Points), m_DimensionsSize(dimensionsSize),
+  m_PointsVec(&points), m_PointsSize(points.size())
+{
+}
+
+SelectionPoints::SelectionPoints(size_t dimensionsSize, size_t pointsSize,
+                                 uint64_t *points)
+: Selection(SelectionType::Points), m_DimensionsSize(dimensionsSize),
+  m_PointsSize(pointsSize), m_PointsPointer(points)
+{
+}
+
+} // end namespace adios
diff --git a/source/adios2/core/SelectionPoints.h b/source/adios2/core/SelectionPoints.h
index 75dfec84d9054766971b70120d3fdb83afa87fa4..5338e53f20110940593fa83bed5d363bd1ebdb9f 100644
--- a/source/adios2/core/SelectionPoints.h
+++ b/source/adios2/core/SelectionPoints.h
@@ -1,18 +1,23 @@
 /*
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
+ *
+ * SelectionPoints.h
+ *
+ *  Created on: May 17, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_CORE_SELECTIONPOINTS_H_
 #define ADIOS2_CORE_SELECTIONPOINTS_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
-#include <cstdint>
-/// \endcond
-
 #include <vector>
+/// \endcond
 
 #include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSTypes.h"
 #include "adios2/core/Selection.h"
 
 namespace adios
@@ -28,30 +33,31 @@ namespace adios
 class SelectionPoints : public Selection
 {
 public:
-    SelectionPoints(std::size_t ndim, std::size_t npoints,
-                    std::vector<std::uint64_t> &points)
-    : Selection(SelectionType::Points), m_Ndim(ndim), m_Npoints(npoints),
-      m_Points(points)
-    {
-    }
-
-    ///< C-style constructor to be used in the C-to-C++ wrapper
-    SelectionPoints(std::size_t ndim, std::size_t npoints, uint64_t *points)
-    : Selection(SelectionType::Points), m_Ndim(ndim), m_Npoints(npoints),
-      m_Points(std::vector<std::uint64_t>()), m_PointsC(points)
-    {
-    }
+    /** number of dimensions from constructor */
+    const size_t m_DimensionsSize;
 
-    virtual ~SelectionPoints() = default;
+    /** reference to points in constructor, must use a pointer as nullptr is
+     * valid if an array is passed in the constructor instead */
+    std::vector<uint64_t> *m_PointsVec = nullptr;
 
-    const std::size_t m_Ndim;
-    const std::size_t m_Npoints;
-    std::vector<std::uint64_t> &m_Points;
-    ///< C-to-C++ wrapper needs a pointer to hold the points created by the C
-    /// application
-    std::uint64_t *m_PointsC = nullptr;
+    /** pointer based applications needed size*/
+    const size_t m_PointsSize;
+    /** pointer based applications needed array*/
+    uint64_t *m_PointsPointer = nullptr;
+
+    /**
+     * Constructor that takes a vector<uint64_t> for points
+     * @param dimensionsSize
+     * @param pointsSize
+     * @param points
+     */
+    SelectionPoints(size_t dimensionsSize, std::vector<uint64_t> &points);
+
+    SelectionPoints(size_t dimensionsSize, size_t pointsSize, uint64_t *points);
+
+    virtual ~SelectionPoints() = default;
 };
 
-} // namespace adios
+} // end namespace adios
 
 #endif /* ADIOS2_CORE_SELECTIONPOINTS_H_ */
diff --git a/source/adios2/core/Support.cpp b/source/adios2/core/Support.cpp
deleted file mode 100644
index c1db02342d3e45a618a2b7638deb737de3ff289a..0000000000000000000000000000000000000000
--- a/source/adios2/core/Support.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Support.cpp
- *
- *  Created on: Oct 18, 2016
- *      Author: wfg
- */
-
-#include "Support.h"
-
-#include "adios2/core/adiosTemplates.h"
-
-namespace adios
-{
-
-const std::string Support::Version{"2.00"};
-
-const std::set<std::string> Support::HostLanguages{{"C++", "C", "Fortran"}};
-
-const std::set<std::string> Support::Transports{
-    {"NULL", "POSIX", "FStream", "MdtmMan"}};
-// TODO(chuckatkins): Add transports MPI, MPI_LUSTRE, MPI_AGGREGATE,
-//                    DATASPACES, DIMES, FLEXPATH, PHDF5, NC4, ICEE
-
-const std::set<std::string> Support::Transforms{
-    {"none", "identity", "bzip2", "isobar", "szip", "zlib"}};
-
-const std::map<std::string, std::set<std::string>> Support::Datatypes{
-    {"C++", {"char",
-             "std::string",
-             "string",
-             "unsigned char",
-             "short",
-             "unsigned short",
-             "int",
-             "integer",
-             "unsigned int",
-             "long int",
-             "long",
-             "unsigned long int",
-             "unsigned long",
-             "long long int",
-             "long long",
-             "unsigned long long int",
-             "unsigned long long",
-             "float",
-             "float complex",
-             "double",
-             "long double",
-             "double complex",
-             "std::complex<double>",
-             "complex<double>"}},
-    {"C",
-     {"char", "unsigned char", "short", "unsigned short", "int", "integer"
-                                                                 "unsigned int",
-      "unsigned integer", "long int", "long", "long integer",
-      "unsigned long int", "unsigned long", "unsigned long integer",
-      "long long int", "long long", "long long integer",
-      "unsigned long long int", "unsigned long long",
-      "unsigned long long integer", "float", "float complex"
-                                             "double",
-      "long double", "double complex"}},
-    {"Fortran",
-     {"character", "integer*2", "integer", "real*2", "real", "real*4",
-      "double precision", "real*8", "complex", "double complex"}}};
-
-const std::map<std::string, std::set<std::string>> Support::DatatypesAliases{
-    {GetType<char>(), {GetType<char>(), "character"}},
-    {GetType<unsigned char>(),
-     {GetType<unsigned char>(), "unsigned character"}},
-    {GetType<short>(), {GetType<short>(), "integer*2"}},
-    {GetType<unsigned short>(), {GetType<unsigned short>()}},
-    {GetType<int>(), {GetType<int>(), "integer"}},
-    {GetType<unsigned int>(), {GetType<unsigned int>(), "unsigned integer"}},
-    {GetType<long int>(), {GetType<long int>(), "long", "long integer"}},
-    {GetType<unsigned long int>(),
-     {GetType<unsigned long int>(), "unsigned long", "unsigned long integer"}},
-    {GetType<long long int>(),
-     {GetType<long long int>(), "long long", "long long integer"}},
-    {GetType<unsigned long long int>(),
-     {GetType<unsigned long long int>(), "unsigned long long",
-      "unsigned long long integer"}},
-    {GetType<float>(), {GetType<float>(), "real", "real*4"}},
-    {GetType<double>(), {GetType<double>(), "double precision", "real*8"}},
-    {GetType<long double>(),
-     {GetType<long double>(), "long double precision", "real*16"}}};
-
-const std::set<std::string> Support::FileTransports{
-    {"POSIX", "File", "FStream", "MPIFile"}};
-
-} // end namespace adios
diff --git a/source/adios2/core/Support.h b/source/adios2/core/Support.h
deleted file mode 100644
index c836724b168a73c51063cd5177d90b4a943a2495..0000000000000000000000000000000000000000
--- a/source/adios2/core/Support.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Support.h
- *
- *  Created on: Oct 10, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_SUPPORT_H_
-#define ADIOS2_CORE_SUPPORT_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <map>
-#include <set>
-#include <string>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-
-namespace adios
-{
-
-struct Support
-{
-    ///< current ADIOS version
-    static const std::string Version;
-
-    ///< supported languages: C, C++, Fortran, Python, Java
-    static const std::set<std::string> HostLanguages;
-
-    static const std::set<std::string> Numbers;
-
-    ///< supported transport methods
-    static const std::set<std::string> Transports;
-
-    ///< supported data transform methods
-    static const std::set<std::string> Transforms;
-
-    ///< supported data types, key: host language, value: all supported types
-    static const std::map<std::string, std::set<std::string>> Datatypes;
-
-    ///< all supported int aliases, key: C++ type (e.g. int), value: aliases to
-    /// type in key (e.g. int, integer)
-    static const std::map<std::string, std::set<std::string>> DatatypesAliases;
-
-    ///< file I/O transports
-    static const std::set<std::string> FileTransports;
-
-    enum class Resolutions
-    {
-        mus,
-        ms,
-        s,
-        m,
-        h
-    };
-};
-
-} // end namespace adios
-
-#endif /* ADIOS2_CORE_SUPPORT_H_ */
diff --git a/source/adios2/core/Timer.cpp b/source/adios2/core/Timer.cpp
deleted file mode 100644
index 2ae983fe859962158d3fd00faf6861d5ee4db86f..0000000000000000000000000000000000000000
--- a/source/adios2/core/Timer.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Timer.cpp
- *
- *  Created on: Apr 4, 2017
- *      Author: wfg
- */
-
-#include "Timer.h"
-
-namespace adios
-{
-namespace profiling
-{
-
-Timer::Timer(const std::string process, const Support::Resolutions resolution,
-             const bool debug)
-: m_Process{process}, m_Resolution{resolution}, m_DebugMode{debug}
-{
-}
-
-void Timer::SetInitialTime()
-{
-    m_InitialTime = std::chrono::high_resolution_clock::now();
-    m_InitialTimeSet = true;
-}
-
-void Timer::SetTime()
-{
-    m_ElapsedTime = std::chrono::high_resolution_clock::now();
-    m_ProcessTime += GetCurrentTime();
-}
-
-std::string Timer::GetUnits() const
-{
-    std::string units;
-    if (m_Resolution == Support::Resolutions::mus)
-        units = "mus";
-    else if (m_Resolution == Support::Resolutions::ms)
-        units = "ms";
-    else if (m_Resolution == Support::Resolutions::s)
-        units = "s";
-    else if (m_Resolution == Support::Resolutions::m)
-        units = "m";
-    else if (m_Resolution == Support::Resolutions::h)
-        units = "h";
-    return units;
-}
-
-// PRIVATE
-
-long long int Timer::GetCurrentTime()
-{
-    if (m_DebugMode == true)
-    {
-        if (m_InitialTimeSet == false)
-            throw std::invalid_argument("ERROR: SetInitialTime() in process " +
-                                        m_Process + " not called\n");
-    }
-
-    if (m_Resolution == Support::Resolutions::mus)
-    {
-        return std::chrono::duration_cast<std::chrono::microseconds>(
-                   m_ElapsedTime - m_InitialTime)
-            .count();
-    }
-    else if (m_Resolution == Support::Resolutions::ms)
-    {
-        return std::chrono::duration_cast<std::chrono::milliseconds>(
-                   m_ElapsedTime - m_InitialTime)
-            .count();
-    }
-    else if (m_Resolution == Support::Resolutions::s)
-    {
-        return std::chrono::duration_cast<std::chrono::seconds>(m_ElapsedTime -
-                                                                m_InitialTime)
-            .count();
-    }
-    else if (m_Resolution == Support::Resolutions::m)
-    {
-        return std::chrono::duration_cast<std::chrono::minutes>(m_ElapsedTime -
-                                                                m_InitialTime)
-            .count();
-    }
-    else if (m_Resolution == Support::Resolutions::h)
-    {
-        return std::chrono::duration_cast<std::chrono::hours>(m_ElapsedTime -
-                                                              m_InitialTime)
-            .count();
-    }
-
-    return -1; // failure
-}
-
-} // end namespace
-} // end namespace
diff --git a/source/adios2/core/Timer.h b/source/adios2/core/Timer.h
deleted file mode 100644
index 59796aedcb3744babcbd0fdb738d56ca29b0c47f..0000000000000000000000000000000000000000
--- a/source/adios2/core/Timer.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Timer.h
- *
- *  Created on: Apr 4, 2017
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_TIMER_H_
-#define ADIOS2_CORE_TIMER_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <chrono>
-#include <string>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Support.h"
-
-namespace adios
-{
-namespace profiling
-{
-
-class Timer
-{
-
-public:
-    const std::string m_Process;
-    unsigned long long int m_ProcessTime = 0;
-
-    /**
-     * Timer object constructor using std::chrono class
-     * @param process name of process to be measured
-     * @param resolution time resolution (mus, ms, s, etc.) from Resolutions in
-     * core/Support.h
-     * @param debugMode true: additional checks and exceptions, false: no checks
-     */
-    Timer(const std::string process, const Support::Resolutions resolution,
-          const bool debugMode = false);
-
-    ~Timer() = default;
-
-    ///< set time to start counting for a process
-    void SetInitialTime();
-
-    ///< sets time to measure, it will add to overall process time
-    void SetTime();
-
-    std::string GetUnits() const;
-
-private:
-    const Support::Resolutions m_Resolution;
-    const bool m_DebugMode = false;
-    std::chrono::time_point<std::chrono::high_resolution_clock> m_InitialTime;
-    std::chrono::time_point<std::chrono::high_resolution_clock> m_ElapsedTime;
-    bool m_InitialTimeSet = false;
-    long long int GetCurrentTime(); ///< called by SetTime
-};
-
-} // end namespace profiling
-} // end namespace adios
-
-#endif /* ADIOS2_CORE_TIMER_H_ */
diff --git a/source/adios2/core/Transform.cpp b/source/adios2/core/Transform.cpp
index ac75b66adf3470058fe0bc5487d0b7be544c0b51..470215622cc6220cfc72aac35f1665c3664f098a 100644
--- a/source/adios2/core/Transform.cpp
+++ b/source/adios2/core/Transform.cpp
@@ -5,17 +5,15 @@
  * Transform.cpp
  *
  *  Created on: Dec 5, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "Transform.h"
 
-#include <utility>
-
 namespace adios
 {
 
-Transform::Transform(std::string method) : m_Method(std::move(method)) {}
+Transform::Transform(const std::string method) : m_Method(method) {}
 
 void Transform::Compress(const std::vector<char> & /*bufferIn*/,
                          std::vector<char> & /*bufferOut*/)
diff --git a/source/adios2/core/Transform.h b/source/adios2/core/Transform.h
index 8073ba4002e4b0412b20b0092b9b4d98adb65bbe..cc147a11467e23f4a3fc5b11d7afd9bf9f90d224 100644
--- a/source/adios2/core/Transform.h
+++ b/source/adios2/core/Transform.h
@@ -2,10 +2,10 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * Transform.h
+ * Transform.h : Base class for all transforms under adios2/transform
  *
  *  Created on: Oct 17, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_CORE_TRANSFORM_H_
@@ -21,21 +21,19 @@
 namespace adios
 {
 
-/**
- * Parent class that defines data variable transformations. Used as a member of
- * CVariable
- */
+/** Base class that defines data variable transformations */
 class Transform
 {
 
 public:
+    /** From derived class to identify the transform */
     const std::string m_Method;
 
     /**
      * Initialize parent method
      * @param method zlib, bzip2, szip
      */
-    Transform(std::string method);
+    Transform(const std::string method);
 
     virtual ~Transform() = default;
 
diff --git a/source/adios2/core/Transport.cpp b/source/adios2/core/Transport.cpp
deleted file mode 100644
index 6b0e0772d584b52ae4f3a4fa3b4757ebb235ab3b..0000000000000000000000000000000000000000
--- a/source/adios2/core/Transport.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Transport.cpp
- *
- *  Created on: Dec 5, 2016
- *      Author: wfg
- */
-
-#include "Transport.h"
-
-#include <utility>
-
-#include "adios2/ADIOSMPI.h"
-
-namespace adios
-{
-
-Transport::Transport(const std::string type, MPI_Comm mpiComm,
-                     const bool debugMode)
-: m_Type(type), m_MPIComm(mpiComm), m_DebugMode(debugMode)
-{
-    MPI_Comm_rank(m_MPIComm, &m_RankMPI);
-    MPI_Comm_size(m_MPIComm, &m_SizeMPI);
-}
-
-void Transport::SetBuffer(char * /*buffer*/, size_t /*size*/) {}
-
-void Transport::Flush() {}
-
-void Transport::Close() {}
-
-void Transport::InitProfiler(const std::string accessMode,
-                             const Support::Resolutions resolution)
-{
-    m_Profiler.Timers.emplace_back("open", Support::Resolutions::mus);
-
-    if (accessMode == "w" || accessMode == "write")
-        m_Profiler.Timers.emplace_back("write", resolution);
-
-    else if (accessMode == "a" || accessMode == "append")
-        m_Profiler.Timers.emplace_back("append", resolution);
-
-    else if (accessMode == "r" || accessMode == "read")
-        m_Profiler.Timers.emplace_back("read", resolution);
-
-    m_Profiler.Timers.emplace_back("close", Support::Resolutions::mus);
-
-    m_Profiler.TotalBytes.push_back(0);
-    m_Profiler.IsActive = true;
-}
-
-} // end namespace adios
diff --git a/source/adios2/core/Transport.h b/source/adios2/core/Transport.h
deleted file mode 100644
index 1a5cf845de38e67bafe1250c53cd0813a103b164..0000000000000000000000000000000000000000
--- a/source/adios2/core/Transport.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * Transport.h
- *
- *  Created on: Oct 6, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_TRANSPORT_H_
-#define ADIOS2_CORE_TRANSPORT_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <string>
-#include <vector>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/ADIOSMPICommOnly.h"
-#include "adios2/core/IOChrono.h"
-
-namespace adios
-{
-
-class Transport
-{
-
-public:
-    const std::string m_Type; ///< transport type from derived class
-    std::string m_Name;       ///< from Open
-    std::string m_AccessMode; ///< from Open
-    bool m_IsOpen = false;
-
-    MPI_Comm m_MPIComm;
-
-    int m_RankMPI = 0;              ///< current MPI rank process
-    int m_SizeMPI = 1;              ///< current MPI processes size
-    profiling::IOChrono m_Profiler; ///< profiles Open, Write/Read, Close
-
-    /**
-     * Base constructor that all derived classes pass
-     * @param
-     * @param mpiComm passed to m_MPIComm
-     * @param debugMode passed to m_DebugMode
-     */
-    Transport(const std::string type, MPI_Comm mpiComm, const bool debugMode);
-
-    virtual ~Transport() = default;
-
-    /**
-     * Open Output file accesing a mode
-     * @param name name of stream or file
-     * @param accessMode r or read, w or write, a or append
-     */
-    virtual void Open(const std::string &name,
-                      const std::string accessMode) = 0;
-
-    /**
-     * Set buffer and size for a particular transport
-     * @param buffer raw data buffer
-     * @param size raw data buffer size
-     */
-    virtual void SetBuffer(char *buffer, std::size_t size);
-
-    /**
-     * Write function for a transport
-     * @param buffer pointer to buffer to be written
-     * @param size size of buffer to be written
-     */
-    virtual void Write(const char *buffer, std::size_t size) = 0;
-
-    virtual void
-    Flush(); ///< flushes current contents to physical medium without
-             /// closing the transport
-
-    virtual void Close(); ///< closes current transport and flushes everything,
-                          /// transport becomes unreachable
-
-    /**
-     * Inits the profiler
-     * @param accessMode
-     * @param resolution
-     */
-    virtual void InitProfiler(const std::string accessMode,
-                              const Support::Resolutions resolution);
-
-protected:
-    const bool m_DebugMode = false; ///< true: turn on exceptions
-};
-
-} // end namespace adios
-
-#endif /* ADIOS2_CORE_TRANSPORT_H_ */
diff --git a/source/adios2/core/Variable.h b/source/adios2/core/Variable.h
index 0773aff308bfc011b1f605317d46b7c4739ab95d..9b859f3fabf94a8a907e20586f1402df638ffa50 100644
--- a/source/adios2/core/Variable.h
+++ b/source/adios2/core/Variable.h
@@ -2,10 +2,10 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * Variable.h
+ * Variable.h : template class for self-describing primitive variables
  *
  *  Created on: Oct 6, 2016
- *      Author: wfg
+ *      Author: William F Godoy
  */
 
 #ifndef ADIOS2_CORE_VARIABLE_H_
@@ -18,101 +18,50 @@
 #include <vector>
 /// \endcond
 
+#include "VariableBase.h"
 #include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSMacros.h"
 #include "adios2/core/Transform.h"
-#include "adios2/core/VariableBase.h"
 
 namespace adios
 {
 
-struct TransformData
-{
-    Transform &Operation; ///< from ADIOS.DefineTransform
-    std::map<std::string, std::string> Parameters; ///< transforms parameters
-    std::vector<std::size_t> Size; ///< vector that carries the sizes after a
-                                   /// transformation is applied
-};
-
 /**
- * @param Base (parent) class for template derived (child) class CVariable.
- * Required to put CVariable objects in STL containers.
+ * @param Base (parent) class for template derived (child) class Variable.
  */
 template <class T>
 class Variable : public VariableBase
 {
 
 public:
-    const T *m_AppValues = nullptr; ///< pointer to values passed from user in
-    /// ADIOS Write
+    /** pointer to values passed from application in Engine Write*/
+    const T *m_AppValues = nullptr;
 
-    ///< vector of values as a possible result of ADIOS Read or InquireVariable
-    std::vector<T> m_Data;
+    /** reference to non-const data, mostly used for reading */
+    T *m_AppPointer = nullptr;
 
-    std::vector<TransformData>
-        m_Transforms; ///< associated transforms, sequence
-    /// determines application order, e.g.
-    /// first Transforms[0] then
-    /// Transforms[1]. Pointer used as
-    /// reference (no memory management).
+    std::vector<T> m_Data;
 
+    /**
+     * Unique constructor
+     * @param name
+     * @param shape
+     * @param start
+     * @param count
+     * @param constantShape
+     * @param debugMode
+     */
     Variable<T>(const std::string &name, const Dims shape, const Dims start,
                 const Dims count, const bool constantShape,
-                const bool debugMode)
-    : VariableBase(name, GetType<T>(), sizeof(T), shape, start, count,
-                   constantShape, debugMode)
-    {
-    }
+                const bool debugMode);
 
-    template <class... Args>
-    void AddTransform(Transform &transform, Args... args)
-    {
-        std::vector<std::string> parameters = {args...};
-        m_Transforms.emplace_back(
-            transform,
-            BuildParametersMap(parameters, m_DebugMode)); // need to check
-    }
+    virtual ~Variable<T>() = default;
 
-    /** Return the global dimensions of the variable
-     *  @return vector of std::size_t values
-     */
-    std::vector<std::size_t> GetGlobalDimensions();
-
-    void Monitor(std::ostream &logInfo) const noexcept
-    {
-        logInfo << "Variable: " << m_Name << "\n";
-        logInfo << "Type: " << m_Type << "\n";
-        logInfo << "Size: " << TotalSize() << " elements\n";
-        logInfo << "Payload: " << PayLoadSize() << " bytes\n";
-
-        if (m_AppValues != nullptr)
-        {
-            logInfo << "Values (first 10 or max_size): \n";
-            std::size_t size = TotalSize();
-            if (size > 10)
-                size = 10;
-
-            if (m_Type.find("complex") != m_Type.npos) // it's complex
-            {
-                for (unsigned int i = 0; i < size; ++i)
-                {
-                    logInfo << "( " << std::real(m_AppValues[i]) << " , "
-                            << std::imag(m_AppValues[i]) << " )  ";
-                }
-            }
-            else
-            {
-                for (unsigned int i = 0; i < size; ++i)
-                {
-                    logInfo << m_AppValues[i] << " ";
-                }
-            }
-
-            logInfo << " ...";
-        }
-        logInfo << "\n";
-    }
+    void ApplyTransforms() final;
 };
 
-} // end namespace
+} // end namespace adios
+
+#include "Variable.inl"
 
 #endif /* ADIOS2_CORE_VARIABLE_H_ */
diff --git a/source/adios2/core/Variable.inl b/source/adios2/core/Variable.inl
new file mode 100644
index 0000000000000000000000000000000000000000..4abb6e3c45592bf362aec74f2786619d94d04eb8
--- /dev/null
+++ b/source/adios2/core/Variable.inl
@@ -0,0 +1,40 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Variable.inl
+ *
+ *  Created on: May 1, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_VARIABLE_INL_
+#define ADIOS2_CORE_VARIABLE_INL_
+#ifndef ADIOS2_CORE_VARIABLE_H_
+#error "Inline file should only be included from it's header, never on it's own"
+#endif
+
+#include "Variable.h"
+
+#include "adios2/helper/adiosFunctions.h" //GetType
+
+namespace adios
+{
+
+template <class T>
+Variable<T>::Variable(const std::string &name, const Dims shape,
+                      const Dims start, const Dims count,
+                      const bool constantShape, const bool debugMode)
+: VariableBase(name, GetType<T>(), sizeof(T), shape, start, count,
+               constantShape, debugMode)
+{
+}
+
+template <class T>
+void Variable<T>::ApplyTransforms()
+{
+}
+
+} // end namespace adios
+
+#endif /* ADIOS2_CORE_VARIABLE_INL_ */
diff --git a/source/adios2/core/VariableBase.cpp b/source/adios2/core/VariableBase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..db50a21db91c2ab96911c5cc74a4b76d7888da84
--- /dev/null
+++ b/source/adios2/core/VariableBase.cpp
@@ -0,0 +1,230 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * VariableBase.cpp
+ *
+ *  Created on: May 11, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "VariableBase.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <algorithm> //std::count
+#include <stdexcept> //std::invalid_argument
+/// \endcond
+
+namespace adios
+{
+
+VariableBase::VariableBase(const std::string &name, const std::string type,
+                           const size_t elementSize, const Dims shape,
+                           const Dims start, const Dims count,
+                           const bool constantShape, const bool debugMode)
+: m_Name(name), m_Type(type), m_ElementSize(elementSize), m_Shape(shape),
+  m_Start(start), m_Count(count), m_ConstantShape(constantShape),
+  m_DebugMode(debugMode)
+{
+    InitShapeType();
+}
+
+size_t VariableBase::PayLoadSize() const noexcept
+{
+    return GetTotalSize(m_Count) * m_ElementSize;
+}
+
+size_t VariableBase::TotalSize() const noexcept
+{
+    return GetTotalSize(m_Count);
+}
+
+void VariableBase::SetSelection(const Dims start, const Dims count)
+{
+    if (m_DebugMode)
+    {
+        if (m_SingleValue)
+        {
+            throw std::invalid_argument(
+                "ERROR: selection is not valid for single value variable " +
+                m_Name + ", in call to SetSelection\n");
+        }
+
+        if (m_ConstantShape)
+        {
+            throw std::invalid_argument(
+                "ERROR: selection is not valid for constant shape variable " +
+                m_Name + ", in call to SetSelection\n");
+        }
+
+        if (m_ShapeID == ShapeID::GlobalArray &&
+            (m_Shape.size() != m_Count.size() ||
+             m_Shape.size() != m_Start.size()))
+        {
+            throw std::invalid_argument("ERROR: count and start must be the "
+                                        "same size as shape for variable " +
+                                        m_Name + ", in call to SetSelection\n");
+        }
+
+        if (m_ShapeID == ShapeID::LocalArray && !start.empty())
+        {
+            throw std::invalid_argument("ERROR: start argument must be empty "
+                                        "for local array variable " +
+                                        m_Name + ", in call to SetSelection\n");
+        }
+
+        if (m_ShapeID == ShapeID::JoinedArray && !start.empty())
+        {
+            throw std::invalid_argument("ERROR: start argument must be empty "
+                                        "for joined array variable " +
+                                        m_Name + ", in call to SetSelection\n");
+        }
+    }
+
+    m_Count = count;
+    m_Start = start;
+}
+
+void VariableBase::SetSelection(const SelectionBoundingBox &selection)
+{
+    SetSelection(selection.m_Start, selection.m_Count);
+}
+
+void VariableBase::SetMemorySelection(const SelectionBoundingBox &selection)
+{
+    if (m_DebugMode)
+    {
+        if (m_SingleValue)
+        {
+            throw std::invalid_argument("ERROR: memory selection is not valid "
+                                        "for single value variable " +
+                                        m_Name +
+                                        ", in call to SetMemorySelection\n");
+        }
+        if (m_Shape.size() != selection.m_Count.size() ||
+            m_Shape.size() != selection.m_Start.size())
+        {
+            throw std::invalid_argument(
+                "ERROR: selection argument m_Count and m_Start sizes must be "
+                "the "
+                "same as variable " +
+                m_Name + " m_Shape, in call to SetMemorySelction\n");
+        }
+    }
+
+    m_MemoryCount = selection.m_Count;
+    m_MemoryStart = selection.m_Start;
+}
+
+void VariableBase::SetStepSelection(const unsigned int startStep,
+                                    const unsigned int countStep)
+{
+    m_ReadFromStep = startStep;
+    m_ReadNSteps = countStep;
+}
+
+// transforms related functions
+void VariableBase::ClearTransforms() { m_TransformsInfo.clear(); }
+
+// PRIVATE
+void VariableBase::InitShapeType()
+{
+    if (!m_Shape.empty() && m_Start.empty() && m_Count.empty())
+    {
+        if (m_DebugMode)
+        {
+            if (m_ConstantShape)
+            {
+                throw std::invalid_argument(
+                    "ERROR: isConstantShape (true) argument is invalid "
+                    "with empty start and count "
+                    "arguments\n");
+            }
+        }
+
+        m_ShapeID = ShapeID::GlobalArray;
+    }
+    else if (!m_Shape.empty() && m_Shape.size() == m_Start.size() &&
+             m_Shape.size() == m_Count.size())
+    {
+        if (m_DebugMode)
+        {
+            auto lf_LargerThanError = [&](const unsigned int i,
+                                          const std::string dims1,
+                                          const std::string dims2) {
+
+                const std::string iString(std::to_string(i));
+                throw std::invalid_argument(
+                    "ERROR: " + dims1 + "[" + iString + "] > " + dims2 + "[" +
+                    iString + "], in DefineVariable " + m_Name + "\n");
+            };
+
+            for (unsigned int i = 0; i < m_Shape.size(); ++i)
+            {
+                if (m_Count[i] > m_Shape[i])
+                {
+                    lf_LargerThanError(i, "count", "shape");
+                }
+                if (m_Start[i] > m_Shape[i])
+                {
+                    lf_LargerThanError(i, "start", "shape");
+                }
+            }
+        }
+
+        m_ShapeID = ShapeID::GlobalArray;
+    }
+    else if (m_Shape.empty() && m_Start.empty() && m_Count.empty())
+    {
+        m_ShapeID = ShapeID::GlobalValue;
+        m_SingleValue = true;
+    }
+    else if (m_Shape.empty() && m_Start.empty() && !m_Count.empty())
+    {
+        m_ShapeID = ShapeID::LocalArray;
+    }
+    else if (m_Shape.size() == 1 && m_Shape.front() == LocalValueDim)
+    {
+        m_ShapeID = ShapeID::LocalValue;
+        m_SingleValue = true;
+    }
+    else if (!m_Shape.empty() &&
+             std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) == 1)
+    {
+        m_ShapeID = ShapeID::JoinedArray;
+    }
+    else if (!m_Shape.empty() &&
+             std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) > 1)
+    {
+        throw std::invalid_argument("ERROR: variable can't have more than one "
+                                    "JoinedDim in shape argument, in call to "
+                                    "DefineVariable " +
+                                    m_Name + "\n");
+    }
+    else
+    {
+        throw std::invalid_argument("ERROR: the "
+                                    "combination of shape, start and count "
+                                    "arguments is inconsistent, in call to "
+                                    "DefineVariable " +
+                                    m_Name + "\n");
+    }
+}
+
+void VariableBase::CheckDims(const std::string hint) const
+{
+    if (m_ShapeID == ShapeID::GlobalArray)
+    {
+        if (m_Start.empty() || m_Count.empty())
+        {
+            throw std::invalid_argument(
+                "ERROR: GlobalArray variable " + m_Name +
+                " start and count dimensions must be defined by either "
+                "DefineVariable or a Selection " +
+                hint + "\n");
+        }
+    }
+    // TODO need to think more exceptions here
+}
+
+} // end namespace adios
diff --git a/source/adios2/core/VariableBase.h b/source/adios2/core/VariableBase.h
index 2ba2d8432f52fee6c39540d52da3313ec2f9fdc6..7c17a1687623d7fa5ea3e5263557f1b5e3cffcfd 100644
--- a/source/adios2/core/VariableBase.h
+++ b/source/adios2/core/VariableBase.h
@@ -2,18 +2,17 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * VariableBase.h
+ * VariableBase.h Base class for Variable and VariableCompound types. Contains
+ * common elements.
  *
  *  Created on: Feb 20, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_CORE_VARIABLEBASE_H_
 #define ADIOS2_CORE_VARIABLEBASE_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
-#include <exception>
-#include <iterator>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -22,222 +21,132 @@
 #include "adios2/ADIOSConfig.h"
 #include "adios2/ADIOSTypes.h"
 #include "adios2/core/SelectionBoundingBox.h"
-#include "adios2/core/adiosFunctions.h"
-#include "adios2/core/adiosTemplates.h"
+#include "adios2/core/Transform.h"
+#include "adios2/helper/adiosFunctions.h"
 
 namespace adios
 {
-
-using Dims = std::vector<std::size_t>;
-
+/** Base class for Variable<T> (primitives) and VariableCompound classes */
 class VariableBase
 {
 
 public:
-    const std::string m_Name;   ///< variable name
-    const std::string m_Type;   ///< variable type
-    const bool m_ConstantShape; ///< dimensions and offsets cannot change after
-                                /// declaration
+    /** unique identifier inside Method that creates a Variable */
+    const std::string m_Name;
 
-    /**
-     * Variable -> sizeof(T),
-     * VariableCompound -> from constructor sizeof(struct)
-     */
-    const std::size_t m_ElementSize;
+    /** primitive from <T> or compound from struct */
+    const std::string m_Type;
 
-    Dims m_Shape;            ///< total dimensions across MPI
-    Dims m_Start;            ///< offsets of local writer in global shape
-    Dims m_Count;            ///< dimensions of the local writer in global shape
-    Dims m_MemoryDimensions; ///< array of memory dimensions
-    Dims m_MemoryOffsets;    ///< array of memory offsets
+    /** Variable -> sizeof(T),
+     *  VariableCompound -> from constructor sizeof(struct) */
+    const size_t m_ElementSize;
 
-    VarClass m_VarClass;
-    bool m_IsScalar = false; /// Global value or Loval value
-    const bool m_IsDimension = false;
-    const bool m_DebugMode = false;
+    ShapeID m_ShapeID;                  ///< see shape types in ADIOSTypes.h
+    bool m_SingleValue = false;         ///< true: single value, false: array
+    const bool m_ConstantShape = false; ///< true: fix m_Shape, m_Start, m_Count
+    Dims m_Shape;                       ///< total dimensions across MPI
+    Dims m_Start; ///< starting point (offsets) in global shape
+    Dims m_Count; ///< dimensions from m_Start in global shape
 
-    VariableBase(const std::string &name, const std::string type,
-                 const std::size_t elementSize, const Dims shape,
-                 const Dims start, const Dims count, const bool constantShape,
-                 const bool debugMode)
-    : m_Name{name}, m_Type{type}, m_ConstantShape{constantShape},
-      m_ElementSize{elementSize}, m_Count{count}, m_Shape{shape},
-      m_Start{start}, m_DebugMode{debugMode}
-    {
-        if (shape.empty() && start.empty())
-        {
-            if (count.empty())
-            {
-                m_VarClass = VarClass::GlobalValue;
-                m_IsScalar = true;
-            }
-            else
-            {
-                m_VarClass = VarClass::LocalArray;
-            }
-        }
-        else if (shape.size() == 1 && shape[0] == LocalValueDim)
-        {
-            m_VarClass = VarClass::LocalValue;
-            m_IsScalar = true;
-        }
-        else if (shape.size() > 0 && shape[0] == JoinedDim)
-        {
-            m_VarClass = VarClass::JoinedArray;
-        }
-        else
-        {
-            if ((start.empty() && count.empty()) ||
-                (shape.size() == start.size() && shape.size() == count.size()))
-            {
-                m_VarClass = VarClass::GlobalArray;
-            }
-            else
-            {
-                throw std::invalid_argument("DefineVariable() is invalid. The "
-                                            "combination of dimension "
-                                            "specifications cannot be "
-                                            "interpreted\n");
-            }
-        }
-    }
+    Dims m_MemoryStart; ///< offset of memory selection
+    Dims m_MemoryCount; ///< subset of m_Shape (e.g. remove ghost points)
 
-    virtual ~VariableBase() {}
+    /** Read from this step (must be 0 in staging) */
+    unsigned int m_ReadFromStep = 0;
+    /** Read this many steps at once (must be 1 in staging) */
+    unsigned int m_ReadNSteps = 1;
+    /** Global array was written as Joined array, so read accordingly */
+    bool m_ReadAsJoined = false;
+    /** Global array was written as Local value, so read accordingly */
+    bool m_ReadAsLocalValue = false;
+    /** number of steps available in a file (or 1 in staging) filled by
+     * InquireVariable*/
+    unsigned int m_AvailableSteps = 1;
+
+    VariableBase(const std::string &name, const std::string type,
+                 const size_t elementSize, const Dims shape, const Dims start,
+                 const Dims count, const bool constantShape,
+                 const bool debugMode);
 
-    std::size_t DimensionsSize() const noexcept { return m_Count.size(); }
+    virtual ~VariableBase() = default;
 
     /**
      * Returns the payload size in bytes
-     * @return TotalSize * sizeof(T)
+     * @return TotalSize * m_ElementSize
      */
-    std::size_t PayLoadSize() const noexcept
-    {
-        return GetTotalSize(m_Count) * m_ElementSize;
-    }
+    size_t PayLoadSize() const noexcept;
 
     /**
-     * Returns the total size
+     * Returns the total number of elements
      * @return number of elements
      */
-    std::size_t TotalSize() const noexcept { return GetTotalSize(m_Count); }
+    size_t TotalSize() const noexcept;
 
-    /**
-     * Set the local dimension and global offset of the variable
-     */
-    void SetSelection(const Dims start, const Dims count)
-    {
-        if (m_IsScalar)
-        {
-            throw std::invalid_argument("Variable.SetSelection() is an invalid "
-                                        "call for single value variable '" +
-                                        m_Name + "'\n");
-        }
-        if (m_ConstantShape)
-        {
-            throw std::invalid_argument(
-                "Variable.SetSelection() is not allowed "
-                "for constant shape variable '" +
-                m_Name + "'\n");
-        }
-        if (m_VarClass == VarClass::GlobalArray &&
-            m_Shape.size() != count.size())
-        {
-            throw std::invalid_argument("Variable.SetSelection() selection "
-                                        "dimension must equal the global "
-                                        "dimension of the variable '" +
-                                        m_Name + "'\n");
-        }
-        if ((m_VarClass == VarClass::LocalArray ||
-             m_VarClass == VarClass::JoinedArray) &&
-            !start.empty())
-        {
-            throw std::invalid_argument(
-                "Variable.SetSelection() for local or joined array '" + m_Name +
-                "' should pass an empty 'start' argument\n");
-        }
-        m_Count = count;
-        m_Start = start;
-    }
+    /** Set the local dimension and global offset of the variable */
+    void SetSelection(const Dims start, const Dims count);
 
-    /**
-     * Set the local dimension and global offset of the variable using a
-     * selection
-     */
-    void SetSelection(const SelectionBoundingBox &sel)
-    {
-        Dims start, count;
-        ConvertUint64VectorToSizetVector(sel.m_Start, start);
-        ConvertUint64VectorToSizetVector(sel.m_Count, count);
-        SetSelection(start, count);
-    }
+    /** Overloaded version of SetSelection using a SelectionBoundingBox */
+    void SetSelection(const SelectionBoundingBox &selection);
 
     /**
      * Set the local dimension and global offset of the variable using a
      * selection
      * Only bounding boxes are allowed
      */
-    void SetMemorySelection(const SelectionBoundingBox &sel)
-    {
-        if (m_Shape.size() == 0)
-        {
-            throw std::invalid_argument(
-                "Variable.SetMemorySelection() is an invalid "
-                "call for single value variables\n");
-        }
-        if (m_Shape.size() != sel.m_Count.size())
-        {
-            throw std::invalid_argument(
-                "Variable.SetMemorySelection() bounding box "
-                "dimension must equal the global "
-                "dimension of the variable\n");
-        }
-
-        ConvertUint64VectorToSizetVector(sel.m_Count, m_MemoryDimensions);
-        ConvertUint64VectorToSizetVector(sel.m_Start, m_MemoryOffsets);
-    }
+    void SetMemorySelection(const SelectionBoundingBox &selection);
 
     /**
      * Set the steps for the variable to read from. The pointer passed at
      * reading must be able to hold enough memory to store multiple steps in a
      * single read.
-     * @param fromStep  The first step to read. Steps start from 0
-     * @param nSteps    Number of consecutive steps to read at once.
+     * @param startStep  The first step to read. Steps start from 0
+     * @param countStep    Number of consecutive steps to read at once.
      *
      */
-    void SetStepSelection(const unsigned int fromStep,
-                          const unsigned int nSteps)
+    void SetStepSelection(const unsigned int startStep,
+                          const unsigned int countStep);
+
+    template <class... Args>
+    void AddTransform(Transform &transform, Args... args)
     {
-        m_ReadFromStep = fromStep;
-        m_ReadNSteps = nSteps;
+        std::vector<std::string> parameters = {args...};
+        m_TransformsInfo.emplace_back(
+            transform,
+            BuildParametersMap(parameters, m_DebugMode)); // need to check
     }
 
-    /** Return the number of steps available for the variable
-     *  @return Number of steps
-     */
-    unsigned int GetNSteps() { return m_NStepsAvailable; }
+    /** Apply current sequence of transforms defined by AddTransform */
+    virtual void ApplyTransforms() = 0;
+
+    /** Clears out the transform sequence defined by AddTransform */
+    void ClearTransforms();
 
-    ///< Should only be called by read engines
-    void SetNSteps(unsigned int steps) { m_NStepsAvailable = steps; }
-    unsigned int GetReadFromStep() { return m_ReadFromStep; }
-    unsigned int GetReadNSteps() { return m_ReadNSteps; }
-    void SetReadAsJoinedArray() { m_ReadAsJoined = true; }
-    void SetReadAsLocalValue() { m_ReadAsLocalValue = true; }
-    bool ReadAsJoinedArray() { return m_ReadAsJoined; }
-    bool ReadAsLocalValue() { return m_ReadAsLocalValue; }
+    /** Self-check dims according to type, called from Engine before Write
+     * @param hint extra debugging info for the exception */
+    void CheckDims(const std::string hint) const;
 
 private:
-    ///< Read from this step (must be 0 in staging)
-    unsigned int m_ReadFromStep = 0;
-    ///< Read this many steps at once (must be 1 in staging)
-    unsigned int m_ReadNSteps = 1;
-    ///< Global array was written as Joined array, so read accordingly
-    bool m_ReadAsJoined = false;
-    ///< Global array was written as Local value, so read accordingly
-    bool m_ReadAsLocalValue = false;
+    const bool m_DebugMode = false;
 
-    /* Values filled by InquireVariable() */
-    ///< number of steps available in a file (or 1 in staging),
-    unsigned int m_NStepsAvailable = 1;
+    void InitShapeType();
+
+    /** Transforms metadata info */
+    struct TransformInfo
+    {
+        /** reference to object derived from Transform class */
+        Transform &Object;
+        /** parameters from AddTransform */
+        std::map<std::string, std::string> Parameters;
+        /** resulting sizes from transformation */
+        std::vector<std::size_t> Sizes;
+    };
+
+    /**
+     * Sequence determines application order, e.g.
+     * first Transforms[0] then Transforms[1]. Pointer used as
+     * reference (no memory management).
+     */
+    std::vector<TransformInfo> m_TransformsInfo;
 };
 
 } // end namespace
diff --git a/source/adios2/core/VariableCompound.cpp b/source/adios2/core/VariableCompound.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..525ecbf19130e560821a1730d4ca9129d3826894
--- /dev/null
+++ b/source/adios2/core/VariableCompound.cpp
@@ -0,0 +1,37 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * VariableCompound.cpp
+ *
+ *  Created on: May 16, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "VariableCompound.h"
+#include "VariableCompound.tcc"
+
+#include "adios2/ADIOSConfig.h"
+
+namespace adios
+{
+
+VariableCompound::VariableCompound(const std::string name,
+                                   const size_t sizeOfStruct, const Dims shape,
+                                   const Dims start, const Dims count,
+                                   const bool constantShape,
+                                   const bool debugMode)
+: VariableBase(name, "compound", sizeOfStruct, shape, start, count,
+               constantShape, debugMode)
+{
+}
+
+void VariableCompound::ApplyTransforms() {}
+
+#define declare_template_instantiation(T)                                      \
+    template void VariableCompound::InsertMember<T>(const std::string,         \
+                                                    const size_t);
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
+} // end namespace
diff --git a/source/adios2/core/VariableCompound.h b/source/adios2/core/VariableCompound.h
index 5153a7c44a773a472c031b36d5fd79c000c465c6..9fc71d766f7a0d56c424e939b411a861d656876c 100644
--- a/source/adios2/core/VariableCompound.h
+++ b/source/adios2/core/VariableCompound.h
@@ -5,24 +5,18 @@
  * VariableCompound.h
  *
  *  Created on: Feb 20, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_CORE_VARIABLECOMPOUND_H_
 #define ADIOS2_CORE_VARIABLECOMPOUND_H_
 
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/VariableBase.h"
+#include "VariableBase.h"
 
-namespace adios
-{
+#include "adios2/ADIOSMacros.h"
 
-struct CompoundElement
+namespace adios
 {
-    const std::string m_Name;
-    const std::size_t m_Offset;
-    const std::string m_Type;
-};
 
 /**
  * @param Base (parent) class for template derived (child) class CVariable.
@@ -34,33 +28,41 @@ class VariableCompound : public VariableBase
 public:
     const void *m_AppValue = nullptr;
 
-    VariableCompound(const std::string name, const std::size_t sizeOfStruct,
-                     const Dims dimensions, const Dims globalDimensions,
-                     const Dims globalOffsets, const bool constantShape,
-                     const bool debugMode)
-    : VariableBase(name, "compound", sizeOfStruct, dimensions, globalDimensions,
-                   globalOffsets, constantShape, debugMode)
+    /** Primitive type element */
+    struct Element
     {
-    }
+        const std::string m_Name;
+        const std::string m_Type; ///< from GetType<T>
+        const size_t m_Offset;    ///< element offset in struct
+    };
 
-    template <class U>
-    void InsertMember(const std::string name, const std::size_t offset)
-    {
-        m_Elements.push_back(CompoundElement{name, offset, GetType<U>()});
-    }
+    /** vector of primitve element types defining compound struct */
+    std::vector<Element> m_Elements;
 
-    void Monitor(std::ostream &logInfo) const noexcept
-    {
-        logInfo << "Variable Compound: " << m_Name << "\n";
-        logInfo << "Type: " << m_Type << "\n";
-        logInfo << "Size: " << TotalSize() << " elements\n";
-        logInfo << "Payload: " << PayLoadSize() << " bytes\n";
-    }
+    VariableCompound(const std::string name, const std::size_t sizeOfStruct,
+                     const Dims shape, const Dims start, const Dims count,
+                     const bool constantShape, const bool debugMode);
+
+    ~VariableCompound() = default;
 
-private:
-    std::vector<CompoundElement> m_Elements; ///< vector of element types
+    void ApplyTransforms() final;
+
+    /**
+     * Inserts an Element into the compound struct definition
+     * @param name
+     * @param offset
+     */
+    template <class T>
+    void InsertMember(const std::string name, const size_t offset);
 };
 
-} // end namespace
+// Explicit declaration of the public template methods
+#define declare_template_instantiation(T)                                      \
+    extern template void VariableCompound::InsertMember<T>(const std::string,  \
+                                                           const size_t);
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
+} // end namespace adios
 
 #endif /* ADIOS2_CORE_VARIABLECOMPOUND_H_ */
diff --git a/source/adios2/core/VariableCompound.tcc b/source/adios2/core/VariableCompound.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..8293bce149e8278fc6f18c167a36fc0c1cfc13d4
--- /dev/null
+++ b/source/adios2/core/VariableCompound.tcc
@@ -0,0 +1,29 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * VariableCompound.tcc
+ *
+ *  Created on: May 16, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_VARIABLECOMPOUND_TCC_
+#define ADIOS2_CORE_VARIABLECOMPOUND_TCC_
+
+#include "VariableCompound.h"
+
+#include "adios2/ADIOSConfig.h"
+
+namespace adios
+{
+
+template <class T>
+void VariableCompound::InsertMember(const std::string name, const size_t offset)
+{
+    m_Elements.push_back(Element{name, GetType<T>(), offset});
+}
+
+} // end namespace
+
+#endif /* ADIOS2_CORE_VARIABLECOMPOUND_TCC_ */
diff --git a/source/adios2/core/adiosFunctions.h b/source/adios2/core/adiosFunctions.h
deleted file mode 100644
index c5336daa1c1ac9fa16123b2bf9d4a94a204ba4e2..0000000000000000000000000000000000000000
--- a/source/adios2/core/adiosFunctions.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * adiosFunctions.h Long helper functions used by ADIOS class
- *
- *  Created on: Oct 10, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_ADIOSFUNCTIONS_H_
-#define ADIOS2_CORE_ADIOSFUNCTIONS_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <cstring> //std::size_t
-#include <map>
-#include <memory> //std::shared_ptr
-#include <string>
-#include <vector>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/ADIOSMPICommOnly.h"
-#include "adios2/core/Transform.h"
-
-namespace adios
-{
-
-/**
- * Opens and checks for file and dumps contents to a single string
- * @param fileName file to be opened
- * @param fileContents output contains the entire file
- */
-void DumpFileToString(const std::string fileName, std::string &fileContents);
-
-/**
- * Extracts a substring between two tags from content
- * @param initialTag
- * @param finalTag
- * @param content full string
- * @param subString if found return substring between initialTag and finalTag,
- * otherwise returns empty
- * @param currentPosition to start the search, moved forward to finalTag
- * position
- */
-void GetSubString(const std::string initialTag, const std::string finalTag,
-                  const std::string content, std::string &subString,
-                  std::string::size_type &currentPosition);
-
-/**
- * Extracts the value inside quotes in a string currentTag ( Example: currentTag
- * --> field1="value1" field2="value2" )
- * @param quote double " or single '
- * @param quotePosition position of the opening quote in currentTag
- * @param currentTag initial tag value, modified by cutting the first found " "
- * portion, currentTag --> field2="value2"
- * @param value value1 in the example above
- */
-void GetQuotedValue(const char quote,
-                    const std::string::size_type &quotePosition,
-                    std::string &currentTag, std::string &value);
-
-/**
- * Get attributes field1="value1" field2="value2" by looping through a single
- * XML tag
- * @param tag field0="value0" field1="value1" in a single string
- * @param pairs pairs[0].first=field0 pairs[0].second=value0
- * pairs[1].first=field1 pairs[1].second=value1
- */
-void GetPairs(const std::string tag,
-              std::vector<std::pair<const std::string, const std::string>>
-                  &pairs) noexcept;
-
-/**
- * Determine tag type and call GetPairs to populate pairs
- * @param fileContent file Content in a single string
- * @param tag field0="value0" field1="value1" in a single string
- * @param pairs pairs[0].first=field0 pairs[0].second=value0
- * pairs[1].first=field1 pairs[1].second=value1
- */
-void GetPairsFromTag(
-    const std::string &fileContent, const std::string tag,
-    std::vector<std::pair<const std::string, const std::string>> &pairs);
-
-/**
- * Set members m_Groups and m_HostLanguage from XML file content, called within
- * Init functions
- * @param fileContent file Content in a single string
- * @param mpiComm MPI Communicator passed from application passed to Transport
- * method if required
- * @param hostLanguage return the host language from fileContent
- * @param transforms return the modified transforms vector if there are
- * variables with transformations
- * @param groups passed returns the map of groups defined in fileContent
- */
-// void SetMembers( const std::string& fileContent, const MPI_Comm mpiComm,
-//                 std::string& hostLanguage, std::vector<
-//                 std::shared_ptr<Transform> >& transforms,
-//                 std::map< std::string, Group >& groups );
-
-/**
- * Called inside the ADIOS XML constructors to get contents from file, broadcast
- * and set hostLanguage and groups from ADIOS class
- * @param xmlConfigFile xml config file name
- * @param mpiComm communicator used from broadcasting
- * @param debugMode from ADIOS m_DebugMode passed to CGroup in groups
- * @param hostLanguage set from host-language in xml file
- * @param transforms return the modified transforms vector if there are
- * variables with transformations
- * @param groups passed returns the map of groups defined in fileContent
- */
-// void InitXML( const std::string xmlConfigFile, const MPI_Comm mpiComm, const
-// bool debugMode,
-//              std::string& hostLanguage, std::vector<
-//              std::shared_ptr<Transform> >& transforms,
-//              std::map< std::string, Group >& groups );
-
-/**
- * Loops through a vector containing dimensions and returns the product of all
- * elements
- * @param dimensions input containing size on each dimension {Nx, Ny, Nz}
- * @return product of all dimensions Nx * Ny * Nz
- */
-std::size_t GetTotalSize(const std::vector<size_t> &dimensions);
-
-/**
- * Might need to add exceptions for debug mode
- * Creates a chain of directories using POSIX systems calls (stat, mkdir),
- * Verifies if directory exists before creating a new one. Permissions are 777
- * for now
- * @param fullPath /full/path/for/directory
- */
-void CreateDirectory(const std::string fullPath) noexcept;
-
-/**
- * Identifies, verifies the corresponding transform method and adds it the
- * transforms container if neccesary.
- * This functions must be updated as new transform methods are supported.
- * @param variableTransforms methods to be added to transforms with format
- * "method:compressionLevel", or  "method" with compressionLevel=0 (default)
- * @param transforms container of existing transform methods, owned by ADIOS
- * class
- * @param debugMode if true will do more checks, exceptions, warnings, expect
- * slower code
- * @param transformIndices returns the corresponding indices in ADIOS
- * m_Transforms for a single variable
- * @param parameters returns the corresponding parameters understood by a
- * collection of transform="method:parameter"
- */
-void SetTransformsHelper(const std::vector<std::string> &transformNames,
-                         std::vector<std::shared_ptr<Transform>> &transforms,
-                         const bool debugMode,
-                         std::vector<short> &transformIndices,
-                         std::vector<short> &parameters);
-
-/**
- * Transforms a vector
- * @param parameters vector of parameters with format "field=value"
- * @param debugMode true=check parameters format, false=no checks
- * @return a map with unique key=field, value=corresponding value
- */
-std::map<std::string, std::string>
-BuildParametersMap(const std::vector<std::string> &parameters,
-                   const bool debugMode);
-
-/**
- * Single call that extract data buffers information from Capsule. That way
- * virtual Capsule functions are called a few times
- * @param capsules input
- * @param dataBuffers from Capsule.GetData()
- * @param positions
- * @param absolutePositions
- */
-// void GetDataBuffers( const std::vector<Capsule*>& capsules,
-// std::vector<char*>& dataBuffers, std::vector<std::size_t>& positions,
-//                     std::vector<std::size_t>& absolutePositions );
-
-/**
- * Converts comma-separated values to a vector of integers
- * @param csv "1,2,3"
- * @return vector<int> = { 1, 2, 3 }
- */
-std::vector<int> CSVToVectorInt(const std::string csv);
-
-/** Convert a vector of uint64_t elements to a vector of std::size_t elements
- *  @param input vector of uint64_t elements
- *  @param output vector of std::size_t elements
- */
-void ConvertUint64VectorToSizetVector(const std::vector<std::uint64_t> &in,
-                                      std::vector<std::size_t> &out);
-/** Convert a C array of uint64_t elements to a vector of std::size_t elements
- *  @param number of elements
- *  @param input array of uint64_t elements
- *  @param vector of std::size_t elements. It will be resized to nElements.
- */
-void Uint64ArrayToSizetVector(const std::size_t nElements, const uint64_t *in,
-                              std::vector<std::size_t> &out);
-
-/** Convert a C array of uint64_t elements to a vector of std::size_t elements
- *  @param number of elements
- *  @param input array of uint64_t elements
- *  @return vector of std::size_t elements
- */
-std::vector<std::size_t> Uint64ArrayToSizetVector(const std::size_t nElements,
-                                                  const uint64_t *in);
-/**
- * Converts a vector of dimensions to a CSV string
- * @param dims vector of dimensions
- * @return comma separate value (CSV)
- */
-std::string DimsToCSV(const std::vector<std::size_t> &dims);
-
-/**
- * Grows a buffer by a factor of  n . growthFactor . currentCapacity to
- * accommodate for incomingDataSize
- * @param incomingDataSize size of new data required to be stored in buffer
- * @param growthFactor buffer grows in multiples of the growth buffer
- * @param buffer to be resized
- * @param position, current buffer position
- * @return -1: failed to allocate (bad_alloc), 0: didn't have to allocate
- * (enough space), 1: successful allocation
- */
-int GrowBuffer(const size_t incomingDataSize, const float growthFactor,
-               std::vector<char> &buffer, const size_t position);
-
-/**
- * Check if system is little endian
- * @return true: little endian, false: big endian
- */
-bool IsLittleEndian() noexcept;
-
-} // end namespace
-
-#endif /* ADIOS2_CORE_ADIOSFUNCTIONS_H_ */
diff --git a/source/adios2/core/adiosTemplates.h b/source/adios2/core/adiosTemplates.h
deleted file mode 100644
index 3c94ff392d5dfbcd2b66d230a5187874ccdc0b80..0000000000000000000000000000000000000000
--- a/source/adios2/core/adiosTemplates.h
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * adiosTemplates.h
- *
- *  Created on: Jan 26, 2017
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_ADIOSTEMPLATES_H_
-#define ADIOS2_CORE_ADIOSTEMPLATES_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <algorithm> //std::minmax_element
-#include <cmath>     //std::sqrt
-#include <complex>
-#include <cstring> //std::memcpy
-#include <iostream>
-#include <set>
-#include <thread>
-#include <vector>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/ADIOSTypes.h"
-
-namespace adios
-{
-/**
- * Get the primitive type in a string from a template
- * @return if T is a char, returns string = "char"
- */
-template <class T>
-inline std::string GetType() noexcept
-{
-    return "compound";
-}
-template <>
-inline std::string GetType<void>() noexcept
-{
-    return "unknown";
-}
-template <>
-inline std::string GetType<char>() noexcept
-{
-    return "char";
-}
-template <>
-inline std::string GetType<unsigned char>() noexcept
-{
-    return "unsigned char";
-}
-template <>
-inline std::string GetType<short>() noexcept
-{
-    return "short";
-}
-template <>
-inline std::string GetType<unsigned short>() noexcept
-{
-    return "unsigned short";
-}
-template <>
-inline std::string GetType<int>() noexcept
-{
-    return "int";
-}
-template <>
-inline std::string GetType<unsigned int>() noexcept
-{
-    return "unsigned int";
-}
-template <>
-inline std::string GetType<long int>() noexcept
-{
-    return "long int";
-}
-template <>
-inline std::string GetType<unsigned long int>() noexcept
-{
-    return "unsigned long int";
-}
-template <>
-inline std::string GetType<long long int>() noexcept
-{
-    return "long long int";
-}
-template <>
-inline std::string GetType<unsigned long long int>() noexcept
-{
-    return "unsigned long long int";
-}
-template <>
-inline std::string GetType<float>() noexcept
-{
-    return "float";
-}
-template <>
-inline std::string GetType<double>() noexcept
-{
-    return "double";
-}
-template <>
-inline std::string GetType<long double>() noexcept
-{
-    return "long double";
-}
-template <>
-inline std::string GetType<std::complex<float>>() noexcept
-{
-    return "float complex";
-}
-template <>
-inline std::string GetType<std::complex<double>>() noexcept
-{
-    return "double complex";
-}
-template <>
-inline std::string GetType<std::complex<long double>>() noexcept
-{
-    return "long double complex";
-}
-
-/**
- * Check in types set if "type" is one of the aliases for a certain type,
- * (e.g. if type = integer is an accepted alias for "int", returning true)
- * @param type input to be compared with an alias
- * @param aliases set containing aliases to a certain type, typically
- * Support::DatatypesAliases from Support.h
- * @return true: is an alias, false: is not
- */
-template <class T>
-bool IsTypeAlias(
-    const std::string type,
-    const std::map<std::string, std::set<std::string>> &aliases) noexcept
-{
-    if (type == GetType<T>()) // most of the time we will pass the same type,
-                              // which is a key in aliases
-        return true;
-
-    bool isAlias = false;
-    if (aliases.at(GetType<T>()).count(type) == 1)
-        isAlias = true;
-
-    return isAlias;
-}
-
-template <class T>
-void GetMinMax(const T *values, const size_t size, T &min, T &max) noexcept
-{
-    auto bounds = std::minmax_element(values, values + size);
-    min = *bounds.first;
-    max = *bounds.second;
-}
-
-/**
- * Get the minimum and maximum values in one loop
- * @param values array of primitives
- * @param size of the values array
- * @param min from values
- * @param max from values
- */
-template <class T>
-void GetMinMaxThreads(const T *values, const size_t size, T &min, T &max,
-                      const unsigned int threads = 1) noexcept
-{
-    if (threads == 1)
-    {
-        GetMinMax(values, size, min, max);
-        return;
-    }
-
-    const size_t stride = size / threads;    // elements per thread
-    const size_t remainder = size % threads; // remainder if not aligned
-    const size_t last = stride + remainder;
-
-    std::vector<T> mins(threads); // zero init
-    std::vector<T> maxs(threads); // zero init
-
-    std::vector<std::thread> getMinMaxThreads;
-    getMinMaxThreads.reserve(threads);
-
-    for (unsigned int t = 0; t < threads; ++t)
-    {
-        const size_t position = stride * t;
-
-        if (t == threads - 1)
-        {
-            getMinMaxThreads.push_back(
-                std::thread(adios::GetMinMax<T>, &values[position], last,
-                            std::ref(mins[t]), std::ref(maxs[t])));
-        }
-        else
-        {
-            getMinMaxThreads.push_back(
-                std::thread(adios::GetMinMax<T>, &values[position], stride,
-                            std::ref(mins[t]), std::ref(maxs[t])));
-        }
-    }
-
-    for (auto &getMinMaxThread : getMinMaxThreads)
-    {
-        getMinMaxThread.join();
-    }
-
-    auto itMin = std::min_element(mins.begin(), mins.end());
-    min = *itMin;
-
-    auto itMax = std::max_element(maxs.begin(), maxs.end());
-    max = *itMax;
-}
-
-/**
- * Overloaded version for complex types, gets the "doughnut" range between min
- * and max modulus
- * @param values array of complex numbers
- * @param size of the values array
- * @param min modulus from values
- * @param max modulus from values
- */
-template <class T>
-void GetMinMaxComplex(const std::complex<T> *values, const size_t size, T &min,
-                      T &max) noexcept
-{
-
-    min = std::norm(values[0]);
-    max = min;
-
-    for (size_t i = 1; i < size; ++i)
-    {
-        T norm = std::norm(values[i]);
-
-        if (norm < min)
-        {
-            min = norm;
-            continue;
-        }
-
-        if (norm > max)
-        {
-            max = norm;
-        }
-    }
-
-    min = std::sqrt(min);
-    max = std::sqrt(max);
-}
-
-template <class T>
-void GetMinMaxThreads(const std::complex<T> *values, const size_t size, T &min,
-                      T &max, const unsigned int threads = 1) noexcept
-{
-    if (threads == 1)
-    {
-        GetMinMaxComplex(values, size, min, max);
-        return;
-    }
-
-    const size_t stride = size / threads;    // elements per thread
-    const size_t remainder = size % threads; // remainder if not aligned
-    const size_t last = stride + remainder;
-
-    std::vector<T> mins(threads); // zero init
-    std::vector<T> maxs(threads); // zero init
-
-    std::vector<std::thread> getMinMaxThreads;
-    getMinMaxThreads.reserve(threads);
-
-    for (unsigned int t = 0; t < threads; ++t)
-    {
-        const size_t position = stride * t;
-
-        if (t == threads - 1)
-        {
-            getMinMaxThreads.push_back(
-                std::thread(GetMinMaxComplex<T>, &values[position], last,
-                            std::ref(mins[t]), std::ref(maxs[t])));
-        }
-        else
-        {
-            getMinMaxThreads.push_back(
-                std::thread(GetMinMaxComplex<T>, &values[position], stride,
-                            std::ref(mins[t]), std::ref(maxs[t])));
-        }
-    }
-
-    for (auto &getMinMaxThread : getMinMaxThreads)
-    {
-        getMinMaxThread.join();
-    }
-
-    auto itMin = std::min_element(mins.begin(), mins.end());
-    min = *itMin;
-
-    auto itMax = std::max_element(maxs.begin(), maxs.end());
-    max = *itMax;
-}
-
-/**
- * threaded version of std::memcpy
- * @param dest
- * @param source
- * @param count total number of bytes (as in memcpy)
- * @param nthreads
- */
-template <class T, class U>
-void MemcpyThreads(T *destination, const U *source, size_t count,
-                   const unsigned int threads = 1)
-{
-    // do not decompose tasks to less than 4MB pieces
-    const size_t minBlockSize = 4194304;
-    const size_t maxNThreads = std::max((size_t)threads, count / minBlockSize);
-
-    if (maxNThreads == 1)
-    {
-        std::memcpy(destination, source, count);
-        return;
-    }
-
-    const std::size_t stride = count / maxNThreads;
-    const std::size_t remainder = count % maxNThreads;
-    const std::size_t last = stride + remainder;
-
-    std::vector<std::thread> memcpyThreads;
-    memcpyThreads.reserve(maxNThreads);
-
-    for (unsigned int t = 0; t < maxNThreads; ++t)
-    {
-        const size_t initialDestination = stride * t / sizeof(T);
-        const size_t initialSource = stride * t / sizeof(U);
-
-        if (t == maxNThreads - 1)
-            memcpyThreads.push_back(
-                std::thread(std::memcpy, &destination[initialDestination],
-                            &source[initialSource], last));
-        else
-            memcpyThreads.push_back(
-                std::thread(std::memcpy, &destination[initialDestination],
-                            &source[initialSource], stride));
-    }
-    // Now join the threads (is this really needed?)
-    for (auto &thread : memcpyThreads)
-        thread.join();
-}
-
-template <class T>
-void MemcpyToBuffer(std::vector<char> &raw, std::size_t &position,
-                    const T *source, std::size_t size) noexcept
-{
-    std::memcpy(&raw[position], source, size);
-    position += size;
-}
-
-/**
- * Version that pushed to the end of the buffer, updates vec.size()
- * automatically
- * @param raw
- * @param source using pointer notation
- * @param elements
- */
-template <class T>
-void InsertToBuffer(std::vector<char> &buffer, const T *source,
-                    const std::size_t elements = 1) noexcept
-{
-    const char *src = reinterpret_cast<const char *>(source);
-    buffer.insert(buffer.end(), src, src + elements * sizeof(T));
-}
-
-/**
- * Copies data to a specific location in the buffer.
- * Updates position.
- * Does not update vec.size().
- * @param raw
- * @param position
- * @param source
- * @param elements
- */
-template <class T>
-void CopyToBuffer(std::vector<char> &buffer, size_t &position, const T *source,
-                  const size_t elements = 1) noexcept
-{
-    const char *src = reinterpret_cast<const char *>(source);
-    std::copy(src, src + elements * sizeof(T), buffer.begin() + position);
-    position += elements * sizeof(T);
-}
-
-template <class T>
-void CopyToBufferThreads(std::vector<char> &buffer, size_t &position,
-                         const T *source, const size_t elements = 1,
-                         const unsigned int threads = 1) noexcept
-{
-    if (threads == 1)
-    {
-        CopyToBuffer(buffer, position, source, elements);
-        return;
-    }
-
-    const size_t stride = elements / threads;    // elements per thread
-    const size_t remainder = elements % threads; // remainder if not aligned
-    const size_t last = stride + remainder;
-
-    std::vector<std::thread> copyThreads;
-    copyThreads.reserve(threads);
-
-    for (unsigned int t = 0; t < threads; ++t)
-    {
-        size_t bufferPosition = stride * t * sizeof(T);
-        const size_t sourcePosition = stride * t;
-
-        if (t == threads - 1) // last thread takes stride + remainder
-        {
-            copyThreads.push_back(std::thread(CopyToBuffer<T>, std::ref(buffer),
-                                              std::ref(bufferPosition),
-                                              &source[sourcePosition], last));
-            position = bufferPosition; // last position
-        }
-        else
-        {
-            copyThreads.push_back(std::thread(CopyToBuffer<T>, std::ref(buffer),
-                                              std::ref(bufferPosition),
-                                              &source[sourcePosition], stride));
-        }
-    }
-
-    for (auto &copyThread : copyThreads)
-    {
-        copyThread.join();
-    }
-}
-
-template <class T>
-void CopyFromBuffer(T *destination, std::size_t elements,
-                    const std::vector<char> &raw,
-                    std::size_t &position) noexcept
-{
-    std::copy(raw.begin() + position,
-              raw.begin() + position + sizeof(T) * elements,
-              reinterpret_cast<char *>(destination));
-    position += elements * sizeof(T);
-}
-
-template <class T>
-void PrintValues(const std::string name, const char *buffer,
-                 const std::size_t position, const std::size_t elements)
-{
-    std::vector<T> values(elements);
-    std::memcpy(values.data(), &buffer[position], elements * sizeof(T));
-
-    std::cout << "Read " << name << "\n";
-    for (const auto value : values)
-        std::cout << value << " ";
-
-    std::cout << "\n";
-}
-
-} // end namespace
-
-#endif /* ADIOS2_CORE_ADIOSTEMPLATES_H_ */
diff --git a/source/adios2/core/capsuleTemplates.h b/source/adios2/core/capsuleTemplates.h
deleted file mode 100644
index 76c022f2775a7421a6926697a7ed9a7a1a0770a9..0000000000000000000000000000000000000000
--- a/source/adios2/core/capsuleTemplates.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * capsuleTemplates.h
- *
- *  Created on: Nov 18, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_CORE_CAPSULETEMPLATES_H_
-#define ADIOS2_CORE_CAPSULETEMPLATES_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <cstring> //std::memcpy
-#include <thread>
-#include <vector>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Transport.h"
-
-namespace adios
-{
-
-/**
- *
- * @param data
- * @param size
- * @param transportIndex
- * @param transports
- * @param maxBufferSize
- * @param buffer
- */
-// template<class T>
-// void WriteToBuffer( const T* data, const size_t size,
-//                    std::vector< std::shared_ptr<Transport> >& transports,
-//                    const size_t maxBufferSize, std::vector<char>& buffer )
-//{
-//    auto lf_TransportsWrite = []( const int transportIndex, std::vector<
-//    std::shared_ptr<Transport> >& transports,
-//                                  std::vector<char>& buffer )
-//    {
-//        if( transportIndex == -1 ) // all transports
-//        {
-//            for( auto& transport : transports )
-//                transport->Write( buffer );
-//        }
-//        else
-//            transports[ transportIndex ]->Write( buffer );
-//    };
-//
-//    //FUNCTION starts here
-//    const size_t dataBytes = size * sizeof( T ); //size of data in bytes
-//
-//    //check for DataMan transport
-//    if( transportIndex == -1 ) // all transports
-//    {
-//        for( auto& transport : transports )
-//        {
-//            if( transport->m_Method == "DataMan" ) //DataMan needs all the
-//            information
-//                buffer.resize( dataBytes ); //resize buffer to fit all data
-//        }
-//    }
-//    else //just one transport
-//    {
-//        if( transports[transportIndex]->m_Method == "DataMan" )
-//            buffer.resize( dataBytes ); //resize buffer to fit all data
-//    }
-//
-//    if( dataBytes <= buffer.size() ) // dataBytes < buffer.size()
-//    {
-//        buffer.resize( dataBytes ); //this resize shouldn't change capacity or
-//        call realloc
-//        MemcpyThreads( &buffer[0], data, dataBytes, 1 ); //copy memory in
-//        threaded fashion, need to test with size, serial for now
-//        lf_TransportsWrite( transportIndex, transports, buffer );
-//        return;
-//    }
-//
-//    if( buffer.size() < dataBytes && dataBytes <= maxBufferSize ) //
-//    buffer.size() < dataBytes <  maxBufferSize
-//    {
-//        buffer.resize( dataBytes );
-//        MemcpyThreads( &buffer[0], data, dataBytes, 1 ); //copy memory in
-//        threaded fashion, need to test with size, serial for now
-//        lf_TransportsWrite( transportIndex, transports, buffer );
-//        return;
-//    }
-//
-//    // dataBytes > maxBufferSize == buffer.size() split the variable in buffer
-//    buckets
-//    buffer.resize( maxBufferSize ); //resize to maxBufferSize, this might call
-//    realloc
-//    const size_t buckets =  dataBytes / maxBufferSize + 1;
-//    const size_t remainder = dataBytes % maxBufferSize;
-//
-//    for( unsigned int bucket = 0; buckets < buckets; ++bucket )
-//    {
-//        const size_t dataOffset = bucket * maxBufferSize / sizeof( T );
-//
-//        if( bucket == buckets-1 )
-//            MemcpyThreads( &buffer[0], data[dataOffset], remainder, 1 );
-//        else
-//            MemcpyThreads( &buffer[0], data[dataOffset], maxBufferSize, 1 );
-//
-//        lf_TransportsWrite( transportIndex, transports, buffer );
-//    }
-//}
-
-} // end namespace
-
-#endif /* ADIOS2_CORE_CAPSULETEMPLATES_H_ */
diff --git a/source/adios2/engine/adios1/ADIOS1Reader.cpp b/source/adios2/engine/adios1/ADIOS1Reader.cpp
index 2571139cbf93b40488b78787872b9b5412e47a82..9556bdb27200c17a2e6e9073423c72dfe28e8159 100644
--- a/source/adios2/engine/adios1/ADIOS1Reader.cpp
+++ b/source/adios2/engine/adios1/ADIOS1Reader.cpp
@@ -5,28 +5,24 @@
  * ADIOS1Reader.cpp
  *
  *  Created on: Feb 27, 2017
- *      Author: wfg
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
  */
 
 #include "ADIOS1Reader.h"
 
-#include "adios2/core/Support.h"
-#include "adios2/core/adiosFunctions.h"           // CSVToVector
-#include "adios2/transport/file/FStream.h"        // uses C++ fstream
-#include "adios2/transport/file/FileDescriptor.h" // uses POSIX
-#include "adios2/transport/file/FilePointer.h"    // uses C FILE*
-
 #include <adios_error.h>
 
+#include "adios2/helper/adiosFunctions.h" // CSVToVector
+
 namespace adios
 {
 
-ADIOS1Reader::ADIOS1Reader(ADIOS &adios, const std::string &name,
-                           const std::string accessMode, MPI_Comm mpiComm,
-                           const Method &method)
-: Engine(adios, "ADIOS1Reader", name, accessMode, mpiComm, method,
-         " ADIOS1Reader constructor (or call to ADIOS Open).\n")
+ADIOS1Reader::ADIOS1Reader(IO &io, const std::string &name,
+                           const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("ADIOS1Reader", io, name, openMode, mpiComm)
 {
+    m_EndMessage = " in call to IO Open ADIOS1Reader " + m_Name + "\n";
+
     Init();
     adios_read_init_method(m_ReadMethod, mpiComm, "");
     if (m_OpenAsFile)
@@ -47,11 +43,12 @@ ADIOS1Reader::~ADIOS1Reader()
     adios_read_finalize_method(m_ReadMethod);
 }
 
-Variable<void> *
-ADIOS1Reader::InquireVariable(const std::string &variableName,
-                              const bool readIn) // not yet implemented
+// PRIVATE
+VariableBase *
+ADIOS1Reader::InquireVariableUnknown(const std::string &variableName,
+                                     const bool readIn)
 {
-    return nullptr;
+    return nullptr; // not yet implemented
 }
 
 Variable<char> *
@@ -224,210 +221,25 @@ void ADIOS1Reader::ScheduleReadCommon(const std::string &name, const Dims &offs,
     }
 }
 
-void ADIOS1Reader::ScheduleRead(Variable<char> &variable, char *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<unsigned char> &variable,
-                                unsigned char *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<short> &variable, short *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<unsigned short> &variable,
-                                unsigned short *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<int> &variable, int *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<unsigned int> &variable,
-                                unsigned int *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<long int> &variable, long int *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<unsigned long int> &variable,
-                                unsigned long int *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<long long int> &variable,
-                                long long int *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<unsigned long long int> &variable,
-                                unsigned long long int *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<float> &variable, float *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<double> &variable, double *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<long double> &variable,
-                                long double *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<std::complex<float>> &variable,
-                                std::complex<float> *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<std::complex<double>> &variable,
-                                std::complex<double> *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
-void ADIOS1Reader::ScheduleRead(Variable<std::complex<long double>> &variable,
-                                std::complex<long double> *values)
-{
-    ScheduleReadCommon(variable.m_Name, variable.m_Start, variable.m_Count,
-                       variable.GetReadFromStep(), variable.GetReadNSteps(),
-                       variable.ReadAsLocalValue(),
-                       variable.ReadAsJoinedArray(), (void *)values);
-}
+#define declare_type(T)                                                        \
+    void ADIOS1Reader::DoScheduleRead(Variable<T> &variable, const T *values)  \
+    {                                                                          \
+        ScheduleReadCommon(variable.m_Name, variable.m_Start,                  \
+                           variable.m_Count, variable.m_ReadFromStep,          \
+                           variable.m_ReadNSteps, variable.m_ReadAsLocalValue, \
+                           variable.m_ReadAsJoined, (void *)values);           \
+    }                                                                          \
+                                                                               \
+    void ADIOS1Reader::DoScheduleRead(const std::string &variableName,         \
+                                      const T *values)                         \
+    {                                                                          \
+        DoScheduleRead(m_IO.GetVariable<T>(variableName), values);             \
+    }
 
-void ADIOS1Reader::ScheduleRead(const std::string &variableName, char *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<char>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                unsigned char *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<unsigned char>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName, short *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<short>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                unsigned short *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<unsigned short>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName, int *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<int>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                unsigned int *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<unsigned int>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                long int *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<long int>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                unsigned long int *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<unsigned long int>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                long long int *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<long long int>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                unsigned long long int *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<unsigned long long int>(variableName),
-                 values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName, float *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<float>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName, double *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<double>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                long double *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<long double>(variableName), values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                std::complex<float> *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<std::complex<float>>(variableName),
-                 values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                std::complex<double> *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<std::complex<double>>(variableName),
-                 values);
-}
-void ADIOS1Reader::ScheduleRead(const std::string &variableName,
-                                std::complex<long double> *values)
-{
-    ScheduleRead(m_ADIOS.GetVariable<std::complex<long double>>(variableName),
-                 values);
-}
+ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
-void ADIOS1Reader::PerformReads(PerformReadMode mode)
+void ADIOS1Reader::PerformReads(ReadMode mode)
 {
     adios_perform_reads(m_fh, (int)mode);
 }
@@ -436,7 +248,7 @@ void ADIOS1Reader::Release() { adios_release_step(m_fh); }
 
 void ADIOS1Reader::Advance(const float timeout_sec)
 {
-    Advance(AdvanceMode::NEXT_AVAILABLE, timeout_sec);
+    Advance(AdvanceMode::NextAvailable, timeout_sec);
 }
 
 void ADIOS1Reader::Advance(AdvanceMode mode, const float timeout_sec)
@@ -447,7 +259,7 @@ void ADIOS1Reader::Advance(AdvanceMode mode, const float timeout_sec)
                                     "Advance() on a file which was opened for "
                                     "read as File\n");
     }
-    int last = (mode == AdvanceMode::NEXT_AVAILABLE ? 0 : 1);
+    int last = (mode == AdvanceMode::NextAvailable ? 0 : 1);
     float *to = const_cast<float *>(&timeout_sec);
     adios_advance_step(m_fh, last, *to);
 
@@ -457,13 +269,13 @@ void ADIOS1Reader::Advance(AdvanceMode mode, const float timeout_sec)
         m_AdvanceStatus = AdvanceStatus::OK;
         break;
     case err_end_of_stream:
-        m_AdvanceStatus = AdvanceStatus::END_OF_STREAM;
+        m_AdvanceStatus = AdvanceStatus::EndOfStream;
         break;
     case err_step_notready:
-        m_AdvanceStatus = AdvanceStatus::STEP_NOT_READY;
+        m_AdvanceStatus = AdvanceStatus::StepNotReady;
         break;
     default:
-        m_AdvanceStatus = AdvanceStatus::OTHER_ERROR;
+        m_AdvanceStatus = AdvanceStatus::OtherError;
         break;
     }
 }
@@ -485,13 +297,15 @@ void ADIOS1Reader::Close(const int transportIndex)
 // PRIVATE
 void ADIOS1Reader::Init()
 {
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
-        if (m_AccessMode != "r" && m_AccessMode != "read")
+        if (m_OpenMode != OpenMode::Read)
+        {
             throw std::invalid_argument(
-                "ERROR: ADIOS1Reader doesn't support access mode " +
-                m_AccessMode +
-                ", in call to ADIOS Open or ADIOS1Reader constructor\n");
+                "ERROR: ADIOS1Reader only supports OpenMode::r (read) access "
+                "mode " +
+                m_EndMessage);
+        }
     }
     InitParameters();
     InitTransports();
@@ -499,8 +313,8 @@ void ADIOS1Reader::Init()
 
 void ADIOS1Reader::InitParameters()
 {
-    auto itOpenAsFile = m_Method.m_Parameters.find("OpenAsFile");
-    if (itOpenAsFile != m_Method.m_Parameters.end())
+    auto itOpenAsFile = m_IO.m_Parameters.find("OpenAsFile");
+    if (itOpenAsFile != m_IO.m_Parameters.end())
     {
         m_OpenAsFile = true;
     }
@@ -509,18 +323,7 @@ void ADIOS1Reader::InitParameters()
 void ADIOS1Reader::InitTransports()
 {
 
-    if (m_DebugMode == true)
-    {
-        if (TransportNamesUniqueness() == false)
-        {
-            throw std::invalid_argument(
-                "ERROR: two transports of the same kind (e.g file IO) "
-                "can't have the same name, modify with name= in Method "
-                "AddTransport\n");
-        }
-    }
-
-    for (const auto &parameters : m_Method.m_TransportParameters)
+    for (const auto &parameters : m_IO.m_TransportsParameters)
     {
         auto itTransport = parameters.find("transport");
         if (itTransport->second == "file" || itTransport->second == "File" ||
@@ -530,11 +333,13 @@ void ADIOS1Reader::InitTransports()
         }
         else
         {
-            if (m_DebugMode == true)
+            if (m_DebugMode)
+            {
                 throw std::invalid_argument(
                     "ERROR: transport " + itTransport->second +
                     " (you mean File?) not supported, in " + m_Name +
                     m_EndMessage);
+            }
         }
     }
 }
diff --git a/source/adios2/engine/adios1/ADIOS1Reader.h b/source/adios2/engine/adios1/ADIOS1Reader.h
index a30894d5df688e9b78ff4124278c9115c089a0ed..882b6b6490fdf222e66a9b275dcfb7fe6813b027 100644
--- a/source/adios2/engine/adios1/ADIOS1Reader.h
+++ b/source/adios2/engine/adios1/ADIOS1Reader.h
@@ -7,7 +7,7 @@
  * It requires adios 1.x installed
  *
  *  Created on: Mar 27, 2017
- *      Author: pnb
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
  */
 
 #ifndef ADIOS2_ENGINE_ADIOS1_ADIOS1READER_H_
@@ -15,11 +15,10 @@
 
 #include <iostream> //this must go away
 
-#include "adios2/ADIOS.h"
 #include "adios2/ADIOSConfig.h"
-#include "adios2/capsule/heap/STLVector.h"
+#include "adios2/core/ADIOS.h"
 #include "adios2/core/Engine.h"
-#include "adios2/core/adiosFunctions.h"
+#include "adios2/helper/adiosFunctions.h"
 
 // Fake out the include guard from ADIOS1's mpidummy.h to prevent it from
 // getting included
@@ -50,102 +49,12 @@ public:
      * @param debugMode
      * @param hostLanguage
      */
-    ADIOS1Reader(ADIOS &adios, const std::string &name,
-                 const std::string accessMode, MPI_Comm mpiComm,
-                 const Method &method);
+    ADIOS1Reader(IO &adios, const std::string &name, const OpenMode openMode,
+                 MPI_Comm mpiComm);
 
     ~ADIOS1Reader();
 
-    Variable<void> *InquireVariable(const std::string &name,
-                                    const bool readIn = true);
-    Variable<char> *InquireVariableChar(const std::string &name,
-                                        const bool readIn = true);
-    Variable<unsigned char> *InquireVariableUChar(const std::string &name,
-                                                  const bool readIn = true);
-    Variable<short> *InquireVariableShort(const std::string &name,
-                                          const bool readIn = true);
-    Variable<unsigned short> *InquireVariableUShort(const std::string &name,
-                                                    const bool readIn = true);
-    Variable<int> *InquireVariableInt(const std::string &name,
-                                      const bool readIn = true);
-    Variable<unsigned int> *InquireVariableUInt(const std::string &name,
-                                                const bool readIn = true);
-    Variable<long int> *InquireVariableLInt(const std::string &name,
-                                            const bool readIn = true);
-    Variable<unsigned long int> *InquireVariableULInt(const std::string &name,
-                                                      const bool readIn = true);
-    Variable<long long int> *InquireVariableLLInt(const std::string &name,
-                                                  const bool readIn = true);
-    Variable<unsigned long long int> *
-    InquireVariableULLInt(const std::string &name, const bool readIn = true);
-    Variable<float> *InquireVariableFloat(const std::string &name,
-                                          const bool readIn = true);
-    Variable<double> *InquireVariableDouble(const std::string &name,
-                                            const bool readIn = true);
-    Variable<long double> *InquireVariableLDouble(const std::string &name,
-                                                  const bool readIn = true);
-    Variable<std::complex<float>> *
-    InquireVariableCFloat(const std::string &name, const bool readIn = true);
-    Variable<std::complex<double>> *
-    InquireVariableCDouble(const std::string &name, const bool readIn = true);
-    Variable<std::complex<long double>> *
-    InquireVariableCLDouble(const std::string &name, const bool readIn = true);
-
-    /**
-     * Not implemented
-     * @param name
-     * @param readIn
-     * @return
-     */
-    VariableCompound *InquireVariableCompound(const std::string &name,
-                                              const bool readIn = true);
-
-    void ScheduleRead(Variable<char> &variable, char *values);
-    void ScheduleRead(Variable<unsigned char> &variable, unsigned char *values);
-    void ScheduleRead(Variable<short> &variable, short *values);
-    void ScheduleRead(Variable<unsigned short> &variable,
-                      unsigned short *values);
-    void ScheduleRead(Variable<int> &variable, int *values);
-    void ScheduleRead(Variable<unsigned int> &variable, unsigned int *values);
-    void ScheduleRead(Variable<long int> &variable, long int *values);
-    void ScheduleRead(Variable<unsigned long int> &variable,
-                      unsigned long int *values);
-    void ScheduleRead(Variable<long long int> &variable, long long int *values);
-    void ScheduleRead(Variable<unsigned long long int> &variable,
-                      unsigned long long int *values);
-    void ScheduleRead(Variable<float> &variable, float *values);
-    void ScheduleRead(Variable<double> &variable, double *values);
-    void ScheduleRead(Variable<long double> &variable, long double *values);
-    void ScheduleRead(Variable<std::complex<float>> &variable,
-                      std::complex<float> *values);
-    void ScheduleRead(Variable<std::complex<double>> &variable,
-                      std::complex<double> *values);
-    void ScheduleRead(Variable<std::complex<long double>> &variable,
-                      std::complex<long double> *values);
-
-    void ScheduleRead(const std::string &variableName, char *values);
-    void ScheduleRead(const std::string &variableName, unsigned char *values);
-    void ScheduleRead(const std::string &variableName, short *values);
-    void ScheduleRead(const std::string &variableName, unsigned short *values);
-    void ScheduleRead(const std::string &variableName, int *values);
-    void ScheduleRead(const std::string &variableName, unsigned int *values);
-    void ScheduleRead(const std::string &variableName, long int *values);
-    void ScheduleRead(const std::string &variableName,
-                      unsigned long int *values);
-    void ScheduleRead(const std::string &variableName, long long int *values);
-    void ScheduleRead(const std::string &variableName,
-                      unsigned long long int *values);
-    void ScheduleRead(const std::string &variableName, float *values);
-    void ScheduleRead(const std::string &variableName, double *values);
-    void ScheduleRead(const std::string &variableName, long double *values);
-    void ScheduleRead(const std::string &variableName,
-                      std::complex<float> *values);
-    void ScheduleRead(const std::string &variableName,
-                      std::complex<double> *values);
-    void ScheduleRead(const std::string &variableName,
-                      std::complex<long double> *values);
-
-    void PerformReads(PerformReadMode mode);
+    void PerformReads(ReadMode mode);
 
     void Release();
     void Advance(const float timeout_sec = 0.0);
@@ -160,120 +69,59 @@ private:
     ADIOS_FILE *m_fh = nullptr; ///< ADIOS1 file handler
     bool m_OpenAsFile = false;
 
-    void Init(); ///< called from constructor, gets the selected ADIOS1
-                 /// transport method from settings
-    void InitParameters();
-    void InitTransports();
+    void Init() final; ///< called from constructor, gets the selected ADIOS1
+                       /// transport method from settings
+    void InitParameters() final;
+    void InitTransports() final;
 
-    template <class T>
-    Variable<T> *InquireVariableCommon(const std::string &name,
-                                       const bool readIn)
-    {
-        // here read variable metadata (dimensions, type, etc.)...then create a
-        // Variable like below:
-        // Variable<T>& variable = m_ADIOS.DefineVariable<T>( m_Name + "/" +
-        // name, )
-        // return &variable; //return address if success
-        ADIOS_VARINFO *vi = adios_inq_var(m_fh, name.c_str());
-        adios::Variable<T> *var = nullptr;
-        if (vi != nullptr)
-        {
-            CheckADIOS1TypeCompatibility(name, GetType<T>(),
-                                         vi->type); // throws
+    VariableBase *InquireVariableUnknown(const std::string &name,
+                                         const bool readIn) final;
+    Variable<char> *InquireVariableChar(const std::string &name,
+                                        const bool readIn) final;
+    Variable<unsigned char> *InquireVariableUChar(const std::string &name,
+                                                  const bool readIn) final;
+    Variable<short> *InquireVariableShort(const std::string &name,
+                                          const bool readIn) final;
+    Variable<unsigned short> *InquireVariableUShort(const std::string &name,
+                                                    const bool readIn) final;
+    Variable<int> *InquireVariableInt(const std::string &name,
+                                      const bool readIn) final;
+    Variable<unsigned int> *InquireVariableUInt(const std::string &name,
+                                                const bool readIn) final;
+    Variable<long int> *InquireVariableLInt(const std::string &name,
+                                            const bool readIn) final;
+    Variable<unsigned long int> *InquireVariableULInt(const std::string &name,
+                                                      const bool readIn) final;
+    Variable<long long int> *InquireVariableLLInt(const std::string &name,
+                                                  const bool readIn) final;
+    Variable<unsigned long long int> *
+    InquireVariableULLInt(const std::string &name, const bool readIn) final;
 
-            if (vi->ndim > 0)
-            {
-                Dims gdims = Uint64ArrayToSizetVector(vi->ndim, vi->dims);
+    Variable<float> *InquireVariableFloat(const std::string &name,
+                                          const bool readIn) final;
+    Variable<double> *InquireVariableDouble(const std::string &name,
+                                            const bool readIn) final;
+    Variable<long double> *InquireVariableLDouble(const std::string &name,
+                                                  const bool readIn) final;
+    Variable<cfloat> *InquireVariableCFloat(const std::string &name,
+                                            const bool readIn) final;
+    Variable<cdouble> *InquireVariableCDouble(const std::string &name,
+                                              const bool readIn) final;
+    Variable<cldouble> *InquireVariableCLDouble(const std::string &name,
+                                                const bool readIn) final;
+    /** Not yet implemented */
+    VariableCompound *InquireVariableCompound(const std::string &name,
+                                              const bool readIn);
 
-                bool joinedread = false;
-                if (gdims[0] == JoinedDim)
-                {
-                    /* Joined Array */
-                    adios_inq_var_blockinfo(m_fh, vi);
-                    size_t joined_size = 0;
-                    for (int i = 0; i < *vi->nblocks; i++)
-                    {
-                        joined_size += vi->blockinfo[i].count[0];
-                    }
-                    gdims[0] = joined_size;
-                    joinedread = true;
-                }
+    template <class T>
+    Variable<T> *InquireVariableCommon(const std::string &name,
+                                       const bool readIn);
 
-                if (!vi->global)
-                {
-                    /* Local array */
-                    for (int j = 0; j < vi->ndim; ++j)
-                    {
-                        gdims[j] = IrregularDim;
-                    }
-                }
-                else
-                {
-                    /* Check if dimensions change in time */
-                    for (int step = 1; step < vi->nsteps; ++step)
-                    {
-                        Dims dims =
-                            gdims; // GetGlobalDimsAtStep(vi, step, joinedread);
-                        for (int j = 0; j < vi->ndim; ++j)
-                        {
-                            if (dims[j] != gdims[j])
-                                gdims[j] = IrregularDim;
-                        }
-                    }
-                }
-                var = &m_ADIOS.DefineArray<T>(name, gdims);
-                if (joinedread)
-                    var->SetReadAsJoinedArray();
-            }
-            else /* Scalars */
-            {
-                /* scalar variable but global value or local value*/
-                std::string aname = name + "/ReadAsArray";
-                bool isLocalValue = false;
-                for (int i = 0; i < vi->nattrs; ++i)
-                {
-                    if (!strcmp(m_fh->attr_namelist[vi->attr_ids[i]],
-                                aname.c_str()))
-                    {
-                        isLocalValue = true;
-                    }
-                }
-                if (isLocalValue)
-                {
-                    /* Local Value */
-                    bool changingDims = false;
-                    for (int step = 1; step < vi->nsteps; ++step)
-                    {
-                        if (vi->nblocks[step] != vi->nblocks[0])
-                            changingDims = true;
-                    }
-                    if (changingDims)
-                    {
-                        var = &m_ADIOS.DefineVariable<T>(name, {IrregularDim});
-                    }
-                    else
-                    {
-                        var = &m_ADIOS.DefineVariable<T>(
-                            name, {(unsigned int)vi->nblocks[0]});
-                    }
-                    var->SetReadAsLocalValue();
-                }
-                else
-                {
-                    /* Global value: store only one value */
-                    var = &m_ADIOS.DefineVariable<T>(name);
-                    if (var)
-                    {
-                        var->m_Data = std::vector<T>(1);
-                        var->m_Data[0] = *static_cast<T *>(vi->value);
-                    }
-                }
-            }
-            var->SetNSteps(vi->nsteps);
-            adios_free_varinfo(vi);
-        }
-        return var;
-    }
+#define declare_type(T)                                                        \
+    void DoScheduleRead(Variable<T> &variable, const T *values) final;         \
+    void DoScheduleRead(const std::string &variableName, const T *values) final;
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
     void ScheduleReadCommon(const std::string &name, const Dims &offs,
                             const Dims &ldims, const int fromStep,
@@ -293,4 +141,6 @@ private:
 
 } // end namespace adios
 
+#include "ADIOS1Reader.inl"
+
 #endif /* ADIOS2_ENGINE_ADIOS1_ADIOS1READER_H_ */
diff --git a/source/adios2/engine/adios1/ADIOS1Reader.inl b/source/adios2/engine/adios1/ADIOS1Reader.inl
new file mode 100644
index 0000000000000000000000000000000000000000..d6b3742faf314fadc5c42e0a23d8de7a84da74bf
--- /dev/null
+++ b/source/adios2/engine/adios1/ADIOS1Reader.inl
@@ -0,0 +1,133 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * ADIOS1Reader.inl
+ *
+ *  Created on: Jun 2, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ */
+
+#ifndef ADIOS2_ENGINE_ADIOS1_ADIOS1READER_INL_
+#define ADIOS2_ENGINE_ADIOS1_ADIOS1READER_INL_
+#ifndef ADIOS2_ENGINE_ADIOS1_ADIOS1READER_H_
+#error "Inline file should only be included from it's header, never on it's own"
+#endif
+
+namespace adios
+{
+
+template <class T>
+Variable<T> *ADIOS1Reader::InquireVariableCommon(const std::string &name,
+                                                 const bool readIn)
+{
+    // here read variable metadata (dimensions, type, etc.)...then create a
+    // Variable like below:
+    // Variable<T>& variable = m_ADIOS.DefineVariable<T>( m_Name + "/" +
+    // name, )
+    // return &variable; //return address if success
+    ADIOS_VARINFO *vi = adios_inq_var(m_fh, name.c_str());
+    adios::Variable<T> *var = nullptr;
+    if (vi != nullptr)
+    {
+        CheckADIOS1TypeCompatibility(name, GetType<T>(), vi->type); // throws
+
+        if (vi->ndim > 0)
+        {
+            Dims gdims = Uint64ArrayToSizetVector(vi->ndim, vi->dims);
+
+            bool joinedread = false;
+            if (gdims[0] == JoinedDim)
+            {
+                /* Joined Array */
+                adios_inq_var_blockinfo(m_fh, vi);
+                size_t joined_size = 0;
+                for (int i = 0; i < *vi->nblocks; i++)
+                {
+                    joined_size += vi->blockinfo[i].count[0];
+                }
+                gdims[0] = joined_size;
+                joinedread = true;
+            }
+
+            if (!vi->global)
+            {
+                /* Local array */
+                for (int j = 0; j < vi->ndim; ++j)
+                {
+                    gdims[j] = IrregularDim;
+                }
+            }
+            else
+            {
+                /* Check if dimensions change in time */
+                for (int step = 1; step < vi->nsteps; ++step)
+                {
+                    Dims dims =
+                        gdims; // GetGlobalDimsAtStep(vi, step, joinedread);
+                    for (int j = 0; j < vi->ndim; ++j)
+                    {
+                        if (dims[j] != gdims[j])
+                            gdims[j] = IrregularDim;
+                    }
+                }
+            }
+            var = &m_IO.DefineVariable<T>(name, gdims);
+            if (joinedread)
+            {
+                var->m_ReadAsJoined = true;
+            }
+        }
+        else /* Scalars */
+        {
+            /* scalar variable but global value or local value*/
+            std::string aname = name + "/ReadAsArray";
+            bool isLocalValue = false;
+            for (int i = 0; i < vi->nattrs; ++i)
+            {
+                if (!strcmp(m_fh->attr_namelist[vi->attr_ids[i]],
+                            aname.c_str()))
+                {
+                    isLocalValue = true;
+                }
+            }
+            if (isLocalValue)
+            {
+                /* Local Value */
+                bool changingDims = false;
+                for (int step = 1; step < vi->nsteps; ++step)
+                {
+                    if (vi->nblocks[step] != vi->nblocks[0])
+                        changingDims = true;
+                }
+                if (changingDims)
+                {
+                    var = &m_IO.DefineVariable<T>(name, {IrregularDim});
+                }
+                else
+                {
+                    var = &m_IO.DefineVariable<T>(
+                        name, {(unsigned int)vi->nblocks[0]});
+                }
+                var->m_ReadAsLocalValue = true;
+            }
+            else
+            {
+                /* Global value: store only one value */
+                var = &m_IO.DefineVariable<T>(name);
+                if (var)
+                {
+                    var->m_Data = std::vector<T>(1);
+                    var->m_Data[0] = *static_cast<T *>(vi->value);
+                }
+            }
+        }
+        var->m_AvailableSteps = vi->nsteps;
+        adios_free_varinfo(vi);
+    }
+    return var;
+}
+
+} // end namespace adios
+
+#endif /* ADIOS2_ENGINE_ADIOS1_ADIOS1READER_INL_ */
diff --git a/source/adios2/engine/adios1/ADIOS1Writer.cpp b/source/adios2/engine/adios1/ADIOS1Writer.cpp
index 71a6d5485b4e333b391717d92025239f04c8892d..e6290d9ee9a0332d0008b803db3111ca666d7195 100644
--- a/source/adios2/engine/adios1/ADIOS1Writer.cpp
+++ b/source/adios2/engine/adios1/ADIOS1Writer.cpp
@@ -7,15 +7,12 @@
  * It requires adios 1.x installed
  *
  *  Created on: Mar 27, 2017
- *      Author: pnb
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
  */
 
 #include "ADIOS1Writer.h"
 
-#include "adios2/core/adiosFunctions.h"
-
-extern int adios_verbose_level;
-extern int adios_errno;
+#include "adios2/helper/adiosFunctions.h"
 
 // Enable compatibility with ADIOS 1.10 adios_declare_group signature
 #if !ADIOS_VERSION_GE(1, 11, 0)
@@ -25,469 +22,45 @@ extern int adios_errno;
 namespace adios
 {
 
-ADIOS1Writer::ADIOS1Writer(ADIOS &adios, const std::string &name,
-                           const std::string accessMode, MPI_Comm mpiComm,
-                           const Method &method)
-: Engine(adios, "ADIOS1Writer", name, accessMode, mpiComm, method,
-         " ADIOS1Writer constructor (or call to ADIOS Open).\n"),
-  m_groupname{method.m_Name.c_str()}, m_filename{name.c_str()}, m_comm{mpiComm}
+ADIOS1Writer::ADIOS1Writer(IO &io, const std::string &name,
+                           const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("ADIOS1Writer", io, name, openMode, mpiComm),
+  m_ADIOS1(io.m_Name, name, mpiComm, io.m_DebugMode)
 {
+    m_EndMessage = " in call to ADIOS1Writer " + m_Name + " Open\n";
     Init();
-    adios_open(&m_adios_file, m_groupname, m_filename, accessMode.c_str(),
-               m_comm);
-    if (adios_errno == err_no_error)
-    {
-        m_IsFileOpen = true;
-    }
-}
-
-ADIOS1Writer::~ADIOS1Writer()
-{
-    if (m_IsFileOpen)
-    {
-        adios_close(m_adios_file);
-        m_IsFileOpen = false;
-    }
 }
 
 void ADIOS1Writer::Init()
 {
-    if (!m_initialized)
-    {
-        adios_init_noxml(m_comm);
-        m_initialized = true;
-    }
-    adios_declare_group(&m_adios_group, m_groupname, "", adios_stat_default);
-
     InitParameters();
     InitTransports();
+    m_ADIOS1.Open(m_OpenMode);
 }
 
-bool ADIOS1Writer::ReOpenAsNeeded()
-{
-    if (!m_IsFileOpen)
-    {
-        adios_open(&m_adios_file, m_groupname, m_filename, "a", m_comm);
-        if (adios_errno == err_no_error)
-        {
-            m_IsFileOpen = true;
-            adios_delete_vardefs(m_adios_group);
-        }
-    }
-    return m_IsFileOpen;
-}
-
-void ADIOS1Writer::DefineVariable(std::string name, VarClass varclass,
-                                  enum ADIOS_DATATYPES vartype,
-                                  std::string ldims, std::string gdims,
-                                  std::string offs)
-{
-    switch (varclass)
-    {
-    case VarClass::GlobalValue:
-        adios_define_var(m_adios_group, name.c_str(), "", vartype, "", "", "");
-        break;
-    case VarClass::LocalValue:
-        adios_define_var(m_adios_group, name.c_str(), "", vartype, "", "", "");
-        adios_define_attribute(m_adios_group, "ReadAsArray", name.c_str(),
-                               adios_byte, "1", nullptr);
-        break;
-    case VarClass::GlobalArray:
-    case VarClass::LocalArray:
-    case VarClass::JoinedArray:
-        adios_define_var(m_adios_group, name.c_str(), "", vartype,
-                         ldims.c_str(), gdims.c_str(), offs.c_str());
-        break;
-    }
-}
-
-void ADIOS1Writer::WriteVariable(std::string name, VarClass varclass,
-                                 enum ADIOS_DATATYPES vartype,
-                                 std::string ldims, std::string gdims,
-                                 std::string offs, const void *values)
-{
-    if (ReOpenAsNeeded())
-    {
-        DefineVariable(name, varclass, vartype, ldims, gdims, offs);
-        adios_write(m_adios_file, name.c_str(), values);
-    }
-}
-
-static std::string DimsToCSV_LocalAware(const std::vector<std::size_t> &dims)
-{
-    std::string dimsCSV;
-    bool localVar = false;
-
-    for (const auto dim : dims)
-    {
-        dimsCSV += std::to_string(dim) + ",";
-        if (dim == JoinedDim || dim == IrregularDim)
-            localVar = true;
-    }
-
-    if (dimsCSV.empty() == false)
-    {
-        dimsCSV.pop_back();
-    }
-
-    /*if (localVar)
-    {
-        dimsCSV.clear();
-    }*/
-
-    return dimsCSV;
-}
-
-void ADIOS1Writer::Write(Variable<char> &variable, const char *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_byte,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<unsigned char> &variable,
-                         const unsigned char *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_unsigned_byte,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<short> &variable, const short *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_short,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<unsigned short> &variable,
-                         const unsigned short *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_unsigned_short,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<int> &variable, const int *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_integer,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<unsigned int> &variable,
-                         const unsigned int *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_unsigned_integer,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<long int> &variable, const long int *values)
-{
-    enum ADIOS_DATATYPES type =
-        adios_integer; // long int is usually 4 bytes which is adios_integer
-    if (sizeof(long int) == 8)
-    {
-        type = adios_long;
+#define declare_type(T)                                                        \
+    void ADIOS1Writer::DoWrite(Variable<T> &variable, const T *values)         \
+    {                                                                          \
+        m_ADIOS1.WriteVariable(variable.m_Name, variable.m_ShapeID,            \
+                               variable.m_Count, variable.m_Shape,             \
+                               variable.m_Start, values);                      \
     }
-    WriteVariable(variable.m_Name, variable.m_VarClass, type,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<unsigned long int> &variable,
-                         const unsigned long int *values)
-{
-    enum ADIOS_DATATYPES type =
-        adios_unsigned_integer; // long int is usually 4 bytes
-    if (sizeof(long int) == 8)
-    {
-        type = adios_unsigned_long;
-    }
-    WriteVariable(variable.m_Name, variable.m_VarClass, type,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<long long int> &variable,
-                         const long long int *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_long,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<unsigned long long int> &variable,
-                         const unsigned long long int *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_unsigned_long,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<float> &variable, const float *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_real,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<double> &variable, const double *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_double,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<long double> &variable,
-                         const long double *values)
-{
-    /* TODO: This is faulty: adios_long_double expects 16 bytes per elements,
-     * but
-     * long double is compiler dependent */
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_long_double,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<std::complex<float>> &variable,
-                         const std::complex<float> *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_complex,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<std::complex<double>> &variable,
-                         const std::complex<double> *values)
-{
-    WriteVariable(variable.m_Name, variable.m_VarClass, adios_double_complex,
-                  DimsToCSV_LocalAware(variable.m_Count),
-                  DimsToCSV_LocalAware(variable.m_Shape),
-                  DimsToCSV_LocalAware(variable.m_Start), values);
-}
-
-void ADIOS1Writer::Write(Variable<std::complex<long double>> &variable,
-                         const std::complex<long double> *values)
-{
-    throw std::invalid_argument(
-        "ERROR: Adios 1.x does not support complex<long "
-        "double> type, so it cannot write variable " +
-        variable.m_Name + "\n");
-}
-
-void ADIOS1Writer::Write(VariableCompound &variable, const void *values)
-{
-    throw std::invalid_argument("ERROR: Adios 1.x does not support compound "
-                                "types, so it cannot write variable " +
-                                variable.m_Name + "\n");
-}
-
-// String version
-void ADIOS1Writer::Write(const std::string &variableName, const char *values)
-{
-    Write(m_ADIOS.GetVariable<char>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const unsigned char *values)
-{
-    Write(m_ADIOS.GetVariable<unsigned char>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName, const short *values)
-{
-    Write(m_ADIOS.GetVariable<short>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const unsigned short *values)
-{
-    Write(m_ADIOS.GetVariable<unsigned short>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName, const int *values)
-{
-    Write(m_ADIOS.GetVariable<int>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const unsigned int *values)
-{
-    Write(m_ADIOS.GetVariable<unsigned int>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const long int *values)
-{
-    Write(m_ADIOS.GetVariable<long int>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const unsigned long int *values)
-{
-    Write(m_ADIOS.GetVariable<unsigned long int>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const long long int *values)
-{
-    Write(m_ADIOS.GetVariable<long long int>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const unsigned long long int *values)
-{
-    Write(m_ADIOS.GetVariable<unsigned long long int>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName, const float *values)
-{
-    Write(m_ADIOS.GetVariable<float>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName, const double *values)
-{
-    Write(m_ADIOS.GetVariable<double>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const long double *values)
-{
-    Write(m_ADIOS.GetVariable<long double>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const std::complex<float> *values)
-{
-    Write(m_ADIOS.GetVariable<std::complex<float>>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const std::complex<double> *values)
-{
-    Write(m_ADIOS.GetVariable<std::complex<double>>(variableName), values);
-}
-
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const std::complex<long double> *values)
-{
-    Write(m_ADIOS.GetVariable<std::complex<long double>>(variableName), values);
-}
+ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
-void ADIOS1Writer::Write(const std::string &variableName,
-                         const void *values) // Compound type
-{
-    throw std::invalid_argument("ERROR: Adios 1.x does not support compound "
-                                "types, so it cannot write variable " +
-                                variableName + "\n");
-}
+void ADIOS1Writer::Advance(const float /*timeout_sec*/) { m_ADIOS1.Advance(); }
 
-void ADIOS1Writer::Advance(const float /*timeout_sec*/)
-{
-    if (m_IsFileOpen)
-    {
-        adios_close(m_adios_file);
-        m_IsFileOpen = false;
-    }
-}
-
-void ADIOS1Writer::Close(const int transportIndex)
-{
-    if (m_IsFileOpen)
-    {
-        adios_close(m_adios_file);
-        m_IsFileOpen = false;
-    }
-}
+void ADIOS1Writer::Close(const int transportIndex) { m_ADIOS1.Close(); }
 
 // PRIVATE FUNCTIONS
 void ADIOS1Writer::InitParameters()
 {
-    auto itMaxBufferSize = m_Method.m_Parameters.find("max_size_MB");
-    if (itMaxBufferSize != m_Method.m_Parameters.end())
-    {
-        adios_set_max_buffer_size(std::stoul(itMaxBufferSize->second));
-    }
-
-    auto itVerbosity = m_Method.m_Parameters.find("verbose");
-    if (itVerbosity != m_Method.m_Parameters.end())
-    {
-        int verbosity = std::stoi(itVerbosity->second);
-        if (m_DebugMode == true)
-        {
-            if (verbosity < 0 || verbosity > 5)
-                throw std::invalid_argument(
-                    "ERROR: Method verbose argument must be an "
-                    "integer in the range [0,5], in call to "
-                    "Open or Engine constructor\n");
-        }
-        adios_verbose_level = verbosity;
-    }
+    m_ADIOS1.InitParameters(m_IO.m_Parameters);
 }
 
 void ADIOS1Writer::InitTransports()
 {
-    if (m_DebugMode == true)
-    {
-        if (TransportNamesUniqueness() == false)
-        {
-            throw std::invalid_argument(
-                "ERROR: two transports of the same kind (e.g file IO) "
-                "can't have the same name, modify with name= in Method "
-                "AddTransport\n");
-        }
-    }
-
-    for (const auto &parameters : m_Method.m_TransportParameters)
-    {
-        auto itTransport = parameters.find("transport");
-
-        if (itTransport->second == "file" || itTransport->second == "File")
-        {
-            auto itLibrary = parameters.find("library");
-            if (itLibrary == parameters.end() ||
-                itLibrary->second == "POSIX") // use default POSIX
-            {
-                adios_select_method(m_adios_group, "POSIX", "", "");
-            }
-            else if (itLibrary->second == "MPI_File" ||
-                     itLibrary->second == "MPI-IO")
-            {
-                adios_select_method(m_adios_group, "MPI", "", "");
-            }
-            else
-            {
-                if (m_DebugMode == true)
-                    throw std::invalid_argument(
-                        "ERROR: file transport library " + itLibrary->second +
-                        " not supported, in " + m_Name + m_EndMessage);
-            }
-        }
-        else
-        {
-            if (m_DebugMode == true)
-                throw std::invalid_argument(
-                    "ERROR: transport " + itTransport->second +
-                    " (you mean File?) not supported, in " + m_Name +
-                    m_EndMessage);
-        }
-    }
+    m_ADIOS1.InitTransports(m_IO.m_TransportsParameters);
 }
 
 } // end namespace adios
diff --git a/source/adios2/engine/adios1/ADIOS1Writer.h b/source/adios2/engine/adios1/ADIOS1Writer.h
index 8a932da8e378788f789feab6242a255d47789152..6f8e9704e6ff7fd98759dbd3699c243da78c092e 100644
--- a/source/adios2/engine/adios1/ADIOS1Writer.h
+++ b/source/adios2/engine/adios1/ADIOS1Writer.h
@@ -4,10 +4,10 @@
  *
  * ADIOS1Writer.h
  * Class to write files using old adios 1.x library.
- * It requires adios 1.x installed
+ * It requires at least adios 1.12.0 installed
  *
  *  Created on: Mar 27, 2017
- *      Author: pnb
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
  */
 
 #ifndef ADIOS2_ENGINE_ADIOS1_ADIOS1WRITER_H_
@@ -15,18 +15,7 @@
 
 #include "adios2/ADIOSConfig.h"
 #include "adios2/core/Engine.h"
-
-// Fake out the include guard from ADIOS1's mpidummy.h to prevent it from
-// getting included
-#ifdef _NOMPI
-#define __MPI_DUMMY_H__
-#define MPI_Comm int
-#endif
-#include <adios.h>
-#ifdef _NOMPI
-#undef MPI_Comm
-#undef __MPI_DUMMY_H__
-#endif
+#include "adios2/toolkit/interop/adios1/ADIOS1Common.h"
 
 namespace adios
 {
@@ -43,60 +32,12 @@ public:
      * @param method
      * @param debugMode
      */
-    ADIOS1Writer(ADIOS &adios, const std::string &name,
-                 const std::string accessMode, MPI_Comm mpiComm,
-                 const Method &method);
-
-    ~ADIOS1Writer();
+    ADIOS1Writer(IO &adios, const std::string &name, const OpenMode openMode,
+                 MPI_Comm mpiComm);
 
-    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(VariableCompound &variable, const void *values);
+    ~ADIOS1Writer() = default;
 
-    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 Write(const std::string &variableName, const void *values);
-
-    void Advance(const float timeout_sec = 0.);
+    void Advance(const float timeoutSeconds = 0.) final;
 
     /**
      * Closes a single transport or all transports
@@ -106,35 +47,19 @@ public:
      * latter
      * is bounds-checked.
      */
-    void Close(const int transportIndex = -1);
+    void Close(const int transportIndex = -1) final;
 
 private:
-    const char *m_groupname; ///< ADIOS1 group name created from the method's
-                             /// name. Must be a unique group name.
-    const char *m_filename;  ///< Save file name from constructor for Advance()
-                             /// when we re-open in ADIOS1
-    MPI_Comm m_comm; ///< Save MPI communicator from constructor for Advance()
-                     /// when we re-open in ADIOS1
-
-    bool m_initialized = false; ///< set to true after calling adios_init()
-    int64_t m_adios_file = 0;  ///< ADIOS1 file handler returned by adios_open()
-    int64_t m_adios_group = 0; ///< ADIOS1 group pointer that holds the ADIOS1
-                               /// variable definitions
-    bool m_IsFileOpen = false;
+    interop::ADIOS1Common m_ADIOS1;
 
-    void Init();
-    // these are unused yet, keeping here to see if we need them
-    void InitParameters();
-    void InitTransports();
-    void InitProcessGroup();
+    void Init() final;
+    void InitParameters() final;
+    void InitTransports() final;
 
-    bool ReOpenAsNeeded(); // return true if file is open or reopened
-    void DefineVariable(std::string name, VarClass varclass,
-                        enum ADIOS_DATATYPES vartype, std::string ldims,
-                        std::string gdims, std::string offs);
-    void WriteVariable(std::string name, VarClass varclass,
-                       enum ADIOS_DATATYPES vartype, std::string ldims,
-                       std::string gdims, std::string offs, const void *values);
+#define declare_type(T)                                                        \
+    void DoWrite(Variable<T> &variable, const T *values) final;
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 };
 
 } // end namespace adios
diff --git a/source/adios2/engine/bp/BPFileReader.cpp b/source/adios2/engine/bp/BPFileReader.cpp
index d74d94adac0ab80f5b2a5cef3b0cfb56803b6b7a..47daed9e45b8cfc89b54e22fd6e8ec673b7b0c96 100644
--- a/source/adios2/engine/bp/BPFileReader.cpp
+++ b/source/adios2/engine/bp/BPFileReader.cpp
@@ -5,32 +5,45 @@
  * BPFileReader.cpp
  *
  *  Created on: Feb 27, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "BPFileReader.h"
 
-#include "adios2/core/Support.h"
-#include "adios2/core/adiosFunctions.h"           // CSVToVector
-#include "adios2/transport/file/FStream.h"        // uses C++ fstream
-#include "adios2/transport/file/FileDescriptor.h" // uses POSIX
-#include "adios2/transport/file/FilePointer.h"    // uses C FILE*
+#include "adios2/helper/adiosFunctions.h" // CSVToVector
 
 namespace adios
 {
 
-BPFileReader::BPFileReader(ADIOS &adios, const std::string &name,
-                           const std::string accessMode, MPI_Comm mpiComm,
-                           const Method &method)
-: Engine(adios, "BPFileReader", name, accessMode, mpiComm, method,
-         " BPFileReader constructor (or call to ADIOS Open).\n"),
-  m_Heap(m_DebugMode)
+BPFileReader::BPFileReader(IO &io, const std::string &name,
+                           const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("BPFileReader", io, name, openMode, mpiComm)
 {
     Init();
 }
 
-Variable<void> *BPFileReader::InquireVariable(const std::string & /*name*/,
-                                              const bool /*readIn*/)
+void BPFileReader::Close(const int /*transportIndex*/) {}
+
+// PRIVATE
+void BPFileReader::Init()
+{
+    if (m_DebugMode)
+    {
+        if (m_OpenMode != OpenMode::Read)
+        {
+            throw std::invalid_argument(
+                "ERROR: BPFileReader only supports OpenMode::r from" + m_Name +
+                " " + m_EndMessage);
+        }
+    }
+
+    InitTransports();
+}
+
+void BPFileReader::InitTransports() {}
+
+VariableBase *BPFileReader::InquireVariableUnknown(const std::string & /*name*/,
+                                                   const bool /*readIn*/)
 {
     // not yet implemented
     return nullptr;
@@ -140,92 +153,4 @@ BPFileReader::InquireVariableCompound(const std::string & /*name*/,
     return nullptr;
 }
 
-void BPFileReader::Close(const int /*transportIndex*/) {}
-
-// PRIVATE
-void BPFileReader::Init()
-{
-    if (m_DebugMode == true)
-    {
-        if (m_AccessMode != "r" && m_AccessMode != "read")
-        {
-            throw std::invalid_argument(
-                "ERROR: BPFileReader doesn't support access mode " +
-                m_AccessMode +
-                ", in call to ADIOS Open or BPFileReader constructor\n");
-        }
-    }
-
-    InitTransports();
-}
-
-void BPFileReader::InitTransports() // maybe move this?
-{
-    if (m_DebugMode == true)
-    {
-        if (TransportNamesUniqueness() == false)
-        {
-            throw std::invalid_argument(
-                "ERROR: two transports of the same kind (e.g file IO) "
-                "can't have the same name, modify with name= in Method "
-                "AddTransport\n");
-        }
-    }
-
-    for (const auto &parameters : m_Method.m_TransportParameters)
-    {
-        auto itTransport = parameters.find("transport");
-        if (itTransport->second == "file" || itTransport->second == "File")
-        {
-            auto itLibrary = parameters.find("library");
-            if (itLibrary == parameters.end() ||
-                itLibrary->second == "POSIX") // use default POSIX
-            {
-                auto file = std::make_shared<transport::FileDescriptor>(
-                    m_MPIComm, m_DebugMode);
-                // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file );
-                m_Transports.push_back(std::move(file));
-            }
-            else if (itLibrary->second == "FILE*" ||
-                     itLibrary->second == "stdio.h")
-            {
-                auto file = std::make_shared<transport::FilePointer>(
-                    m_MPIComm, m_DebugMode);
-                // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file );
-                m_Transports.push_back(std::move(file));
-            }
-            else if (itLibrary->second == "fstream" ||
-                     itLibrary->second == "std::fstream")
-            {
-                auto file = std::make_shared<transport::FStream>(m_MPIComm,
-                                                                 m_DebugMode);
-                // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file );
-                m_Transports.push_back(std::move(file));
-            }
-            else if (itLibrary->second == "MPI-IO")
-            {
-            }
-            else
-            {
-                if (m_DebugMode == true)
-                {
-                    throw std::invalid_argument(
-                        "ERROR: file transport library " + itLibrary->second +
-                        " not supported, in " + m_Name + m_EndMessage);
-                }
-            }
-        }
-        else
-        {
-            if (m_DebugMode == true)
-            {
-                throw std::invalid_argument(
-                    "ERROR: transport " + itTransport->second +
-                    " (you mean File?) not supported, in " + m_Name +
-                    m_EndMessage);
-            }
-        }
-    }
-}
-
 } // end namespace adios
diff --git a/source/adios2/engine/bp/BPFileReader.h b/source/adios2/engine/bp/BPFileReader.h
index 6f36b4f336810ec97aff3ff6b437c0a221a7092c..5302d485425532ad62949385ff14ab96cfc35a09 100644
--- a/source/adios2/engine/bp/BPFileReader.h
+++ b/source/adios2/engine/bp/BPFileReader.h
@@ -2,19 +2,16 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * BPReader.h
+ * BPFileReader.h
  *
  *  Created on: Feb 27, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_ENGINE_BP_BPFILEREADER_H_
 #define ADIOS2_ENGINE_BP_BPFILEREADER_H_
 
-#include <iostream> //this must go away
-
 #include "adios2/ADIOSConfig.h"
-#include "adios2/capsule/heap/STLVector.h"
 #include "adios2/core/Engine.h"
 
 namespace adios
@@ -25,24 +22,23 @@ class BPFileReader : 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
-     * @param hostLanguage
+     *
      */
-    BPFileReader(ADIOS &adios, const std::string &name,
-                 const std::string accessMode, MPI_Comm mpiComm,
-                 const Method &method);
+    BPFileReader(IO &io, const std::string &name, const OpenMode openMode,
+                 MPI_Comm mpiComm);
 
     virtual ~BPFileReader() = default;
 
-    Variable<void> *InquireVariable(const std::string &variableName,
-                                    const bool readIn = true);
+    void Close(const int transportIndex = -1);
+
+private:
+    void Init(); ///< calls InitCapsules and InitTransports based on Method,
+                 /// called from constructor
+
+    void InitTransports(); ///< from Transports
+
+    VariableBase *InquireVariableUnknown(const std::string &variableName,
+                                         const bool readIn = true);
 
     Variable<char> *InquireVariableChar(const std::string &variableName,
                                         const bool readIn = true);
@@ -109,24 +105,6 @@ public:
     VariableCompound *InquireVariableCompound(const std::string &variableName,
                                               const bool readIn = true);
 
-    void Close(const int transportIndex = -1);
-
-private:
-    capsule::STLVector
-        m_Heap; ///< heap capsule, contains data and metadata buffers
-    // format::BP1Writer m_BP1Writer; ///< format object will provide the
-    // required
-    // BP functionality to be applied on m_Buffer and m_Transports
-
-    void Init(); ///< calls InitCapsules and InitTransports based on Method,
-                 /// called from constructor
-
-    void InitTransports(); ///< from Transports
-
-    std::string
-    GetMdtmParameter(const std::string parameter,
-                     const std::map<std::string, std::string> &mdtmParameters);
-
     template <class T>
     Variable<T> *InquireVariableCommon(const std::string &name,
                                        const bool readIn)
diff --git a/source/adios2/engine/bp/BPFileWriter.cpp b/source/adios2/engine/bp/BPFileWriter.cpp
index 314519912b4aa3f961046415dad7eae99b43534d..b397681b336dc7a81790bd5b6b9758b2b3c3605c 100644
--- a/source/adios2/engine/bp/BPFileWriter.cpp
+++ b/source/adios2/engine/bp/BPFileWriter.cpp
@@ -5,28 +5,30 @@
  * BPFileWriter.cpp
  *
  *  Created on: Dec 19, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "BPFileWriter.h"
+#include "BPFileWriter.tcc"
 
-#include <utility>
+#include <iostream>
 
-#include "adios2/ADIOS.h"
-#include "adios2/transport/file/FStream.h"
-#include "adios2/transport/file/FileDescriptor.h"
-#include "adios2/transport/file/FilePointer.h"
+#include "adios2/ADIOSMPI.h"
+#include "adios2/core/IO.h"
+#include "adios2/helper/adiosFunctions.h" //CheckIndexRange
+#include "adios2/toolkit/transport/file/FileDescriptor.h"
+#include "adios2/toolkit/transport/file/FilePointer.h"
+#include "adios2/toolkit/transport/file/FileStream.h"
 
 namespace adios
 {
 
-BPFileWriter::BPFileWriter(ADIOS &adios, const std::string &name,
-                           const std::string accessMode, MPI_Comm mpiComm,
-                           const Method &method)
-: Engine(adios, "BPFileWriter", name, accessMode, mpiComm, method,
-         " BPFileWriter constructor (or call to ADIOS Open).\n"),
-  m_BP1Writer(mpiComm, m_DebugMode)
+BPFileWriter::BPFileWriter(IO &io, const std::string &name,
+                           const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("BPFileWriter", io, name, openMode, mpiComm),
+  m_BP1Writer(mpiComm, m_DebugMode), m_TransportsManager(mpiComm, m_DebugMode)
 {
+    m_EndMessage = " in call to IO Open BPFileWriter " + m_Name + "\n";
     Init();
 }
 
@@ -36,244 +38,56 @@ void BPFileWriter::Init()
 {
     InitParameters();
     InitTransports();
-    InitProcessGroup();
+    InitBPBuffer();
 }
 
-void BPFileWriter::Write(Variable<char> &variable, const char *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<unsigned char> &variable,
-                         const unsigned char *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<short> &variable, const short *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<unsigned short> &variable,
-                         const unsigned short *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<int> &variable, const int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<unsigned int> &variable,
-                         const unsigned int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<long int> &variable, const long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<unsigned long int> &variable,
-                         const unsigned long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<long long int> &variable,
-                         const long long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<unsigned long long int> &variable,
-                         const unsigned long long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<float> &variable, const float *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<double> &variable, const double *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<long double> &variable,
-                         const long double *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<std::complex<float>> &variable,
-                         const std::complex<float> *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<std::complex<double>> &variable,
-                         const std::complex<double> *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(Variable<std::complex<long double>> &variable,
-                         const std::complex<long double> *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void BPFileWriter::Write(VariableCompound & /*variable*/,
-                         const void * /*values*/)
-{
-}
-
-// String version
-void BPFileWriter::Write(const std::string &variableName, const char *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<char>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const unsigned char *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned char>(variableName),
-                        values);
-}
-
-void BPFileWriter::Write(const std::string &variableName, const short *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<short>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const unsigned short *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned short>(variableName),
-                        values);
-}
-
-void BPFileWriter::Write(const std::string &variableName, const int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<int>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const unsigned int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned int>(variableName),
-                        values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const long int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<long int>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const unsigned long int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned long int>(variableName),
-                        values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const long long int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<long long int>(variableName),
-                        values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const unsigned long long int *values)
-{
-    WriteVariableCommon(
-        m_ADIOS.GetVariable<unsigned long long int>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName, const float *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<float>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName, const double *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<double>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const long double *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<long double>(variableName), values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const std::complex<float> *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<std::complex<float>>(variableName),
-                        values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const std::complex<double> *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<std::complex<double>>(variableName),
-                        values);
-}
-
-void BPFileWriter::Write(const std::string &variableName,
-                         const std::complex<long double> *values)
-{
-    WriteVariableCommon(
-        m_ADIOS.GetVariable<std::complex<long double>>(variableName), values);
-}
+#define declare_type(T)                                                        \
+    void BPFileWriter::DoWrite(Variable<T> &variable, const T *values)         \
+    {                                                                          \
+        DoWriteCommon(variable, values);                                       \
+    }
+ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
-void BPFileWriter::Write(const std::string & /*variableName*/,
-                         const void * /*values*/) // Compound type
+void BPFileWriter::Advance(const float /*timeout_sec*/)
 {
+    m_BP1Writer.Advance();
 }
 
-void BPFileWriter::Advance(float /*timeout_sec*/) { m_BP1Writer.Advance(); }
-
 void BPFileWriter::Close(const int transportIndex)
 {
-    CheckTransportIndex(transportIndex);
-    if (transportIndex == -1)
+    if (m_DebugMode)
     {
-        for (auto &transport : m_Transports)
+        if (!m_TransportsManager.CheckTransportIndex(transportIndex))
         {
-            // false: not using aggregation for now
-            m_BP1Writer.Close(*transport, m_IsFirstClose, false);
+            auto transportsSize = m_TransportsManager.m_Transports.size();
+            throw std::invalid_argument(
+                "ERROR: transport index " + std::to_string(transportIndex) +
+                " outside range, -1 (default) to " +
+                std::to_string(transportsSize - 1) + ", in call to Close\n");
         }
     }
-    else
-    {
-        // false: not using aggregation for now
-        m_BP1Writer.Close(*m_Transports[transportIndex], m_IsFirstClose, false);
-    }
 
-    if (m_BP1Writer.m_MetadataSet.Log.IsActive == true)
+    // close bp buffer by flattening data and metadata
+    m_BP1Writer.Close();
+    // send data to corresponding transport
+    m_TransportsManager.CloseFiles(transportIndex,
+                                   m_BP1Writer.m_HeapBuffer.m_Data.data(),
+                                   m_BP1Writer.m_HeapBuffer.m_DataPosition);
+
+    if (m_BP1Writer.m_Profiler.IsActive)
     {
-        bool allClose = true;
-        for (auto &transport : m_Transports)
+        // aggregate and write profiling.log
+        if (m_TransportsManager.AllTransportsClosed())
         {
-            if (transport->m_IsOpen == true)
-            {
-                allClose = false;
-                break;
-            }
-        }
+            auto transportTypes = m_TransportsManager.GetTransportsTypes();
+            auto transportProfilers =
+                m_TransportsManager.GetTransportsProfilers();
 
-        if (allClose == true) // aggregate and write profiling.log
-        {
-            m_BP1Writer.WriteProfilingLogFile(m_Name, m_RankMPI, m_Transports);
+            const std::string log(m_BP1Writer.GetRankProfilingLog(
+                transportTypes, transportProfilers));
+            // TODO profiling.log
+            // m_BP1Writer.m_BP1Aggregator.WriteProfilingLog( )
         }
     }
 }
@@ -281,277 +95,41 @@ void BPFileWriter::Close(const int transportIndex)
 // PRIVATE FUNCTIONS
 void BPFileWriter::InitParameters()
 {
-    auto itProfile = m_Method.m_Parameters.find("profile_units");
-    if (itProfile != m_Method.m_Parameters.end())
-    {
-        auto &log = m_BP1Writer.m_MetadataSet.Log;
-
-        if (itProfile->second == "mus" || itProfile->second == "microseconds")
-        {
-            log.Timers.emplace_back("buffering", Support::Resolutions::mus);
-        }
-        else if (itProfile->second == "ms" ||
-                 itProfile->second == "milliseconds")
-        {
-            log.Timers.emplace_back("buffering", Support::Resolutions::ms);
-        }
-        else if (itProfile->second == "s" || itProfile->second == "seconds")
-        {
-            log.Timers.emplace_back("buffering", Support::Resolutions::s);
-        }
-        else if (itProfile->second == "min" || itProfile->second == "minutes")
-        {
-            log.Timers.emplace_back("buffering", Support::Resolutions::m);
-        }
-        else if (itProfile->second == "h" || itProfile->second == "hours")
-        {
-            log.Timers.emplace_back("buffering", Support::Resolutions::h);
-        }
-        else
-        {
-            if (m_DebugMode == true)
-            {
-                throw std::invalid_argument(
-                    "ERROR: Method profile_buffering_units "
-                    "argument must be mus, ms, s, min or h, in "
-                    "call to Open or Engine constructor\n");
-            }
-        }
-
-        log.IsActive = true;
-    }
-
-    auto itGrowthFactor = m_Method.m_Parameters.find("buffer_growth");
-    if (itGrowthFactor != m_Method.m_Parameters.end())
-    {
-        const float growthFactor = std::stof(itGrowthFactor->second);
-        if (m_DebugMode == true)
-        {
-            if (growthFactor == 1.f)
-            {
-                throw std::invalid_argument("ERROR: buffer_growth argument "
-                                            "can't be less of equal than 1, "
-                                            "in " +
-                                            m_EndMessage + "\n");
-            }
-        }
-
-        m_BP1Writer.m_GrowthFactor = growthFactor;
-    }
-
-    auto itMaxBufferSize = m_Method.m_Parameters.find("max_size_MB");
-    if (itMaxBufferSize != m_Method.m_Parameters.end())
-    {
-        if (m_DebugMode == true)
-        {
-            if (m_GrowthFactor <= 1.f)
-            {
-                throw std::invalid_argument(
-                    "ERROR: Method buffer_growth argument "
-                    "can't be less of equal than 1, in " +
-                    m_EndMessage + "\n");
-            }
-        }
-
-        // convert from MB to bytes
-        m_BP1Writer.m_MaxBufferSize =
-            std::stoul(itMaxBufferSize->second) * 1048576;
-    }
-
-    auto itVerbosity = m_Method.m_Parameters.find("verbose");
-    if (itVerbosity != m_Method.m_Parameters.end())
-    {
-        int verbosity = std::stoi(itVerbosity->second);
-        if (m_DebugMode == true)
-        {
-            if (verbosity < 0 || verbosity > 5)
-            {
-                throw std::invalid_argument(
-                    "ERROR: Method verbose argument must be an "
-                    "integer in the range [0,5], in call to "
-                    "Open or Engine constructor\n");
-            }
-        }
-        m_BP1Writer.m_Verbosity = verbosity;
-    }
+    m_BP1Writer.InitParameters(m_IO.m_Parameters);
 }
 
 void BPFileWriter::InitTransports()
 {
-    if (m_DebugMode == true)
+    // TODO need to add support for aggregators here later
+    if (m_IO.m_TransportsParameters.empty())
     {
-        if (TransportNamesUniqueness() == false)
-        {
-            throw std::invalid_argument(
-                "ERROR: two transports of the same kind (e.g file IO) "
-                "can't have the same name, modify with name= in Method "
-                "AddTransport\n");
-        }
+        Params defaultTransportParameters;
+        defaultTransportParameters["transport"] = "File";
+        m_IO.m_TransportsParameters.push_back(defaultTransportParameters);
     }
 
-    bool setBuffer = false;
-
-    for (const auto &parameters : m_Method.m_TransportParameters)
-    {
-        auto itProfile = parameters.find("profile_units");
-        bool doProfiling = false;
-        // default is seconds for this engine
-        Support::Resolutions resolution = Support::Resolutions::s;
-        if (itProfile != parameters.end())
-        {
-            if (itProfile->second == "mus" ||
-                itProfile->second == "microseconds")
-            {
-                resolution = Support::Resolutions::mus;
-            }
-            else if (itProfile->second == "ms" ||
-                     itProfile->second == "milliseconds")
-            {
-                resolution = Support::Resolutions::ms;
-            }
-            else if (itProfile->second == "s" || itProfile->second == "seconds")
-            {
-                resolution = Support::Resolutions::s;
-            }
-            else if (itProfile->second == "min" ||
-                     itProfile->second == "minutes")
-            {
-                resolution = Support::Resolutions::m;
-            }
-            else if (itProfile->second == "h" || itProfile->second == "hours")
-            {
-                resolution = Support::Resolutions::h;
-            }
-            else
-            {
-                if (m_DebugMode == true)
-                {
-                    throw std::invalid_argument(
-                        "ERROR: Transport profile_units argument "
-                        "must be mus, ms, s, min or h " +
-                        m_EndMessage);
-                }
-            }
-            doProfiling = true;
-        }
-
-        auto itTransport = parameters.find("transport");
-
-        if (itTransport->second == "file" || itTransport->second == "File")
-        {
-            auto itLibrary = parameters.find("library");
-            if (itLibrary == parameters.end() ||
-                itLibrary->second == "POSIX") // use default POSIX
-            {
-                auto file = std::make_shared<transport::FileDescriptor>(
-                    m_MPIComm, m_DebugMode);
-                if (doProfiling == true)
-                {
-                    file->InitProfiler(m_AccessMode, resolution);
-                }
-
-                m_BP1Writer.OpenRankFiles(m_Name, m_AccessMode, *file);
-                m_Transports.push_back(std::move(file));
-                setBuffer = true;
-            }
-            else if (itLibrary->second == "FILE*" ||
-                     itLibrary->second == "stdio")
-            {
-                auto file = std::make_shared<transport::FilePointer>(
-                    m_MPIComm, m_DebugMode);
-                if (doProfiling == true)
-                {
-                    file->InitProfiler(m_AccessMode, resolution);
-                }
-
-                m_BP1Writer.OpenRankFiles(m_Name, m_AccessMode, *file);
-                m_Transports.push_back(std::move(file));
-                setBuffer = true;
-            }
-            else if (itLibrary->second == "fstream" ||
-                     itLibrary->second == "std::fstream")
-            {
-                auto file = std::make_shared<transport::FStream>(m_MPIComm,
-                                                                 m_DebugMode);
-
-                if (doProfiling == true)
-                {
-                    file->InitProfiler(m_AccessMode, resolution);
-                }
+    // Names are std::vector<std::string>
+    auto transportsNames = m_TransportsManager.GetFilesBaseNames(
+        m_Name, m_IO.m_TransportsParameters);
+    auto bpBaseNames = m_BP1Writer.GetBPBaseNames(transportsNames);
+    auto bpNames = m_BP1Writer.GetBPNames(bpBaseNames);
 
-                m_BP1Writer.OpenRankFiles(m_Name, m_AccessMode, *file);
-                m_Transports.push_back(std::move(file));
-                setBuffer = true;
-            }
-            else if (itLibrary->second == "MPI_File" ||
-                     itLibrary->second == "MPI-IO")
-            {
-            }
-            else
-            {
-                if (m_DebugMode == true)
-                {
-                    throw std::invalid_argument(
-                        "ERROR: file transport library " + itLibrary->second +
-                        " not supported, in " + m_Name + m_EndMessage);
-                }
-            }
-        }
-        else
-        {
-            if (m_DebugMode == true)
-            {
-                throw std::invalid_argument(
-                    "ERROR: transport " + itTransport->second +
-                    " (you mean File?) not supported, in " + m_Name +
-                    m_EndMessage);
-            }
-        }
-    }
-
-    if (setBuffer == false)
-    {
-        if (m_DebugMode == true)
-        {
-            throw std::invalid_argument(
-                "ERROR: file transport not declared in Method "
-                "need call to Method.AddTransport, in " +
-                m_Name + m_EndMessage);
-        }
-    }
-
-    // initial size is 16KB, memory is initialized to zero
-    m_BP1Writer.m_Heap.ResizeData(16777216);
+    m_TransportsManager.OpenFiles(bpBaseNames, bpNames, m_OpenMode,
+                                  m_IO.m_TransportsParameters,
+                                  m_BP1Writer.m_Profiler.IsActive);
 }
 
-void BPFileWriter::InitProcessGroup()
+void BPFileWriter::InitBPBuffer()
 {
-    if (m_BP1Writer.m_MetadataSet.Log.IsActive == true)
+    if (m_OpenMode == OpenMode::Append)
     {
-        m_BP1Writer.m_MetadataSet.Log.Timers[0].SetInitialTime();
+        // TODO: Get last pg timestep and update timestep counter in
     }
-
-    if (m_AccessMode == "a")
-    {
-        // Get last pg timestep and update timestep counter in
-        // format::BP1MetadataSet
-    }
-
-    WriteProcessGroupIndex();
-
-    if (m_BP1Writer.m_MetadataSet.Log.IsActive == true)
+    else
     {
-        m_BP1Writer.m_MetadataSet.Log.Timers[0].SetTime();
+        m_BP1Writer.WriteProcessGroupIndex(
+            m_IO.m_HostLanguage, m_TransportsManager.GetTransportsTypes());
     }
 }
 
-void BPFileWriter::WriteProcessGroupIndex()
-{
-    const bool isFortran = (m_HostLanguage == "Fortran") ? true : false;
-
-    m_BP1Writer.WriteProcessGroupIndex(isFortran, std::to_string(m_RankMPI),
-                                       static_cast<uint32_t>(m_RankMPI),
-                                       m_Transports);
-}
-
 } // end namespace adios
diff --git a/source/adios2/engine/bp/BPFileWriter.h b/source/adios2/engine/bp/BPFileWriter.h
index 343c3167c48b6f6f39dda8bdd85ddaa1fc55a789..24ce235b0e1c0a27d0da4032e95f7354b38c9aeb 100644
--- a/source/adios2/engine/bp/BPFileWriter.h
+++ b/source/adios2/engine/bp/BPFileWriter.h
@@ -2,19 +2,19 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * BPWriter.h
+ * BPFileWriter.h
  *
  *  Created on: Dec 16, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_ENGINE_BP_BPFILEWRITER_H_
 #define ADIOS2_ENGINE_BP_BPFILEWRITER_H_
 
 #include "adios2/ADIOSConfig.h"
-#include "adios2/capsule/heap/STLVector.h"
 #include "adios2/core/Engine.h"
-#include "adios2/utilities/format/bp1/BP1.h"
+#include "adios2/toolkit/format/bp1/BP1.h"            //format::BP1Writer
+#include "adios2/toolkit/transportman/TransportMan.h" //transport::TransportsMan
 
 namespace adios
 {
@@ -24,67 +24,17 @@ class BPFileWriter : public Engine
 
 public:
     /**
-     * Constructor for Writer writes in BP format into a single heap capsule,
-     * manages several transports
+     * Constructor for file Writer in BP format
      * @param name unique name given to the engine
-     * @param accessMode
-     * @param mpiComm
-     * @param method
-     * @param debugMode
+     * @param openMode w (supported), r, a from OpenMode in ADIOSTypes.h
+     * @param mpiComm MPI communicator
      */
-    BPFileWriter(ADIOS &adios, const std::string &name,
-                 const std::string accessMode, MPI_Comm mpiComm,
-                 const Method &method);
+    BPFileWriter(IO &io, const std::string &name, const OpenMode openMode,
+                 MPI_Comm mpiComm);
+
     ~BPFileWriter();
 
-    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(VariableCompound &variable, const void *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 Write(const std::string &variableName, const void *values);
-
-    void Advance(float timeout_sec = 0.0);
+    void Advance(const float timeoutSeconds = 0.0) final;
 
     /**
      * Closes a single transport or all transports
@@ -94,88 +44,39 @@ public:
      * latter
      * is bounds-checked.
      */
-    void Close(const int transportIndex = -1);
+    void Close(const int transportIndex = -1) final;
 
 private:
+    /** Single object controlling BP buffering */
     format::BP1Writer m_BP1Writer;
 
-    /** set to false after first Close is reached so metadata
-        doesn't have to be accommodated for a subsequent Close */
-    bool m_IsFirstClose = true;
+    /** single object controlling a vector of Transports from IO AddTransport */
+    transportman::TransportMan m_TransportsManager;
 
-    /** data buffer exponential growth factor */
-    float m_GrowthFactor = 1.5;
+    /** true: due to buffer overflow, move to transports manager */
+    bool m_DoTransportFlush = false;
 
-    ///< true: due to buffer overflow
-    bool m_TransportFlush = false;
+    void Init() final;
 
-    /** set to true if advance is called, this
-        prevents flattening the data and metadata in Close*/
-    bool m_CloseProcessGroup = false;
+    /** Parses parameters from IO SetParameters */
+    void InitParameters() final;
+    /** Parses transports and parameters from IO AddTransport */
+    void InitTransports() final;
 
-    void Init();
-    void InitParameters();
-    void InitTransports();
-    void InitProcessGroup();
+    void InitBPBuffer();
 
-    void WriteProcessGroupIndex();
+#define declare_type(T)                                                        \
+    void DoWrite(Variable<T> &variable, const T *values) final;
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
     /**
      * Common function for primitive (including std::complex) writes
-     * @param group
-     * @param variableName
      * @param variable
+     * @param values
      */
     template <class T>
-    void WriteVariableCommon(Variable<T> &variable, const T *values)
-    {
-        if (m_BP1Writer.m_MetadataSet.Log.IsActive == true)
-        {
-            m_BP1Writer.m_MetadataSet.Log.Timers[0].SetInitialTime();
-        }
-
-        // set variable
-        variable.m_AppValues = values;
-        m_WrittenVariables.insert(variable.m_Name);
-
-        // if first timestep Write create a new pg index
-        if (m_BP1Writer.m_MetadataSet.DataPGIsOpen == false)
-        {
-            WriteProcessGroupIndex();
-        }
-
-        // pre-calculate new metadata and payload sizes
-        //        m_TransportFlush = CheckBufferAllocation(
-        //        m_BP1Writer.GetVariableIndexSize( variable ) +
-        //        variable.PayLoadSize(),
-        //                                                  m_GrowthFactor,
-        //                                                  m_MaxBufferSize,
-        //                                                  m_Buffer.m_Data );
-
-        // WRITE INDEX to data buffer and metadata structure (in memory)//
-        m_BP1Writer.WriteVariableMetadata(variable);
-
-        if (m_TransportFlush == true) // in batches
-        {
-            // write pg index
-
-            // flush to transports
-
-            // reset relative positions to zero, update absolute position
-        }
-        else // Write data to buffer
-        {
-            m_BP1Writer.WriteVariablePayload(variable);
-        }
-
-        // not needed after write
-        variable.m_AppValues = nullptr;
-
-        if (m_BP1Writer.m_MetadataSet.Log.IsActive == true)
-        {
-            m_BP1Writer.m_MetadataSet.Log.Timers[0].SetTime();
-        }
-    }
+    void DoWriteCommon(Variable<T> &variable, const T *values);
 };
 
 } // end namespace adios
diff --git a/source/adios2/engine/bp/BPFileWriter.tcc b/source/adios2/engine/bp/BPFileWriter.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..baf8999269438db0c6c34e39c950e8e5f1b2cc07
--- /dev/null
+++ b/source/adios2/engine/bp/BPFileWriter.tcc
@@ -0,0 +1,56 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * BPFileWriter.tcc implementation of template functions with known type
+ *
+ *  Created on: May 22, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "BPFileWriter.h"
+
+namespace adios
+{
+
+template <class T>
+void BPFileWriter::DoWriteCommon(Variable<T> &variable, const T *values)
+{
+    // set variable
+    variable.m_AppValues = values;
+    m_WrittenVariables.insert(variable.m_Name);
+
+    // if first timestep Write create a new pg index
+    if (!m_BP1Writer.m_MetadataSet.DataPGIsOpen)
+    {
+        m_BP1Writer.WriteProcessGroupIndex(
+            m_IO.m_HostLanguage, m_TransportsManager.GetTransportsTypes());
+    }
+
+    // pre-calculate new metadata and payload sizes
+    //        m_TransportFlush = CheckBufferAllocation(
+    //        m_BP1Writer.GetVariableIndexSize( variable ) +
+    //        variable.PayLoadSize(),
+    //                                                  m_GrowthFactor,
+    //                                                  m_MaxBufferSize,
+    //                                                  m_Buffer.m_Data );
+
+    // WRITE INDEX to data buffer and metadata structure (in memory)//
+    m_BP1Writer.WriteVariableMetadata(variable);
+
+    if (m_DoTransportFlush) // in batches
+    {
+        // flatten data
+
+        // flush to transports
+
+        // reset relative positions to zero, update absolute position
+    }
+    else // Write data to buffer
+    {
+        m_BP1Writer.WriteVariablePayload(variable);
+    }
+    variable.m_AppValues = nullptr; // not needed after write
+}
+
+} // end namespace adios
diff --git a/source/adios2/engine/dataman/DataManReader.cpp b/source/adios2/engine/dataman/DataManReader.cpp
index e9349adad5708bc94a1492b35ae22b3196743cdb..d05cac30116e5e038d3472809eb809897d759770 100644
--- a/source/adios2/engine/dataman/DataManReader.cpp
+++ b/source/adios2/engine/dataman/DataManReader.cpp
@@ -10,22 +10,16 @@
 
 #include "DataManReader.h"
 
-#include "adios2/core/Support.h"
-#include "adios2/core/adiosFunctions.h"           //CSVToVector
-#include "adios2/transport/file/FStream.h"        // uses C++ fstream
-#include "adios2/transport/file/FileDescriptor.h" // uses POSIX
-#include "adios2/transport/file/FilePointer.h"    // uses C FILE*
-#include "adios2/transport/wan/MdtmMan.h"         //uses Mdtm library
+#include "adios2/helper/adiosFunctions.h" //CSVToVector
 
 namespace adios
 {
 
-DataManReader::DataManReader(ADIOS &adios, const std::string &name,
-                             const std::string accessMode, MPI_Comm mpiComm,
-                             const Method &method)
-: Engine(adios, "DataManReader", name, accessMode, mpiComm, method,
-         " DataManReader constructor (or call to ADIOS Open).\n")
+DataManReader::DataManReader(IO &io, const std::string &name,
+                             const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("DataManReader", io, name, openMode, mpiComm)
 {
+    m_EndMessage = " in call to IO Open DataManReader " + m_Name + "\n";
     Init();
 }
 
@@ -38,135 +32,13 @@ void DataManReader::SetCallBack(
     m_Man.reg_callback(callback);
 }
 
-Variable<void> *
-DataManReader::InquireVariable(const std::string &name,
-                               const bool readIn) // not yet implemented
-{
-    return nullptr;
-}
-
-Variable<char> *DataManReader::InquireVariableChar(const std::string &name,
-                                                   const bool readIn)
-{
-    return InquireVariableCommon<char>(name, readIn);
-}
-
-Variable<unsigned char> *
-DataManReader::InquireVariableUChar(const std::string &name, const bool readIn)
-{
-    return InquireVariableCommon<unsigned char>(name, readIn);
-}
-
-Variable<short> *DataManReader::InquireVariableShort(const std::string &name,
-                                                     const bool readIn)
-{
-    return InquireVariableCommon<short>(name, readIn);
-}
-
-Variable<unsigned short> *
-DataManReader::InquireVariableUShort(const std::string &name, const bool readIn)
-{
-    return InquireVariableCommon<unsigned short>(name, readIn);
-}
-
-Variable<int> *DataManReader::InquireVariableInt(const std::string &name,
-                                                 const bool readIn)
-{
-    return InquireVariableCommon<int>(name, readIn);
-}
-
-Variable<unsigned int> *
-DataManReader::InquireVariableUInt(const std::string &name, const bool readIn)
-{
-    return InquireVariableCommon<unsigned int>(name, readIn);
-}
-
-Variable<long int> *DataManReader::InquireVariableLInt(const std::string &name,
-                                                       const bool readIn)
-{
-    return InquireVariableCommon<long int>(name, readIn);
-}
-
-Variable<unsigned long int> *
-DataManReader::InquireVariableULInt(const std::string &name, const bool readIn)
-{
-    return InquireVariableCommon<unsigned long int>(name, readIn);
-}
-
-Variable<long long int> *
-DataManReader::InquireVariableLLInt(const std::string &name, const bool readIn)
-{
-    return InquireVariableCommon<long long int>(name, readIn);
-}
-
-Variable<unsigned long long int> *
-DataManReader::InquireVariableULLInt(const std::string &name, const bool readIn)
-{
-    return InquireVariableCommon<unsigned long long int>(name, readIn);
-}
-
-Variable<float> *DataManReader::InquireVariableFloat(const std::string &name,
-                                                     const bool readIn)
-{
-    return InquireVariableCommon<float>(name, readIn);
-}
-
-Variable<double> *DataManReader::InquireVariableDouble(const std::string &name,
-                                                       const bool readIn)
-{
-    return InquireVariableCommon<double>(name, readIn);
-}
-
-Variable<long double> *
-DataManReader::InquireVariableLDouble(const std::string &name,
-                                      const bool readIn)
-{
-    return InquireVariableCommon<long double>(name, readIn);
-}
-
-Variable<std::complex<float>> *
-DataManReader::InquireVariableCFloat(const std::string &name, const bool readIn)
-{
-    return InquireVariableCommon<std::complex<float>>(name, readIn);
-}
-
-Variable<std::complex<double>> *
-DataManReader::InquireVariableCDouble(const std::string &name,
-                                      const bool readIn)
-{
-    return InquireVariableCommon<std::complex<double>>(name, readIn);
-}
-
-Variable<std::complex<long double>> *
-DataManReader::InquireVariableCLDouble(const std::string &name,
-                                       const bool readIn)
-{
-    return InquireVariableCommon<std::complex<long double>>(name, readIn);
-}
-
-VariableCompound *
-DataManReader::InquireVariableCompound(const std::string &name,
-                                       const bool readIn)
-{
-    return nullptr;
-}
-
 void DataManReader::Close(const int transportIndex) {}
 
 // PRIVATE
 void DataManReader::Init()
 {
-    if (m_DebugMode == true)
-    {
-        if (m_AccessMode != "r" && m_AccessMode != "read")
-            throw std::invalid_argument(
-                "ERROR: DataManReader doesn't support access mode " +
-                m_AccessMode +
-                ", in call to ADIOS Open or DataManReader constructor\n");
-    }
-
-    auto itRealTime = m_Method.m_Parameters.find("real_time");
-    if (itRealTime != m_Method.m_Parameters.end())
+    auto itRealTime = m_IO.m_Parameters.find("real_time");
+    if (itRealTime != m_IO.m_Parameters.end())
     {
         if (itRealTime->second == "yes" || itRealTime->second == "true")
             m_DoRealTime = true;
@@ -181,8 +53,8 @@ void DataManReader::Init()
          */
         auto lf_AssignString = [this](const std::string parameter,
                                       std::string &localVariable) {
-            auto it = m_Method.m_Parameters.find(parameter);
-            if (it != m_Method.m_Parameters.end())
+            auto it = m_IO.m_Parameters.find(parameter);
+            if (it != m_IO.m_Parameters.end())
             {
                 localVariable = it->second;
             }
@@ -195,8 +67,8 @@ void DataManReader::Init()
          */
         auto lf_AssignInt = [this](const std::string parameter,
                                    int &localVariable) {
-            auto it = m_Method.m_Parameters.find(parameter);
-            if (it != m_Method.m_Parameters.end())
+            auto it = m_IO.m_Parameters.find(parameter);
+            if (it != m_IO.m_Parameters.end())
             {
                 localVariable = std::stoi(it->second);
             }
@@ -209,7 +81,7 @@ void DataManReader::Init()
         };
 
         json jmsg;
-        for (auto &i : m_Method.m_Parameters)
+        for (auto &i : m_IO.m_Parameters)
         {
             if (is_number(i.second))
             {
@@ -234,80 +106,4 @@ void DataManReader::Init()
     }
 }
 
-void DataManReader::InitTransports() // maybe move this?
-{
-    TransportNamesUniqueness();
-
-    for (const auto &parameters : m_Method.m_TransportParameters)
-    {
-        auto itTransport = parameters.find("transport");
-
-        if (itTransport->second == "Mdtm" || itTransport->second == "MdtmMan")
-        {
-            const std::string localIP(
-                GetMdtmParameter("localIP", parameters)); // mandatory
-            const std::string remoteIP(
-                GetMdtmParameter("remoteIP", parameters)); // mandatory
-            const std::string prefix(GetMdtmParameter("prefix", parameters));
-            const int numberOfPipes =
-                std::stoi(GetMdtmParameter("pipes", parameters));
-            const std::vector<int> tolerances =
-                CSVToVectorInt(GetMdtmParameter("tolerances", parameters));
-            const std::vector<int> priorities =
-                CSVToVectorInt(GetMdtmParameter("priorities", parameters));
-
-            //            m_Transports.push_back(std::make_shared<transport::MdtmMan>(
-            //                localIP, remoteIP, m_AccessMode, prefix,
-            //                numberOfPipes,
-            //                tolerances, priorities, m_MPIComm, m_DebugMode));
-        }
-        else if (itTransport->second == "Zmq")
-        {
-        }
-        else
-        {
-            if (m_DebugMode == true)
-                throw std::invalid_argument(
-                    "ERROR: transport + " + itTransport->second +
-                    " not supported, in " + m_Name + m_EndMessage);
-        }
-    }
-}
-
-std::string DataManReader::GetMdtmParameter(
-    const std::string parameter,
-    const std::map<std::string, std::string> &mdtmParameters)
-{
-    auto itParam = mdtmParameters.find(parameter);
-    if (itParam != mdtmParameters.end()) // found
-    {
-        return itParam->second; // return value
-    }
-    // if not found
-    // mandatory ones
-    if (parameter == "localIP" || parameter == "remoteIP")
-    {
-        if (m_DebugMode == true)
-            throw std::invalid_argument(
-                "ERROR: " + parameter +
-                " parameter not found in Method, in call to "
-                "DataManWriter constructor\n");
-    }
-    else if (parameter == "prefix")
-    {
-        return "";
-    }
-    else if (parameter == "pipes")
-    {
-        return "0"; // or 1?
-    }
-    else if (parameter == "tolerances") // so far empty string
-    {
-    }
-    else if (parameter == "priority")
-    {
-    }
-
-    return ""; // return empty string
-}
-}
+} // end namespace adios
diff --git a/source/adios2/engine/dataman/DataManReader.h b/source/adios2/engine/dataman/DataManReader.h
index 43588fbc89be78604b92fd9df9d438ac7207e0fd..af45f1054804199c74986ac46fcafea79c4e08f2 100644
--- a/source/adios2/engine/dataman/DataManReader.h
+++ b/source/adios2/engine/dataman/DataManReader.h
@@ -16,9 +16,7 @@
 #include <DataMan.h>
 
 #include "adios2/ADIOSConfig.h"
-#include "adios2/capsule/heap/STLVector.h"
 #include "adios2/core/Engine.h"
-#include "adios2/utilities/format/bp1/BP1Writer.h"
 
 namespace adios
 {
@@ -38,9 +36,8 @@ public:
      * @param nthreads
      */
     using json = nlohmann::json;
-    DataManReader(ADIOS &adios, const std::string &name,
-                  const std::string accessMode, MPI_Comm mpiComm,
-                  const Method &method);
+    DataManReader(IO &io, const std::string &name, const OpenMode openMode,
+                  MPI_Comm mpiComm);
 
     virtual ~DataManReader() = default;
 
@@ -53,41 +50,6 @@ public:
                                         std::string, Dims)>
                          callback);
 
-    Variable<void> *InquireVariable(const std::string &name,
-                                    const bool readIn = true);
-    Variable<char> *InquireVariableChar(const std::string &name,
-                                        const bool readIn = true);
-    Variable<unsigned char> *InquireVariableUChar(const std::string &name,
-                                                  const bool readIn = true);
-    Variable<short> *InquireVariableShort(const std::string &name,
-                                          const bool readIn = true);
-    Variable<unsigned short> *InquireVariableUShort(const std::string &name,
-                                                    const bool readIn = true);
-    Variable<int> *InquireVariableInt(const std::string &name,
-                                      const bool readIn = true);
-    Variable<unsigned int> *InquireVariableUInt(const std::string &name,
-                                                const bool readIn = true);
-    Variable<long int> *InquireVariableLInt(const std::string &name,
-                                            const bool readIn = true);
-    Variable<unsigned long int> *InquireVariableULInt(const std::string &name,
-                                                      const bool readIn = true);
-    Variable<long long int> *InquireVariableLLInt(const std::string &name,
-                                                  const bool readIn = true);
-    Variable<unsigned long long int> *
-    InquireVariableULLInt(const std::string &name, const bool readIn = true);
-    Variable<float> *InquireVariableFloat(const std::string &name,
-                                          const bool readIn = true);
-    Variable<double> *InquireVariableDouble(const std::string &name,
-                                            const bool readIn = true);
-    Variable<long double> *InquireVariableLDouble(const std::string &name,
-                                                  const bool readIn = true);
-    Variable<std::complex<float>> *
-    InquireVariableCFloat(const std::string &name, const bool readIn = true);
-    Variable<std::complex<double>> *
-    InquireVariableCDouble(const std::string &name, const bool readIn = true);
-    Variable<std::complex<long double>> *
-    InquireVariableCLDouble(const std::string &name, const bool readIn = true);
-
     /**
      * Not implemented
      * @param name
@@ -106,22 +68,19 @@ private:
                        Dims)>
         m_CallBack; ///< call back function
 
-    void Init(); ///< calls InitCapsules and InitTransports based on Method,
-                 /// called from constructor
-    void InitTransports(); ///< from Transports
-
-    std::string
-    GetMdtmParameter(const std::string parameter,
-                     const std::map<std::string, std::string> &mdtmParameters);
+    void Init();
 
     template <class T>
     Variable<T> *InquireVariableCommon(const std::string name,
                                        const bool readIn)
     {
-        std::cout << "I am hooked to the DataMan library\n";
-        std::cout << "Hello DatamanReader from rank " << m_RankMPI << "\n";
-        std::cout << "Trying to read variable " << name
-                  << " from one of the variables coming from a WAN transport\n";
+        // int rank = 0;
+        // MPI_Comm_rank(m_MPIComm, &rank);
+
+        // std::cout << "I am hooked to the DataMan library\n";
+        // std::cout << "Hello DatamanReader from rank " << rank << "\n";
+        // std::cout << "Trying to read variable " << name
+        //        << " from one of the variables coming from a WAN transport\n";
 
         // here read variable metadata (dimensions, type, etc.)...then create a
         // Variable like below:
@@ -132,6 +91,6 @@ private:
     }
 };
 
-} // end namespace
+} // end namespace adios
 
 #endif /* ADIOS2_ENGINE_DATAMAN_DATAMANREADER_H_ */
diff --git a/source/adios2/engine/dataman/DataManWriter.cpp b/source/adios2/engine/dataman/DataManWriter.cpp
index 11eba0ac5afa927c01abb29af92f99370bca0a27..bf0b140161b8503b72e60ec26607bb0d11f4c1d4 100644
--- a/source/adios2/engine/dataman/DataManWriter.cpp
+++ b/source/adios2/engine/dataman/DataManWriter.cpp
@@ -13,20 +13,16 @@
 
 #include <iostream> //needs to go away, this is just for demo purposes
 
-#include "adios2/core/Support.h"
-#include "adios2/core/adiosFunctions.h"    //CSVToVector
-#include "adios2/transport/file/FStream.h" // uses C++ fstream
-#include "adios2/transport/wan/MdtmMan.h"  //uses Mdtm library
+#include "adios2/helper/adiosFunctions.h" //CSVToVector
 
 namespace adios
 {
 
-DataManWriter::DataManWriter(ADIOS &adios, const std::string name,
-                             const std::string accessMode, MPI_Comm mpiComm,
-                             const Method &method)
-: Engine(adios, "DataManWriter", name, accessMode, mpiComm, method,
-         " DataManWriter constructor (or call to ADIOS Open).\n")
+DataManWriter::DataManWriter(IO &io, const std::string &name,
+                             const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("DataManWriter", io, name, openMode, mpiComm)
 {
+    m_EndMessage = ", in call to Open DataManWriter\n";
     Init();
 }
 
@@ -39,231 +35,31 @@ void DataManWriter::SetCallBack(
     m_Man.reg_callback(callback);
 }
 
-void DataManWriter::Write(Variable<char> &variable, const char *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<unsigned char> &variable,
-                          const unsigned char *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<short> &variable, const short *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<unsigned short> &variable,
-                          const unsigned short *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<int> &variable, const int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<unsigned int> &variable,
-                          const unsigned int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<long int> &variable, const long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<unsigned long int> &variable,
-                          const unsigned long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<long long int> &variable,
-                          const long long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<unsigned long long int> &variable,
-                          const unsigned long long int *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<float> &variable, const float *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<double> &variable, const double *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<long double> &variable,
-                          const long double *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<std::complex<float>> &variable,
-                          const std::complex<float> *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<std::complex<double>> &variable,
-                          const std::complex<double> *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-void DataManWriter::Write(Variable<std::complex<long double>> &variable,
-                          const std::complex<long double> *values)
-{
-    WriteVariableCommon(variable, values);
-}
-
-// String version
-void DataManWriter::Write(const std::string &variableName, const char *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<char>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const unsigned char *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned char>(variableName),
-                        values);
-}
-
-void DataManWriter::Write(const std::string &variableName, const short *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<short>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const unsigned short *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned short>(variableName),
-                        values);
-}
-
-void DataManWriter::Write(const std::string &variableName, const int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<int>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const unsigned int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned int>(variableName),
-                        values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const long int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<long int>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const unsigned long int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<unsigned long int>(variableName),
-                        values);
-}
+void DataManWriter::Advance(const float timeoutSeconds) { m_Man.flush(); }
 
-void DataManWriter::Write(const std::string &variableName,
-                          const long long int *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<long long int>(variableName),
-                        values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const unsigned long long int *values)
-{
-    WriteVariableCommon(
-        m_ADIOS.GetVariable<unsigned long long int>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName, const float *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<float>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName, const double *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<double>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const long double *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<long double>(variableName), values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const std::complex<float> *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<std::complex<float>>(variableName),
-                        values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const std::complex<double> *values)
-{
-    WriteVariableCommon(m_ADIOS.GetVariable<std::complex<double>>(variableName),
-                        values);
-}
-
-void DataManWriter::Write(const std::string &variableName,
-                          const std::complex<long double> *values)
-{
-    WriteVariableCommon(
-        m_ADIOS.GetVariable<std::complex<long double>>(variableName), values);
-}
-
-void DataManWriter::Close(const int transportIndex)
-{
-    m_Man.flush();
-    // here close IPs and deallocate or free/close resources (if using STL no
-    // need
-    // for memory deallocation)
-}
+void DataManWriter::Close(const int transportIndex) { m_Man.flush(); }
 
 // PRIVATE functions below
 void DataManWriter::Init()
 {
-    if (m_DebugMode == true)
-    {
-        if (m_AccessMode != "w" && m_AccessMode != "write" &&
-            m_AccessMode != "a" && m_AccessMode != "append")
-            throw std::invalid_argument(
-                "ERROR: DataManWriter doesn't support access mode " +
-                m_AccessMode +
-                ", in call to ADIOS Open or DataManWriter constructor\n");
-    }
+    auto lf_SetBoolParameter = [&](const std::string key, bool &parameter) {
 
-    auto itRealTime = m_Method.m_Parameters.find("real_time");
-    if (itRealTime != m_Method.m_Parameters.end())
-    {
-        if (itRealTime->second == "yes" || itRealTime->second == "true")
-            m_DoRealTime = true;
-    }
+        auto itKey = m_IO.m_Parameters.find(key);
+        if (itKey != m_IO.m_Parameters.end())
+        {
+            if (itKey->second == "yes" || itKey->second == "true")
+            {
+                parameter = true;
+            }
+            else if (itKey->second == "no" || itKey->second == "false")
+            {
+                parameter = false;
+            }
+        }
+    };
 
-    itRealTime = m_Method.m_Parameters.find("monitoring");
-    if (itRealTime != m_Method.m_Parameters.end())
-    {
-        if (itRealTime->second == "yes" || itRealTime->second == "true")
-            m_DoMonitor = true;
-    }
+    lf_SetBoolParameter("real_time", m_DoRealTime);
+    lf_SetBoolParameter("monitoring", m_DoMonitor);
 
     if (m_DoRealTime)
     {
@@ -272,10 +68,10 @@ void DataManWriter::Init()
          * localVariable
          * of type std::string
          */
-        auto lf_AssignString = [this](const std::string parameter,
-                                      std::string &localVariable) {
-            auto it = m_Method.m_Parameters.find(parameter);
-            if (it != m_Method.m_Parameters.end())
+        auto lf_AssignString = [&](const std::string parameter,
+                                   std::string &localVariable) {
+            auto it = m_IO.m_Parameters.find(parameter);
+            if (it != m_IO.m_Parameters.end())
             {
                 localVariable = it->second;
             }
@@ -286,25 +82,25 @@ void DataManWriter::Init()
          * localVariable
          * of type int
          */
-        auto lf_AssignInt = [this](const std::string parameter,
-                                   int &localVariable) {
-            auto it = m_Method.m_Parameters.find(parameter);
-            if (it != m_Method.m_Parameters.end())
+        auto lf_AssignInt = [&](const std::string parameter,
+                                int &localVariable) {
+            auto it = m_IO.m_Parameters.find(parameter);
+            if (it != m_IO.m_Parameters.end())
             {
                 localVariable = std::stoi(it->second);
             }
         };
 
-        auto is_number = [](const std::string &s) {
+        auto lf_IsNumber = [](const std::string &s) {
             return !s.empty() && std::find_if(s.begin(), s.end(), [](char c) {
                                      return !std::isdigit(c);
                                  }) == s.end();
         };
 
         json jmsg;
-        for (auto &i : m_Method.m_Parameters)
+        for (const auto &i : m_IO.m_Parameters)
         {
-            if (is_number(i.second))
+            if (lf_IsNumber(i.second))
             {
                 jmsg[i.first] = std::stoi(i.second);
             }
@@ -317,91 +113,19 @@ void DataManWriter::Init()
         m_Man.add_stream(jmsg);
 
         std::string method_type;
-        int num_channels = 0;
         lf_AssignString("method_type", method_type);
-        lf_AssignInt("num_channels", num_channels);
-    }
-    else
-    {
-        InitTransports();
-    }
-}
-
-void DataManWriter::InitTransports() // maybe move this?
-{
-    TransportNamesUniqueness();
-
-    for (const auto &parameters : m_Method.m_TransportParameters)
-    {
-        auto itTransport = parameters.find("transport");
-
-        if (itTransport->second == "Mdtm" || itTransport->second == "MdtmMan")
-        {
-            const std::string localIP(
-                GetMdtmParameter("localIP", parameters)); // mandatory
-            const std::string remoteIP(
-                GetMdtmParameter("remoteIP", parameters)); // mandatory
-            const std::string prefix(GetMdtmParameter("prefix", parameters));
-            const int numberOfPipes =
-                std::stoi(GetMdtmParameter("pipes", parameters));
-            const std::vector<int> tolerances =
-                CSVToVectorInt(GetMdtmParameter("tolerances", parameters));
-            const std::vector<int> priorities =
-                CSVToVectorInt(GetMdtmParameter("priorities", parameters));
 
-            //            m_Transports.push_back(std::make_shared<transport::MdtmMan>(
-            //                localIP, remoteIP, m_AccessMode, prefix,
-            //                numberOfPipes,
-            //                tolerances, priorities, m_MPIComm, m_DebugMode));
-        }
-        else if (itTransport->second == "Zmq")
-        {
-        }
-        else
-        {
-            if (m_DebugMode == true)
-                throw std::invalid_argument(
-                    "ERROR: transport + " + itTransport->second +
-                    " not supported, in " + m_Name + m_EndMessage);
-        }
+        int num_channels = 0;
+        lf_AssignInt("num_channels", num_channels);
     }
 }
 
-std::string DataManWriter::GetMdtmParameter(
-    const std::string parameter,
-    const std::map<std::string, std::string> &mdtmParameters)
-{
-    auto itParam = mdtmParameters.find(parameter);
-    if (itParam != mdtmParameters.end()) // found
-    {
-        return itParam->second; // return value
-    }
-    // if not found
-    // mandatory ones
-    if (parameter == "localIP" || parameter == "remoteIP")
-    {
-        if (m_DebugMode == true)
-            throw std::invalid_argument(
-                "ERROR: " + parameter +
-                " parameter not found in Method, in call to "
-                "DataManWriter constructor\n");
-    }
-    else if (parameter == "prefix")
-    {
-        return "";
+#define declare_type(T)                                                        \
+    void DataManWriter::DoWrite(Variable<T> &variable, const T *values)        \
+    {                                                                          \
+        DoWriteCommon(variable, values);                                       \
     }
-    else if (parameter == "pipes")
-    {
-        return "0"; // or 1?
-    }
-    else if (parameter == "tolerances") // so far empty string
-    {
-    }
-    else if (parameter == "priority")
-    {
-    }
-
-    return ""; // return empty string
-}
+ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
 } // end namespace adios
diff --git a/source/adios2/engine/dataman/DataManWriter.h b/source/adios2/engine/dataman/DataManWriter.h
index f9fe6131ee637d2f14c58c090230a6ea3ee11666..f9a1e017321c18a8d91bf148a1a62a6c0e3922f5 100644
--- a/source/adios2/engine/dataman/DataManWriter.h
+++ b/source/adios2/engine/dataman/DataManWriter.h
@@ -17,9 +17,7 @@
 #include <DataMan.h>
 
 #include "adios2/ADIOSConfig.h"
-#include "adios2/capsule/heap/STLVector.h"
 #include "adios2/core/Engine.h"
-#include "adios2/utilities/format/bp1/BP1Writer.h"
 
 namespace adios
 {
@@ -29,72 +27,19 @@ class DataManWriter : public Engine
 
 public:
     using json = nlohmann::json;
-    /**
-     * Constructor for dataman engine Writer for WAN communications
-     * @param adios
-     * @param name unique name given to the engine
-     * @param accessMode
-     * @param mpiComm
-     * @param method
-     * @param debugMode
-     * @param nthreads
-     */
-    DataManWriter(ADIOS &adios, const std::string name,
-                  const std::string accessMode, MPI_Comm mpiComm,
-                  const Method &method);
+
+    DataManWriter(IO &io, const std::string &name, const OpenMode openMode,
+                  MPI_Comm mpiComm);
 
     virtual ~DataManWriter() = default;
 
     void SetCallBack(std::function<void(const void *, std::string, std::string,
                                         std::string, Dims)>
-                         callback);
-
-    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);
+                         callback) final;
+
+    void Advance(const float timeoutSeconds = 0.0) final;
+
+    void Close(const int transportIndex = -1) final;
 
 private:
     bool m_DoRealTime = false;
@@ -106,21 +51,14 @@ private:
 
     void Init(); ///< calls InitCapsules and InitTransports based on Method,
                  /// called from constructor
-    void InitTransports(); ///< from Transports
-
-    /**
-     * From transport Mdtm in m_Method
-     * @param parameter must be an accepted parameter
-     * @param mdtmParameters
-     * @return value either returns user-defined from "parameter=value" or a
-     * default
-     */
-    std::string
-    GetMdtmParameter(const std::string parameter,
-                     const std::map<std::string, std::string> &mdtmParameters);
+
+#define declare_type(T)                                                        \
+    void DoWrite(Variable<T> &variable, const T *values) final;
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
     template <class T>
-    void WriteVariableCommon(Variable<T> &variable, const T *values);
+    void DoWriteCommon(Variable<T> &variable, const T *values);
 };
 
 } // end namespace adios
diff --git a/source/adios2/engine/dataman/DataManWriter.tcc b/source/adios2/engine/dataman/DataManWriter.tcc
index 149830a06401752f41f710ab505ba74a627d47d1..9c3023e4574142d4cc4af2137923339ad1128237 100644
--- a/source/adios2/engine/dataman/DataManWriter.tcc
+++ b/source/adios2/engine/dataman/DataManWriter.tcc
@@ -19,7 +19,7 @@ namespace adios
 {
 
 template <class T>
-void DataManWriter::WriteVariableCommon(Variable<T> &variable, const T *values)
+void DataManWriter::DoWriteCommon(Variable<T> &variable, const T *values)
 {
     // here comes your magic at Writing now variable.m_UserValues has the
     // data
@@ -53,15 +53,19 @@ void DataManWriter::WriteVariableCommon(Variable<T> &variable, const T *values)
     {
         MPI_Barrier(m_MPIComm);
         std::cout << "I am hooked to the DataMan library\n";
-        std::cout << "putshape " << variable.m_Count.size() << std::endl;
-        std::cout << "varshape " << variable.m_Shape.size() << std::endl;
-        std::cout << "offset " << variable.m_Start.size() << std::endl;
-        for (int i = 0; i < m_SizeMPI; ++i)
+        std::cout << "Variable " << variable.m_Name << "\n";
+        std::cout << "putshape " << variable.m_Count.size() << "\n";
+        std::cout << "varshape " << variable.m_Shape.size() << "\n";
+        std::cout << "offset " << variable.m_Start.size() << "\n";
+
+        int rank = 0, size = 1;
+        MPI_Comm_size(m_MPIComm, &size);
+
+        for (int i = 0; i < size; ++i)
         {
-            if (i == m_RankMPI)
+            if (i == rank)
             {
-                std::cout << "Rank: " << m_RankMPI << "\n";
-                variable.Monitor(std::cout);
+                std::cout << "Rank: " << i << "\n";
                 std::cout << std::endl;
             }
             else
diff --git a/source/adios2/engine/hdf5/HDF5Common.h b/source/adios2/engine/hdf5/HDF5Common.h
deleted file mode 100644
index d5a6a77190b1ed2465bf62b82073835b061afe27..0000000000000000000000000000000000000000
--- a/source/adios2/engine/hdf5/HDF5Common.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * HDF5CommonP.h
- *
- *  Created on: March 20, 2017
- *      Author: Junmin
- */
-
-#ifndef ADIOS2_ENGINE_HDF5_HDF5COMMON_P_H_
-#define ADIOS2_ENGINE_HDF5_HDF5COMMON_P_H_
-
-#include <string>
-
-#include "adios2/ADIOSMPICommOnly.h"
-
-#include <hdf5.h>
-
-namespace adios
-{
-
-class HDF5Common
-{
-
-public:
-    /**
-     * Constructor for HDF5 file
-     */
-    HDF5Common();
-
-    void Init(const std::string name, MPI_Comm comm, bool toWrite);
-    void Close();
-    void Advance();
-
-    unsigned int GetNumTimeSteps();
-    void WriteTimeSteps();
-
-    hid_t m_PropertyListId, m_FileId;
-    hid_t m_GroupId;
-
-    hid_t m_DefH5TypeComplexDouble;
-    hid_t m_DefH5TypeComplexFloat;
-    hid_t m_DefH5TypeComplexLongDouble;
-
-    unsigned int m_CurrentTimeStep;
-
-    void CheckWriteGroup();
-
-private:
-    bool m_WriteMode;
-    unsigned int m_NumTimeSteps;
-};
-
-} // end namespace adios
-
-#endif /* ADIOS2_ENGINE_HDF5_HDF5COMMON_P_H_ */
diff --git a/source/adios2/engine/hdf5/HDF5ReaderP.cpp b/source/adios2/engine/hdf5/HDF5ReaderP.cpp
index 7f3ead729cae47aaa634e6a0d2365a2294584a06..e880f6f5ca1fbce296f88fe47207a797754babee 100644
--- a/source/adios2/engine/hdf5/HDF5ReaderP.cpp
+++ b/source/adios2/engine/hdf5/HDF5ReaderP.cpp
@@ -15,177 +15,53 @@
 namespace adios
 {
 
-HDF5Reader::HDF5Reader(ADIOS &adios, const std::string name,
-                       const std::string accessMode, MPI_Comm mpiComm,
-                       const Method &method)
-: Engine(adios, "HDF5Reader", name, accessMode, mpiComm, method,
-         " HDF5Reader constructor (or call to ADIOS Open).\n")
-
+HDF5ReaderP::HDF5ReaderP(IO &io, const std::string &name,
+                         const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("HDF5Reader", io, name, openMode, mpiComm), m_H5File(io.m_DebugMode)
 {
+    m_EndMessage = ", in call to IO HDF5Reader Open " + m_Name + "\n";
     Init();
 }
 
-HDF5Reader::~HDF5Reader() { Close(); }
+HDF5ReaderP::~HDF5ReaderP() { Close(); }
 
-bool HDF5Reader::isValid()
+bool HDF5ReaderP::IsValid()
 {
-    if (m_AccessMode != "r" && m_AccessMode != "read")
+    bool isValid = false;
+
+    if (m_OpenMode != OpenMode::Read)
     {
-        return false;
+        return isValid;
     }
     if (m_H5File.m_FileId >= 0)
     {
-        return true;
+        isValid = true;
     }
+    return isValid;
 }
-void HDF5Reader::Init()
+void HDF5ReaderP::Init()
 {
-    if (m_AccessMode != "r" && m_AccessMode != "read")
+    if (m_OpenMode != OpenMode::Read)
     {
         throw std::invalid_argument(
-            "ERROR: HDF5Reader doesn't support access mode " + m_AccessMode +
-            ", in call to ADIOS Open or HDF5Reader constructor\n");
+            "ERROR: HDF5Reader only supports OpenMode::Read "
+            ", in call to Open\n");
     }
 
     m_H5File.Init(m_Name, m_MPIComm, false);
     m_H5File.GetNumTimeSteps();
 }
 
-Variable<void> *HDF5Reader::InquireVariable(const std::string &variableName,
-                                            const bool readIn)
-{
-    std::cout << "Not implemented: HDF5Reader::InquireVariable()" << std::endl;
-    return nullptr;
-}
-
-Variable<char> *HDF5Reader::InquireVariableChar(const std::string &variableName,
-                                                const bool readIn)
-{
-    return nullptr;
-}
-
-Variable<unsigned char> *
-HDF5Reader::InquireVariableUChar(const std::string &variableName,
-                                 const bool readIn)
-{
-    return nullptr;
-}
-
-Variable<short> *
-HDF5Reader::InquireVariableShort(const std::string &variableName,
-                                 const bool readIn)
-{
-    return nullptr;
-}
-
-Variable<unsigned short> *
-HDF5Reader::InquireVariableUShort(const std::string &variableName,
-                                  const bool readIn)
-{
-    return nullptr;
-}
-
-Variable<int> *HDF5Reader::InquireVariableInt(const std::string &variableName,
-                                              const bool)
-{
-    return nullptr;
-}
-
-Variable<unsigned int> *
-HDF5Reader::InquireVariableUInt(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<long int> *
-HDF5Reader::InquireVariableLInt(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<unsigned long int> *
-HDF5Reader::InquireVariableULInt(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<long long int> *
-HDF5Reader::InquireVariableLLInt(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<unsigned long long int> *
-HDF5Reader::InquireVariableULLInt(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<float> *
-HDF5Reader::InquireVariableFloat(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<double> *
-HDF5Reader::InquireVariableDouble(const std::string &variableName, const bool)
-{
-
-    if (m_RankMPI == 0)
-    {
-        std::cout << " ... reading var: " << variableName << std::endl;
-    }
-    int totalts = m_H5File.GetNumTimeSteps();
-
-    if (m_RankMPI == 0)
-    {
-        std::cout << " ... I saw total timesteps: " << totalts << std::endl;
-    }
-
-    return nullptr;
-}
-
-Variable<long double> *
-HDF5Reader::InquireVariableLDouble(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<std::complex<float>> *
-HDF5Reader::InquireVariableCFloat(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<std::complex<double>> *
-HDF5Reader::InquireVariableCDouble(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-Variable<std::complex<long double>> *
-HDF5Reader::InquireVariableCLDouble(const std::string &variableName, const bool)
-{
-    return nullptr;
-}
-
-VariableCompound *
-HDF5Reader::InquireVariableCompound(const std::string &variableName,
-                                    const bool readIn)
-{
-    return nullptr;
-}
-
 template <class T>
-void HDF5Reader::UseHDFRead(const std::string &variableName, T *values,
-                            hid_t h5Type)
+void HDF5ReaderP::UseHDFRead(const std::string &variableName, T *values,
+                             hid_t h5Type)
 {
+    int rank, size;
+    MPI_Comm_rank(m_MPIComm, &rank);
+    MPI_Comm_size(m_MPIComm, &size);
+
     hid_t dataSetId =
         H5Dopen(m_H5File.m_GroupId, variableName.c_str(), H5P_DEFAULT);
-    if (m_RankMPI == 0)
-    {
-        std::cout << " opened to read: " << variableName << std::endl;
-    }
 
     if (dataSetId < 0)
     {
@@ -206,18 +82,15 @@ void HDF5Reader::UseHDFRead(const std::string &variableName, T *values,
     int totalElements = 1;
     for (int i = 0; i < ndims; i++)
     {
-        std::cout << " [" << i << "] th dimension: " << dims[i] << std::endl;
         count[i] = dims[i];
         totalElements *= dims[i];
     }
 
-    start[0] = m_RankMPI * dims[0] / m_SizeMPI;
-    count[0] = dims[0] / m_SizeMPI;
-    if (m_RankMPI == m_SizeMPI - 1)
+    start[0] = rank * dims[0] / size;
+    count[0] = dims[0] / size;
+    if (rank == size - 1)
     {
-        count[0] = dims[0] - count[0] * (m_SizeMPI - 1);
-        std::cout << " rank = " << m_RankMPI << ", count=" << count[0]
-                  << std::endl;
+        count[0] = dims[0] - count[0] * (size - 1);
     }
 
     hid_t ret = H5Sselect_hyperslab(fileSpace, H5S_SELECT_SET, start, stride,
@@ -239,20 +112,14 @@ void HDF5Reader::UseHDFRead(const std::string &variableName, T *values,
     ret = H5Dread(dataSetId, h5Type, memDataSpace, fileSpace, H5P_DEFAULT,
                   data_array);
 
-    for (int i = 0; i < elementsRead; i++)
-    {
-        std::cout << "... rank " << m_RankMPI << "   , " << data_array[i]
-                  << std::endl;
-    }
-
     H5Sclose(memDataSpace);
 
     H5Sclose(fileSpace);
     H5Dclose(dataSetId);
 }
 
-void HDF5Reader::Advance(float timeoutSec) { m_H5File.Advance(); }
+void HDF5ReaderP::Advance(const float timeoutSeconds) { m_H5File.Advance(); }
 
-void HDF5Reader::Close(const int transportIndex) { m_H5File.Close(); }
+void HDF5ReaderP::Close(const int transportIndex) { m_H5File.Close(); }
 
 } // end namespace adios
diff --git a/source/adios2/engine/hdf5/HDF5ReaderP.h b/source/adios2/engine/hdf5/HDF5ReaderP.h
index 70c71137b5c6a4f7edc92600cae66a2ec67fb07d..90584bd6cf94b8c6f19c459aac640e5a1429913c 100644
--- a/source/adios2/engine/hdf5/HDF5ReaderP.h
+++ b/source/adios2/engine/hdf5/HDF5ReaderP.h
@@ -11,15 +11,14 @@
 #ifndef ADIOS2_ENGINE_HDF5_HDF5READERP_H_
 #define ADIOS2_ENGINE_HDF5_HDF5READERP_H_
 
-#include "HDF5Common.h"
-
-#include "adios2/ADIOSMPICommOnly.h"
 #include "adios2/core/Engine.h"
+#include "adios2/core/IO.h"
+#include "adios2/toolkit/interop/hdf5/HDF5Common.h"
 
 namespace adios
 {
 
-class HDF5Reader : public Engine
+class HDF5ReaderP : public Engine
 {
 
 public:
@@ -30,96 +29,23 @@ public:
      * @param mpiComm
      * @param method
      */
-    HDF5Reader(ADIOS &adios, const std::string name,
-               const std::string accessMode, MPI_Comm mpiComm,
-               const Method &method);
-
-    virtual ~HDF5Reader();
-
-    bool isValid();
-
-    Variable<void> *InquireVariable(const std::string &variableName,
-                                    const bool readIn = true);
-
-    Variable<char> *InquireVariableChar(const std::string &variableName,
-                                        const bool readIn = true);
-
-    Variable<unsigned char> *
-    InquireVariableUChar(const std::string &variableName,
-                         const bool readIn = true);
-
-    Variable<short> *InquireVariableShort(const std::string &variableName,
-                                          const bool readIn = true);
-
-    Variable<unsigned short> *
-    InquireVariableUShort(const std::string &variableName,
-                          const bool readIn = true);
-
-    Variable<int> *InquireVariableInt(const std::string &variableName,
-                                      const bool readIn = true);
-
-    Variable<unsigned int> *InquireVariableUInt(const std::string &variableName,
-                                                const bool readIn = true);
-
-    Variable<long int> *InquireVariableLInt(const std::string &variableName,
-                                            const bool readIn = true);
+    HDF5ReaderP(IO &adios, const std::string &name, const OpenMode openMode,
+                MPI_Comm mpiComm);
 
-    Variable<unsigned long int> *
-    InquireVariableULInt(const std::string &variableName,
-                         const bool readIn = true);
+    ~HDF5ReaderP();
 
-    Variable<long long int> *
-    InquireVariableLLInt(const std::string &variableName,
-                         const bool readIn = true);
+    bool IsValid();
 
-    Variable<unsigned long long int> *
-    InquireVariableULLInt(const std::string &variableName,
-                          const bool readIn = true);
+    void Advance(const float timeoutSeconds = 0.0) final;
 
-    Variable<float> *InquireVariableFloat(const std::string &variableName,
-                                          const bool readIn = true);
+    void Close(const int transportIndex = -1) final;
 
-    Variable<double> *InquireVariableDouble(const std::string &variableName,
-                                            const bool readIn = true);
-    Variable<long double> *
-    InquireVariableLDouble(const std::string &variableName,
-                           const bool readIn = true);
-
-    Variable<std::complex<float>> *
-    InquireVariableCFloat(const std::string &variableName,
-                          const bool readIn = true);
-
-    Variable<std::complex<double>> *
-    InquireVariableCDouble(const std::string &variableName,
-                           const bool readIn = true);
-
-    Variable<std::complex<long double>> *
-    InquireVariableCLDouble(const std::string &variableName,
-                            const bool readIn = true);
-
-    /**
-     * Not implemented
-     * @param name
-     * @param readIn
-     * @return
-     */
-    VariableCompound *InquireVariableCompound(const std::string &variableName,
-                                              const bool readIn = true);
-
-    void Advance(float timeoutSecc = 0.0);
-
-    void Close(const int transportIndex = -1);
-
-    template <typename T>
+    template <class T>
     void UseHDFRead(const std::string &variableName, T *values, hid_t h5Type);
 
-    /*
-    template <class T>
-    void ReadMe(Variable<T> &variable, T *values, hid_t h5type);
-    */
 private:
-    HDF5Common m_H5File;
-    void Init();
+    interop::HDF5Common m_H5File;
+    void Init() final;
 };
 };
 #endif /* ADIOS2_ENGINE_HDF5_HDF5READERP_H_ */
diff --git a/source/adios2/engine/hdf5/HDF5WriterP.cpp b/source/adios2/engine/hdf5/HDF5WriterP.cpp
index db9d6c4e6e0e1a7d31e54aa5055eb2a325b9deb3..e21be47f660d999ef809efb3bdc9cb03ca1f9ea4 100644
--- a/source/adios2/engine/hdf5/HDF5WriterP.cpp
+++ b/source/adios2/engine/hdf5/HDF5WriterP.cpp
@@ -11,333 +11,54 @@
 #include "HDF5WriterP.h"
 
 #include "adios2/ADIOSMPI.h"
-#include "adios2/core/Support.h"
-#include "adios2/core/adiosFunctions.h" //CSVToVector
+#include "adios2/helper/adiosFunctions.h" //CSVToVector
 
 namespace adios
 {
 
-HDF5Writer::HDF5Writer(ADIOS &adios, const std::string name,
-                       const std::string accessMode, MPI_Comm mpiComm,
-                       const Method &method)
-: Engine(adios, "HDF5Writer", name, accessMode, mpiComm,
-         method, /*debugMode, cores,*/
-         " HDF5Writer constructor (or call to ADIOS Open).\n")
-// m_Buffer(m_DebugMode)
+HDF5WriterP::HDF5WriterP(IO &io, const std::string &name,
+                         const OpenMode openMode, MPI_Comm mpiComm)
+: Engine("HDF5Writer", io, name, openMode, mpiComm), m_H5File(io.m_DebugMode)
 {
+    m_EndMessage = ", in call to IO HDF5Writer Open " + m_Name + "\n";
     Init();
 }
 
-HDF5Writer::~HDF5Writer() { Close(); }
+HDF5WriterP::~HDF5WriterP() { Close(); }
 
-void HDF5Writer::Init()
+// PRIVATE
+void HDF5WriterP::Init()
 {
-    if (m_AccessMode != "w" && m_AccessMode != "write" && m_AccessMode != "a" &&
-        m_AccessMode != "append")
+    if (m_OpenMode != OpenMode::Write && m_OpenMode != OpenMode::Append)
     {
         throw std::invalid_argument(
-            "ERROR: HDF5Writer doesn't support access mode " + m_AccessMode +
+            "ERROR: HDF5Writer only support OpenMode::Write or "
+            "OpenMode::Append "
             ", in call to ADIOS Open or HDF5Writer constructor\n");
     }
 
     m_H5File.Init(m_Name, m_MPIComm, true);
 }
 
-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, m_H5File.m_DefH5TypeComplexFloat);
-}
-
-void HDF5Writer::Write(Variable<std::complex<double>> &variable,
-                       const std::complex<double> *values)
-{
-    UseHDFWrite(variable, values, m_H5File.m_DefH5TypeComplexDouble);
-}
-
-void HDF5Writer::Write(Variable<std::complex<long double>> &variable,
-                       const std::complex<long double> *values)
-{
-    UseHDFWrite(variable, values, m_H5File.m_DefH5TypeComplexLongDouble);
-}
-
-// 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,
-                m_H5File.m_DefH5TypeComplexFloat);
-}
-
-void HDF5Writer::Write(const std::string &variableName,
-                       const std::complex<double> *values)
-{
-    UseHDFWrite(m_ADIOS.GetVariable<std::complex<double>>(variableName), values,
-                m_H5File.m_DefH5TypeComplexDouble);
-}
+#define declare_type(T)                                                        \
+    void HDF5WriterP::DoWrite(Variable<T> &variable, const T *values)          \
+    {                                                                          \
+        DoWriteCommon(variable, values);                                       \
+    }
 
-void HDF5Writer::Write(const std::string &variableName,
-                       const std::complex<long double> *values)
-{
-    UseHDFWrite(m_ADIOS.GetVariable<std::complex<long double>>(variableName),
-                values, m_H5File.m_DefH5TypeComplexLongDouble);
-}
+ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
-void HDF5Writer::Advance(float timeoutSec) { m_H5File.Advance(); }
+void HDF5WriterP::Advance(const float timeoutSeconds) { m_H5File.Advance(); }
 
-void HDF5Writer::Close(const int transportIndex) { m_H5File.Close(); }
+void HDF5WriterP::Close(const int transportIndex) { m_H5File.Close(); }
 
 template <class T>
-void HDF5Writer::UseHDFWrite(Variable<T> &variable, const T *values,
-                             hid_t h5Type)
+void HDF5WriterP::DoWriteCommon(Variable<T> &variable, const T *values)
 {
-    m_H5File.CheckWriteGroup();
-    // 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);
-
-    int dimSize = std::max(variable.m_Shape.size(), variable.m_Count.size());
-
-    if (dimSize == 0)
-    {
-        // scalar
-        hid_t filespaceID = H5Screate(H5S_SCALAR);
-        hid_t dsetID =
-            H5Dcreate(m_H5File.m_GroupId, variable.m_Name.c_str(), h5Type,
-                      filespaceID, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-        herr_t status =
-            H5Dwrite(dsetID, h5Type, H5S_ALL, H5S_ALL, H5P_DEFAULT, values);
-
-        H5Sclose(filespaceID);
-        H5Dclose(dsetID);
-
-        return;
-    }
-
-    std::vector<hsize_t> dimsf, count, offset;
-
-    for (int i = 0; i < dimSize; i++)
-    {
-        if (variable.m_Shape.size() == dimSize)
-        {
-            dimsf.push_back(variable.m_Shape[i]);
-        }
-        else
-        {
-            dimsf.push_back(variable.m_Count[i]);
-        }
-
-        if (variable.m_Count.size() == dimSize)
-        {
-            count.push_back(variable.m_Count[i]);
-            if (variable.m_Start.size() == dimSize)
-            {
-                offset.push_back(variable.m_Start[i]);
-            }
-            else
-            {
-                offset.push_back(0);
-            }
-        }
-        else
-        {
-            count.push_back(variable.m_Shape[i]);
-            offset.push_back(0);
-        }
-    }
-
-    hid_t fileSpace = H5Screate_simple(dimSize, dimsf.data(), NULL);
-
-    hid_t dsetID =
-        H5Dcreate(m_H5File.m_GroupId, variable.m_Name.c_str(), h5Type,
-                  fileSpace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-    // H5Sclose(fileSpace);
-
-    hid_t memSpace = H5Screate_simple(dimSize, count.data(), NULL);
-
-    // Select hyperslab
-    fileSpace = H5Dget_space(dsetID);
-    H5Sselect_hyperslab(fileSpace, H5S_SELECT_SET, offset.data(), NULL,
-                        count.data(), NULL);
-
-    //  Create property list for collective dataset write.
-
-    hid_t plistID = H5Pcreate(H5P_DATASET_XFER);
-#ifdef ADIOS2_HAVE_MPI
-    H5Pset_dxpl_mpio(plistID, H5FD_MPIO_COLLECTIVE);
-#endif
-    herr_t status;
-
-    status = H5Dwrite(dsetID, h5Type, memSpace, fileSpace, plistID, values);
-
-    if (status < 0)
-    {
-        // error
-        std::cerr << " Write failed. " << std::endl;
-    }
-
-    H5Dclose(dsetID);
-    H5Sclose(fileSpace);
-    H5Sclose(memSpace);
-    H5Pclose(plistID);
+    m_H5File.Write(variable, values);
 }
 
 } // end namespace adios
diff --git a/source/adios2/engine/hdf5/HDF5WriterP.h b/source/adios2/engine/hdf5/HDF5WriterP.h
index 22a1b8f57ef079c04f87680c57bb52fa340f74a0..84c3e182fdf633edf92b5434149b7f5215f0d476 100644
--- a/source/adios2/engine/hdf5/HDF5WriterP.h
+++ b/source/adios2/engine/hdf5/HDF5WriterP.h
@@ -1,4 +1,3 @@
-
 /*
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
@@ -12,19 +11,18 @@
 #ifndef ADIOS2_ENGINE_HDF5_HDF5WRITERP_H__
 #define ADIOS2_ENGINE_HDF5_HDF5WRITERP_H__
 
-#include "HDF5Common.h"
+#include <hdf5.h>
 
 #include "adios2/ADIOSConfig.h"
 #include "adios2/ADIOSMPICommOnly.h"
-#include "adios2/capsule/heap/STLVector.h"
 #include "adios2/core/Engine.h"
-
-#include <hdf5.h>
+#include "adios2/core/IO.h"
+#include "adios2/toolkit/interop/hdf5/HDF5Common.h"
 
 namespace adios
 {
 
-class HDF5Writer : public Engine
+class HDF5WriterP : public Engine
 {
 
 public:
@@ -35,71 +33,27 @@ public:
      * @param mpiComm
      * @param method
      */
-    HDF5Writer(ADIOS &adios, const std::string name,
-               const std::string accessMode, MPI_Comm mpiComm,
-               const Method &method);
-
-    virtual ~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);
+    HDF5WriterP(IO &io, const std::string &name, const OpenMode openMode,
+                MPI_Comm mpiComm);
 
-    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);
+    ~HDF5WriterP();
 
-    void Advance(float timeoutSec = 0.0);
+    void Advance(const float timeoutSeconds = 0.0) final;
 
-    void Close(const int transportIndex = -1);
+    void Close(const int transportIndex = -1) final;
 
 private:
-    ///< heap capsule, contains data and metadata buffers
-    // capsule::STLVector m_Buffer;
+    interop::HDF5Common m_H5File;
 
     void Init();
 
-    HDF5Common m_H5File;
+#define declare_type(T)                                                        \
+    void DoWrite(Variable<T> &variable, const T *values) final;
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
 
     template <class T>
-    void UseHDFWrite(Variable<T> &variable, const T *values, hid_t h5Type);
+    void DoWriteCommon(Variable<T> &variable, const T *values);
 };
 
 } // end namespace adios
diff --git a/source/adios2/helper/adiosFunctions.h b/source/adios2/helper/adiosFunctions.h
new file mode 100644
index 0000000000000000000000000000000000000000..af3e98f18f93c75e745c2903ce5f7ab4e98c662f
--- /dev/null
+++ b/source/adios2/helper/adiosFunctions.h
@@ -0,0 +1,22 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosFunctions.h helper functions used by ADIOS class. This is the only
+ * required "public" header.
+ *
+ *  Created on: Oct 10, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSFUNCTIONS_H_
+#define ADIOS2_HELPER_ADIOSFUNCTIONS_H_
+
+#include "adios2/helper/adiosMath.h"   //math functions (cmath, algorithm)
+#include "adios2/helper/adiosMemory.h" //memcpy, std::copy, insert, resize
+#include "adios2/helper/adiosString.h" //std::string manipulation
+#include "adios2/helper/adiosSystem.h" //OS functionality, POSIX, filesystem
+#include "adios2/helper/adiosType.h"   //Type casting, conversion, checks, etc.
+#include "adios2/helper/adiosXML.h"    //XML parsing
+
+#endif /* ADIOS2_HELPER_ADIOSFUNCTIONS_H_ */
diff --git a/source/adios2/helper/adiosMath.cpp b/source/adios2/helper/adiosMath.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..91f27372d296fd98427db2bf243b02b08c850b78
--- /dev/null
+++ b/source/adios2/helper/adiosMath.cpp
@@ -0,0 +1,39 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMath.cpp
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "adiosMath.h"
+
+namespace adios
+{
+
+size_t GetTotalSize(const Dims &dimensions) noexcept
+{
+    size_t product = 1;
+
+    for (const auto dimension : dimensions)
+    {
+        product *= dimension;
+    }
+
+    return product;
+}
+
+bool CheckIndexRange(const int index, const int upperLimit,
+                     const int lowerLimit) noexcept
+{
+    bool inRange = false;
+    if (index <= upperLimit && index >= lowerLimit)
+    {
+        inRange = true;
+    }
+    return inRange;
+}
+
+} // end namespace adios
diff --git a/source/adios2/helper/adiosMath.h b/source/adios2/helper/adiosMath.h
new file mode 100644
index 0000000000000000000000000000000000000000..69d941b2d502f409ae1c4bfc9bfb3d96ece1c981
--- /dev/null
+++ b/source/adios2/helper/adiosMath.h
@@ -0,0 +1,95 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMath.h math functions used in the ADIOS framework
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSMATH_H_
+#define ADIOS2_HELPER_ADIOSMATH_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSTypes.h"
+
+namespace adios
+{
+/**
+ * Loops through a vector containing dimensions and returns the product of all
+ * elements
+ * @param dimensions input containing size on each dimension {Nx, Ny, Nz}
+ * @return product of all dimensions Nx * Ny * Nz
+ */
+size_t GetTotalSize(const Dims &dimensions) noexcept;
+
+/**
+ * Gets the min and max from a values array of primitive types (not including
+ * complex)
+ * @param values input array
+ * @param size of values array
+ * @param min of values
+ * @param max of values
+ */
+template <class T>
+void GetMinMax(const T *values, const size_t size, T &min, T &max) noexcept;
+
+/**
+ * Version for complex types of GetMinMax, gets the "doughnut" range between min
+ * and max modulus. Needed a different function as thread can't resolve the
+ * overload of a GetMinMax with complex types
+ * @param values array of complex numbers
+ * @param size of the values array
+ * @param min modulus from values
+ * @param max modulus from values
+ */
+template <class T>
+void GetMinMaxComplex(const std::complex<T> *values, const size_t size, T &min,
+                      T &max) noexcept;
+
+/**
+ * Threaded version of GetMinMax.
+ * Gets the min and max from a values array of primitive types (not including
+ * complex) using threads
+ * @param values input array of complex
+ * @param size of values array
+ * @param min of values
+ * @param max of values
+ * @param threads used for parallel computation
+ */
+template <class T>
+void GetMinMaxThreads(const T *values, const size_t size, T &min, T &max,
+                      const unsigned int threads = 1) noexcept;
+
+/**
+ * Overloaded version of GetMinMaxThreads for complex types
+ * @param values input array of complex
+ * @param size of values array
+ * @param min of values
+ * @param max of values
+ * @param threads used for parallel computation
+ */
+template <class T>
+void GetMinMaxThreads(const std::complex<T> *values, const size_t size, T &min,
+                      T &max, const unsigned int threads = 1) noexcept;
+
+/**
+ * Check if index is within (inclusive) limits
+ * lowerLimit <= index <= upperLimit
+ * @param index input to be checked
+ * @param upperLimit
+ * @param lowerLimit
+ * @return true index is within limits
+ */
+bool CheckIndexRange(const int index, const int upperLimit,
+                     const int lowerLimit = 0) noexcept;
+
+} // end namespace adios
+
+#include "adiosMath.inl"
+
+#endif /* ADIOS2_HELPER_ADIOSMATH_H_ */
diff --git a/source/adios2/helper/adiosMath.inl b/source/adios2/helper/adiosMath.inl
new file mode 100644
index 0000000000000000000000000000000000000000..b6d7dce9e8187a9802f1f947f2bd11878370064c
--- /dev/null
+++ b/source/adios2/helper/adiosMath.inl
@@ -0,0 +1,161 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMath.inl
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSMATH_INL_
+#define ADIOS2_HELPER_ADIOSMATH_INL_
+#ifndef ADIOS2_HELPER_ADIOSMATH_H_
+#error "Inline file should only be included from it's header, never on it's own"
+#endif
+
+#include <algorithm> //std::minmax_element, std::min_element, std::max_element
+#include <thread>
+
+namespace adios
+{
+
+template <class T>
+void GetMinMax(const T *values, const size_t size, T &min, T &max) noexcept
+{
+    auto bounds = std::minmax_element(values, values + size);
+    min = *bounds.first;
+    max = *bounds.second;
+}
+
+template <class T>
+void GetMinMaxComplex(const std::complex<T> *values, const size_t size, T &min,
+                      T &max) noexcept
+{
+
+    min = std::norm(values[0]);
+    max = min;
+
+    for (size_t i = 1; i < size; ++i)
+    {
+        T norm = std::norm(values[i]);
+
+        if (norm < min)
+        {
+            min = norm;
+            continue;
+        }
+
+        if (norm > max)
+        {
+            max = norm;
+        }
+    }
+
+    min = std::sqrt(min);
+    max = std::sqrt(max);
+}
+
+template <class T>
+void GetMinMaxThreads(const T *values, const size_t size, T &min, T &max,
+                      const unsigned int threads) noexcept
+{
+    if (threads == 1)
+    {
+        GetMinMax(values, size, min, max);
+        return;
+    }
+
+    const size_t stride = size / threads;    // elements per thread
+    const size_t remainder = size % threads; // remainder if not aligned
+    const size_t last = stride + remainder;
+
+    std::vector<T> mins(threads); // zero init
+    std::vector<T> maxs(threads); // zero init
+
+    std::vector<std::thread> getMinMaxThreads;
+    getMinMaxThreads.reserve(threads);
+
+    for (unsigned int t = 0; t < threads; ++t)
+    {
+        const size_t position = stride * t;
+
+        if (t == threads - 1)
+        {
+            getMinMaxThreads.push_back(
+                std::thread(adios::GetMinMax<T>, &values[position], last,
+                            std::ref(mins[t]), std::ref(maxs[t])));
+        }
+        else
+        {
+            getMinMaxThreads.push_back(
+                std::thread(adios::GetMinMax<T>, &values[position], stride,
+                            std::ref(mins[t]), std::ref(maxs[t])));
+        }
+    }
+
+    for (auto &getMinMaxThread : getMinMaxThreads)
+    {
+        getMinMaxThread.join();
+    }
+
+    auto itMin = std::min_element(mins.begin(), mins.end());
+    min = *itMin;
+
+    auto itMax = std::max_element(maxs.begin(), maxs.end());
+    max = *itMax;
+}
+
+template <class T>
+void GetMinMaxThreads(const std::complex<T> *values, const size_t size, T &min,
+                      T &max, const unsigned int threads) noexcept
+{
+    if (threads == 1)
+    {
+        GetMinMaxComplex(values, size, min, max);
+        return;
+    }
+
+    const size_t stride = size / threads;    // elements per thread
+    const size_t remainder = size % threads; // remainder if not aligned
+    const size_t last = stride + remainder;
+
+    std::vector<T> mins(threads); // zero init
+    std::vector<T> maxs(threads); // zero init
+
+    std::vector<std::thread> getMinMaxThreads;
+    getMinMaxThreads.reserve(threads);
+
+    for (unsigned int t = 0; t < threads; ++t)
+    {
+        const size_t position = stride * t;
+
+        if (t == threads - 1)
+        {
+            getMinMaxThreads.push_back(
+                std::thread(GetMinMaxComplex<T>, &values[position], last,
+                            std::ref(mins[t]), std::ref(maxs[t])));
+        }
+        else
+        {
+            getMinMaxThreads.push_back(
+                std::thread(GetMinMaxComplex<T>, &values[position], stride,
+                            std::ref(mins[t]), std::ref(maxs[t])));
+        }
+    }
+
+    for (auto &getMinMaxThread : getMinMaxThreads)
+    {
+        getMinMaxThread.join();
+    }
+
+    auto itMin = std::min_element(mins.begin(), mins.end());
+    min = *itMin;
+
+    auto itMax = std::max_element(maxs.begin(), maxs.end());
+    max = *itMax;
+}
+
+} // end namespace adios
+
+#endif /* ADIOS2_HELPER_ADIOSMATH_INL_ */
diff --git a/source/adios2/helper/adiosMemory.cpp b/source/adios2/helper/adiosMemory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5420b698d975b72c13105b86d54d5aa77eb5fa50
--- /dev/null
+++ b/source/adios2/helper/adiosMemory.cpp
@@ -0,0 +1,49 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMemory.cpp
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "adiosMemory.h"
+
+namespace adios
+{
+
+int GrowBuffer(const size_t incomingDataSize, const float growthFactor,
+               std::vector<char> &buffer, const size_t position)
+{
+    const size_t currentCapacity = buffer.capacity();
+    const size_t availableSpace = currentCapacity - position;
+    const double gf = static_cast<double>(growthFactor);
+
+    if (incomingDataSize < availableSpace)
+    {
+        return 0;
+    }
+
+    const size_t neededCapacity = incomingDataSize + position;
+    const double numerator = std::log(static_cast<double>(neededCapacity) /
+                                      static_cast<double>(currentCapacity));
+    const double denominator = std::log(gf);
+
+    const double n = std::ceil(numerator / denominator);
+    const size_t newSize =
+        static_cast<size_t>(std::ceil(std::pow(gf, n) * currentCapacity));
+
+    try
+    {
+        buffer.resize(newSize);
+    }
+    catch (std::bad_alloc &e)
+    {
+        return -1;
+    }
+
+    return 1;
+}
+
+} // end namespace adios
diff --git a/source/adios2/helper/adiosMemory.h b/source/adios2/helper/adiosMemory.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa2c6f785a95ecebae1f31db80936ffc6401cd86
--- /dev/null
+++ b/source/adios2/helper/adiosMemory.h
@@ -0,0 +1,103 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMemory.h : Memory copy operations functions using std::copy std::insert
+ * and std::memcpy
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSMEMORY_H_
+#define ADIOS2_HELPER_ADIOSMEMORY_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSTypes.h"
+
+namespace adios
+{
+
+/**
+ * Inserts source at the end of a buffer updating buffer.size()
+ * @param buffer data destination calls insert()
+ * @param source pointer to source data
+ * @param elements number of elements of source type
+ */
+template <class T>
+void InsertToBuffer(std::vector<char> &buffer, const T *source,
+                    const size_t elements = 1) noexcept;
+
+/**
+ * Copies data to a specific location in the buffer updating position
+ * Does not update vec.size().
+ * @param buffer data destination used in std::copy
+ * @param position starting position in buffer (in terms of T not bytes)
+ * @param source pointer to source data
+ * @param elements number of elements of source type
+ */
+template <class T>
+void CopyToBuffer(std::vector<char> &buffer, size_t &position, const T *source,
+                  const size_t elements = 1) noexcept;
+
+/**
+ * Copies data to a specific location in the buffer updating position using
+ * threads.
+ * Does not update vec.size().
+ * @param buffer data destination used in std::copy
+ * @param position starting position in buffer (in terms of T not bytes)
+ * @param source pointer to source data
+ * @param elements number of elements of source type
+ * @param threads number of threads sharing the copy load
+ */
+template <class T>
+void CopyToBufferThreads(std::vector<char> &buffer, size_t &position,
+                         const T *source, const size_t elements = 1,
+                         const unsigned int threads = 1) noexcept;
+
+/**
+ * Memcpy data to a specific location in the buffer updating position
+ * Does not update vec.size().
+ * @param buffer data destination used in memcpy
+ * @param position starting position in buffer (in terms of T not bytes)
+ * @param source pointer to source data
+ * @param size number of bytes from source
+ */
+template <class T>
+void MemcpyToBuffer(std::vector<char> &buffer, size_t &position,
+                    const T *source, size_t size) noexcept;
+
+/**
+ * Threaded version of MemcpyToBuffer
+ * @param buffer data destination used in memcpy
+ * @param position starting position in buffer (in terms of T not bytes)
+ * @param source pointer to source data
+ * @param size number of bytes from source
+ * @param threads number of threads sharing the memcpy load
+ */
+template <class T>
+void MemcpyToBufferThreads(std::vector<char> &buffer, size_t &position,
+                           const T *source, size_t size,
+                           const unsigned int threads = 1);
+
+/**
+ * Grows a buffer by a factor of  n . growthFactor . currentCapacity to
+ * accommodate for incomingDataSize
+ * @param incomingDataSize size of new data required to be stored in buffer
+ * @param growthFactor buffer grows in multiples of the growth buffer
+ * @param buffer to be resized
+ * @param position, current buffer position
+ * @return -1: failed to allocate (bad_alloc), 0: didn't have to allocate
+ * (enough space), 1: successful allocation
+ */
+int GrowBuffer(const size_t incomingDataSize, const float growthFactor,
+               std::vector<char> &buffer, const size_t position);
+
+} // end namespace adios
+
+#include "adiosMemory.inl"
+
+#endif /* ADIOS2_HELPER_ADIOSMEMORY_H_ */
diff --git a/source/adios2/helper/adiosMemory.inl b/source/adios2/helper/adiosMemory.inl
new file mode 100644
index 0000000000000000000000000000000000000000..949c256d54ad95879d764f9ba1fbc76f5a9540ba
--- /dev/null
+++ b/source/adios2/helper/adiosMemory.inl
@@ -0,0 +1,150 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMemory.inl definition of template functions in adiosMemory.h
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSMEMORY_INL_
+#define ADIOS2_HELPER_ADIOSMEMORY_INL_
+#ifndef ADIOS2_HELPER_ADIOSMEMORY_H_
+#error "Inline file should only be included from it's header, never on it's own"
+#endif
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <algorithm> //std::copy
+#include <cstring>   //std::memcpy
+#include <thread>
+/// \endcond
+
+namespace adios
+{
+
+template <class T>
+void InsertToBuffer(std::vector<char> &buffer, const T *source,
+                    const std::size_t elements) noexcept
+{
+    const char *src = reinterpret_cast<const char *>(source);
+    buffer.insert(buffer.end(), src, src + elements * sizeof(T));
+}
+
+template <class T>
+void CopyToBuffer(std::vector<char> &buffer, size_t &position, const T *source,
+                  const size_t elements) noexcept
+{
+    const char *src = reinterpret_cast<const char *>(source);
+    std::copy(src, src + elements * sizeof(T), buffer.begin() + position);
+    position += elements * sizeof(T);
+}
+
+template <class T>
+void CopyToBufferThreads(std::vector<char> &buffer, size_t &position,
+                         const T *source, const size_t elements,
+                         const unsigned int threads) noexcept
+{
+    if (threads == 1)
+    {
+        CopyToBuffer(buffer, position, source, elements);
+        return;
+    }
+
+    const size_t stride = elements / threads;    // elements per thread
+    const size_t remainder = elements % threads; // remainder if not aligned
+    const size_t last = stride + remainder;
+
+    std::vector<std::thread> copyThreads;
+    copyThreads.reserve(threads);
+
+    for (unsigned int t = 0; t < threads; ++t)
+    {
+        size_t bufferPosition = stride * t * sizeof(T);
+        const size_t sourcePosition = stride * t;
+
+        if (t == threads - 1) // last thread takes stride + remainder
+        {
+            copyThreads.push_back(std::thread(CopyToBuffer<T>, std::ref(buffer),
+                                              std::ref(bufferPosition),
+                                              &source[sourcePosition], last));
+            position = bufferPosition; // last position
+        }
+        else
+        {
+            copyThreads.push_back(std::thread(CopyToBuffer<T>, std::ref(buffer),
+                                              std::ref(bufferPosition),
+                                              &source[sourcePosition], stride));
+        }
+    }
+
+    for (auto &copyThread : copyThreads)
+    {
+        copyThread.join();
+    }
+}
+
+template <class T>
+void CopyFromBuffer(T *destination, size_t elements,
+                    const std::vector<char> &buffer, size_t &position) noexcept
+{
+    std::copy(buffer.begin() + position,
+              buffer.begin() + position + sizeof(T) * elements,
+              reinterpret_cast<char *>(destination));
+    position += elements * sizeof(T);
+}
+
+template <class T>
+void MemcpyToBuffer(std::vector<char> &buffer, size_t &position,
+                    const T *source, size_t size) noexcept
+{
+    std::memcpy(&buffer[position], source, size);
+    position += size;
+}
+
+template <class T>
+void MemcpyToBufferThreads(std::vector<char> &buffer, size_t &position,
+                           const T *source, size_t size,
+                           const unsigned int threads)
+{
+    if (threads == 1)
+    {
+        std::memcpy(&buffer[position], source, size);
+        return;
+    }
+
+    const size_t stride = size / threads;
+    const size_t remainder = size % threads;
+    const size_t last = stride + remainder;
+
+    std::vector<std::thread> memcpyThreads;
+    memcpyThreads.reserve(threads);
+
+    for (unsigned int t = 0; t < threads; ++t)
+    {
+        const size_t initialDestination = position + stride * t;
+        const size_t initialSource = stride * t / sizeof(T);
+
+        if (t == threads - 1)
+        {
+            memcpyThreads.push_back(std::thread(std::memcpy,
+                                                &buffer[initialDestination],
+                                                &source[initialSource], last));
+        }
+        else
+        {
+            memcpyThreads.push_back(
+                std::thread(std::memcpy, &buffer[initialDestination],
+                            &source[initialSource], stride));
+        }
+    }
+
+    for (auto &thread : memcpyThreads)
+    {
+        thread.join();
+    }
+}
+
+} // end namespace
+
+#endif /* ADIOS2_HELPER_ADIOSMEMORY_INL_ */
diff --git a/source/adios2/helper/adiosString.cpp b/source/adios2/helper/adiosString.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..69d34efd7e2d87447a3f64f0594bde7876e46c70
--- /dev/null
+++ b/source/adios2/helper/adiosString.cpp
@@ -0,0 +1,134 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosString.cpp
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "adiosString.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <fstream>
+#include <ios> //std::ios_base::failure
+#include <sstream>
+#include <stdexcept> // std::invalid_argument
+/// \endcond
+
+namespace adios
+{
+
+std::string FileToString(const std::string &fileName)
+{
+    std::ifstream fileStream(fileName);
+
+    if (!fileStream.good())
+    {
+        throw std::ios_base::failure(
+            "ERROR: file " + fileName +
+            " could not be opened. Check permissions or existence\n");
+    }
+
+    std::ostringstream fileSS;
+    fileSS << fileStream.rdbuf();
+    fileStream.close();
+    return fileSS.str();
+}
+
+Params BuildParametersMap(const std::vector<std::string> &parameters,
+                          const bool debugMode)
+{
+    auto lf_GetFieldValue = [](const std::string parameter, std::string &field,
+                               std::string &value, const bool debugMode) {
+        auto equalPosition = parameter.find("=");
+
+        if (debugMode)
+        {
+            if (equalPosition == parameter.npos)
+            {
+                throw std::invalid_argument(
+                    "ERROR: wrong format for parameter " + parameter +
+                    ", format must be field=value \n");
+            }
+
+            if (equalPosition == parameter.size() - 1)
+            {
+                throw std::invalid_argument("ERROR: empty value in parameter " +
+                                            parameter +
+                                            ", format must be field=value \n");
+            }
+        }
+
+        field = parameter.substr(0, equalPosition);
+        value = parameter.substr(equalPosition + 1); // need to test
+    };
+
+    // BODY OF FUNCTION STARTS HERE
+    Params parametersOutput;
+
+    for (const auto parameter : parameters)
+    {
+        std::string field, value;
+        lf_GetFieldValue(parameter, field, value, debugMode);
+
+        if (debugMode)
+        {
+            if (parametersOutput.count(field) == 1)
+            {
+                throw std::invalid_argument(
+                    "ERROR: parameter " + field +
+                    " already exists, must be unique\n");
+            }
+        }
+
+        parametersOutput[field] = value;
+    }
+
+    return parametersOutput;
+}
+
+std::string AddExtension(const std::string &name,
+                         const std::string extension) noexcept
+{
+    std::string result(name);
+    if (name.find(extension) != name.size() - 3)
+    {
+        result += extension;
+    }
+    return result;
+}
+
+std::vector<std::string>
+GetParametersValues(const std::string &key,
+                    const std::vector<Params> &parametersVector) noexcept
+{
+    std::vector<std::string> values;
+    values.reserve(parametersVector.size());
+
+    for (const auto &parameters : parametersVector)
+    {
+        auto itKey = parameters.find(key);
+        std::string value;
+        if (itKey != parameters.end())
+        {
+            value = itKey->second;
+        }
+        values.push_back(value);
+    }
+
+    return values;
+}
+
+void SetParameterValue(const std::string key, const Params &parameters,
+                       std::string &value) noexcept
+{
+    auto itKey = parameters.find(key);
+    if (itKey != parameters.end())
+    {
+        value = itKey->second;
+    }
+}
+
+} // end namespace adios
diff --git a/source/adios2/helper/adiosString.h b/source/adios2/helper/adiosString.h
new file mode 100644
index 0000000000000000000000000000000000000000..64f851c52e0652982bb856292cdbeaa4e36d2824
--- /dev/null
+++ b/source/adios2/helper/adiosString.h
@@ -0,0 +1,72 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosString.h string manipulation functionality
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSSTRING_H_
+#define ADIOS2_HELPER_ADIOSSTRING_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <map>
+#include <string>
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSTypes.h"
+
+namespace adios
+{
+
+/**
+ * Opens and checks for file and dumps content to a single string.
+ * @param fileName of text file
+ * @return file contents in a string
+ */
+std::string FileToString(const std::string &fileName);
+
+/**
+ * Transforms a vector to a map of parameters
+ * @param parameters vector of parameters with format "field=value"
+ * @param debugMode true=check parameters format, false=no checks
+ * @return a map with unique key=field, value=corresponding value
+ */
+Params BuildParametersMap(const std::vector<std::string> &parameters,
+                          const bool debugMode);
+
+/**
+ * Add name extension if not existing at the end of name
+ * @param name input
+ * @param extension .ext .bp
+ * @return if name already has extension returns name (name.bp), otherwise
+ * returns name.extension (name.bp)
+ */
+std::string AddExtension(const std::string &name,
+                         const std::string extension) noexcept;
+
+/**
+ * Get values for each param entry of a certain key in a vector.
+ * If key not found then string in vector is empty.
+ * @param key parameter to be extracted
+ * @param parametersVector
+ * @return vector of values, from key,value in parametersVector
+ */
+std::vector<std::string>
+GetParametersValues(const std::string &key,
+                    const std::vector<Params> &parametersVector) noexcept;
+
+/**
+ * Searches key and assign value from parameters map
+ * @param field input to look for in parameters
+ * @param parameters map with key: field, value: value
+ * @param value if found it's modified to value in parameters
+ */
+void SetParameterValue(const std::string key, const Params &parameters,
+                       std::string &value) noexcept;
+}
+
+#endif /* ADIOS2_HELPER_ADIOSSTRING_H_ */
diff --git a/source/adios2/helper/adiosSystem.cpp b/source/adios2/helper/adiosSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9836130796bb035d886d0d8c60bd334c20748ac5
--- /dev/null
+++ b/source/adios2/helper/adiosSystem.cpp
@@ -0,0 +1,80 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosSystem.cpp implementation of adiosSystem.h functions
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+#include "adiosSystem.h"
+
+#include <sys/stat.h>  //stat, mkdir
+#include <sys/types.h> //CreateDirectory
+#include <unistd.h>    //CreateDirectory
+
+#include <chrono> //system_clock, now
+#include <ctime>  //std::ctime
+
+#include "adios2/ADIOSTypes.h"
+
+namespace adios
+{
+
+bool CreateDirectory(const std::string &fullPath) noexcept
+{
+    auto lf_Mkdir = [](const std::string directory, struct stat &st) -> bool {
+        if (stat(directory.c_str(), &st) == -1) // doesn't exist
+        {
+            mkdir(directory.c_str(), 0777);
+            if (stat(directory.c_str(), &st) == -1) // doesn't exist
+            {
+                return false;
+            }
+        }
+        return true;
+    };
+
+    bool directoryExists = false;
+    auto directoryPosition = fullPath.find("/");
+
+    if (fullPath[0] == '/' || fullPath[0] == '.')
+    { // find the second '/'
+        directoryPosition = fullPath.find("/", directoryPosition + 1);
+    }
+
+    struct stat st = {0};
+    if (directoryPosition == fullPath.npos) // no subdirectories
+    {
+        directoryExists = lf_Mkdir(fullPath.c_str(), st);
+    }
+    else
+    {
+        std::string directory(fullPath.substr(0, directoryPosition));
+        lf_Mkdir(directory.c_str(), st);
+
+        while (directoryPosition != fullPath.npos)
+        {
+            directoryPosition = fullPath.find("/", directoryPosition + 1);
+            directory = fullPath.substr(0, directoryPosition);
+            directoryExists = lf_Mkdir(directory.c_str(), st);
+        }
+    }
+    return directoryExists;
+}
+
+bool IsLittleEndian() noexcept
+{
+    uint16_t hexa = 0x1234;
+    return *reinterpret_cast<uint8_t *>(&hexa) != 0x12; // NOLINT
+}
+
+std::string LocalTimeDate() noexcept
+{
+    std::time_t now =
+        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+
+    return std::string(std::ctime(&now));
+}
+
+} // end namespace adios
diff --git a/source/adios2/helper/adiosSystem.h b/source/adios2/helper/adiosSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..9374d160370839377b6c4897f3b489fbb850216e
--- /dev/null
+++ b/source/adios2/helper/adiosSystem.h
@@ -0,0 +1,46 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosSystem.h  system related functions using std or POSIX,
+ * we might wait for C++17 filesystem
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSSYSTEM_H_
+#define ADIOS2_HELPER_ADIOSSYSTEM_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <string>
+#include <vector>
+/// \endcond
+
+namespace adios
+{
+
+/**
+ * Creates a chain of directories using POSIX systems calls (stat, mkdir),
+ * Verifies if directory exists before creating a new one. Permissions are 777
+ * for now
+ * @param fullPath /full/path/for/directory
+ * @return true: directory exists, false: failed to create or access directory
+ */
+bool CreateDirectory(const std::string &fullPath) noexcept;
+
+/**
+ * Check if system is little endian
+ * @return true: little endian, false: big endian
+ */
+bool IsLittleEndian() noexcept;
+
+/**
+ * returns a string with current local time and date information from std::ctime
+ * @return string from char* std::ctime
+ */
+std::string LocalTimeDate() noexcept;
+
+} // end namespace adios
+
+#endif /* ADIOS2_HELPER_ADIOSSYSTEM_H_ */
diff --git a/source/adios2/helper/adiosType.cpp b/source/adios2/helper/adiosType.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5d3e3430fa5d03d943c85cd0d44f30b1581f1e8
--- /dev/null
+++ b/source/adios2/helper/adiosType.cpp
@@ -0,0 +1,215 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosType.cpp
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "adiosType.h"
+#include "adiosType.inl"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <algorithm> //std::transform, std::count
+#include <sstream>
+/// \endcond
+
+namespace adios
+{
+
+std::string DimsToCSV(const Dims &dimensions) noexcept
+{
+    std::string dimsCSV;
+
+    for (const auto dimension : dimensions)
+    {
+        dimsCSV += std::to_string(dimension) + ",";
+    }
+
+    if (!dimsCSV.empty())
+    {
+        dimsCSV.pop_back(); // remove last comma
+    }
+
+    return dimsCSV;
+}
+
+std::vector<int> CSVToVectorInt(const std::string csv) noexcept
+{
+    std::vector<int> numbers;
+    if (csv.empty())
+    {
+        return numbers;
+    }
+
+    if (csv.find(",") == csv.npos) // if no commas, one int
+    {
+        numbers.push_back(std::stoi(csv)); // might need to be checked
+    }
+    else
+    {
+        int count = std::count(csv.begin(), csv.end(), ',');
+        numbers.reserve(count);
+
+        std::istringstream csvSS(csv);
+        std::string value;
+        while (std::getline(csvSS, value, ','))
+        {
+            numbers.push_back(std::stoi(csv));
+        }
+    }
+
+    return numbers;
+}
+
+void ConvertUint64VectorToSizetVector(const std::vector<uint64_t> &in,
+                                      std::vector<size_t> &out) noexcept
+{
+    out.resize(in.size());
+    std::transform(in.begin(), in.end(), out.begin(),
+                   [](uint64_t value) { return static_cast<size_t>(value); });
+}
+
+void Uint64ArrayToSizetVector(const size_t nElements, const uint64_t *in,
+                              std::vector<size_t> &out) noexcept
+{
+    out.resize(nElements);
+    for (size_t i = 0; i < nElements; i++)
+    {
+        out[i] = static_cast<size_t>(in[i]);
+    }
+}
+
+std::vector<std::size_t> Uint64ArrayToSizetVector(const size_t nElements,
+                                                  const uint64_t *in) noexcept
+{
+    std::vector<size_t> out(nElements);
+    for (size_t i = 0; i < nElements; i++)
+    {
+        out[i] = static_cast<size_t>(in[i]);
+    }
+    return out;
+}
+
+std::vector<std::size_t>
+Uint64VectorToSizetVector(const std::vector<uint64_t> &in) noexcept
+{
+    std::vector<size_t> out(in.size());
+    out.resize(in.size());
+    std::transform(in.begin(), in.end(), out.begin(),
+                   [](uint64_t value) { return static_cast<size_t>(value); });
+
+    return out;
+}
+
+TimeUnit StringToTimeUnit(const std::string timeUnitString,
+                          const bool debugMode)
+{
+    TimeUnit timeUnit = TimeUnit::Microseconds; // default
+
+    if (timeUnitString == "Microseconds")
+    {
+        timeUnit = TimeUnit::Microseconds;
+    }
+    else if (timeUnitString == "Milliseconds")
+    {
+        timeUnit = TimeUnit::Milliseconds;
+    }
+    else if (timeUnitString == "Seconds")
+    {
+        timeUnit = TimeUnit::Seconds;
+    }
+    else if (timeUnitString == "Minutes")
+    {
+        timeUnit = TimeUnit::Minutes;
+    }
+    else if (timeUnitString == "Hours")
+    {
+        timeUnit = TimeUnit::Hours;
+    }
+    else
+    {
+        if (debugMode)
+        {
+            throw std::invalid_argument("ERROR: profile_units=value "
+                                        " must be Microseconds, Milliseconds, "
+                                        "Seconds, Minutes or Hours\n");
+        }
+    }
+    return timeUnit;
+}
+
+size_t BytesFactor(const std::string units, const bool debugMode)
+{
+    size_t factor = 1; // bytes
+    if (units == "Gb")
+    {
+        factor = 1024 * 1024 * 1024;
+    }
+    else if (units == "Mb")
+    {
+        factor = 1024 * 1024;
+    }
+    else if (units == "Kb")
+    {
+        factor = 1024;
+    }
+    else if (units == "b" || units == "bytes")
+    {
+        // do nothing
+    }
+    else
+    {
+        if (debugMode)
+        {
+            throw std::invalid_argument("ERROR: units " + units +
+                                        " not supported\n");
+        }
+    }
+    return factor;
+}
+
+std::string OpenModeToString(const OpenMode openMode,
+                             const bool oneLetter) noexcept
+{
+    std::string openModeString;
+
+    if (openMode == OpenMode::Write)
+    {
+        if (oneLetter)
+        {
+            openModeString = "w";
+        }
+        else
+        {
+            openModeString = "Write";
+        }
+    }
+    else if (openMode == OpenMode::Append)
+    {
+        if (oneLetter)
+        {
+            openModeString = "a";
+        }
+        else
+        {
+            openModeString = "Append";
+        }
+    }
+    else if (openMode == OpenMode::Read)
+    {
+        if (oneLetter)
+        {
+            openModeString = "r";
+        }
+        else
+        {
+            openModeString = "Read";
+        }
+    }
+    return openModeString;
+}
+
+} // end namespace adios
diff --git a/source/adios2/helper/adiosType.h b/source/adios2/helper/adiosType.h
new file mode 100644
index 0000000000000000000000000000000000000000..d98d9a4f95eff007df21a3e2bbbc6fffb611d4e1
--- /dev/null
+++ b/source/adios2/helper/adiosType.h
@@ -0,0 +1,114 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosType.h helper functions for types: conversion, mapping, etc.
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSTYPE_H_
+#define ADIOS2_HELPER_ADIOSTYPE_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSTypes.h"
+
+namespace adios
+{
+
+/**
+ * Gets type from template parameter T
+ * @return string with type
+ */
+template <class T>
+inline std::string GetType() noexcept;
+
+/**
+ * Check in types set if "type" is one of the aliases for a certain type,
+ * (e.g. if type = integer is an accepted alias for "int", returning true)
+ * @param type input to be compared with an alias
+ * @param aliases set containing aliases to a certain type, typically
+ * Support::DatatypesAliases from Support.h
+ * @return true: is an alias, false: is not
+ */
+template <class T>
+bool IsTypeAlias(
+    const std::string type,
+    const std::map<std::string, std::set<std::string>> &aliases) noexcept;
+
+/**
+ * Converts a vector of dimensions to a CSV string
+ * @param dims vector of dimensions
+ * @return comma separate value (CSV)
+ */
+std::string DimsToCSV(const Dims &dimensions) noexcept;
+
+/**
+ * Converts comma-separated values (csv) to a vector of integers
+ * @param csv "1,2,3"
+ * @return vector<int> = { 1, 2, 3 }
+ */
+std::vector<int> CSVToVectorInt(const std::string csv) noexcept;
+
+/**
+ * Convert a vector of uint64_t element into size_t
+ * @param in  uint64_t vector
+ * @param out size_t vector with contents of in
+ */
+void ConvertUint64VectorToSizetVector(const std::vector<uint64_t> &in,
+                                      std::vector<size_t> &out) noexcept;
+
+/** Convert a C array of uint64_t elements to a vector of std::size_t elements
+ *  @param number of elements
+ *  @param input array of uint64_t elements
+ *  @param vector of std::size_t elements. It will be resized to nElements.
+ */
+void Uint64ArrayToSizetVector(const size_t nElements, const uint64_t *in,
+                              std::vector<size_t> &out) noexcept;
+
+/** Convert a C array of uint64_t elements to a vector of std::size_t elements
+ *  @param number of elements
+ *  @param input array of uint64_t elements
+ *  @return vector of std::size_t elements
+ */
+std::vector<size_t> Uint64ArrayToSizetVector(const size_t nElements,
+                                             const uint64_t *in) noexcept;
+
+/**
+ * Converts a recognized time unit string to TimeUnit enum
+ * @param timeUnit string with acceptable time unit
+ * @param debugMode true: throw exception if timeUnitString not valid
+ * @return TimeUnit enum (int) TimeUnit::s, TimeUnit::ms, etc.
+ */
+TimeUnit StringToTimeUnit(const std::string timeUnitString,
+                          const bool debugMode);
+
+/**
+ * Returns the conversion factor from input units Tb, Gb, Mb, Kb, to bytes as a
+ * factor of 1024
+ * @param units input
+ * @param debugMode true: check if input units are valid
+ * @return conversion factor to bytes, size_t
+ */
+size_t BytesFactor(const std::string units, const bool debugMode);
+
+/**
+ * Returns open mode as a string
+ * @param openMode from ADIOSTypes.h
+ * @param oneLetter if true returns a one letter version ("w", "a" or "r")
+ * @return string with open mode
+ */
+std::string OpenModeToString(const OpenMode openMode,
+                             const bool oneLetter = false) noexcept;
+}
+
+#include "adiosType.inl"
+
+#endif /* ADIOS2_HELPER_ADIOSTYPE_H_ */
diff --git a/source/adios2/helper/adiosType.inl b/source/adios2/helper/adiosType.inl
new file mode 100644
index 0000000000000000000000000000000000000000..cb8424259ed3e6e6725932a0a11d7f8e04b3420c
--- /dev/null
+++ b/source/adios2/helper/adiosType.inl
@@ -0,0 +1,132 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosType.inl implementation of template functions in adiosType.h
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSTYPE_INL_
+#define ADIOS2_HELPER_ADIOSTYPE_INL_
+#ifndef ADIOS2_HELPER_ADIOSTYPE_H_
+#error "Inline file should only be included from it's header, never on it's own"
+#endif
+
+namespace adios
+{
+
+template <class T>
+inline std::string GetType() noexcept
+{
+    return "compound";
+}
+template <>
+inline std::string GetType<void>() noexcept
+{
+    return "unknown";
+}
+template <>
+inline std::string GetType<char>() noexcept
+{
+    return "char";
+}
+template <>
+inline std::string GetType<unsigned char>() noexcept
+{
+    return "unsigned char";
+}
+template <>
+inline std::string GetType<short>() noexcept
+{
+    return "short";
+}
+template <>
+inline std::string GetType<unsigned short>() noexcept
+{
+    return "unsigned short";
+}
+template <>
+inline std::string GetType<int>() noexcept
+{
+    return "int";
+}
+template <>
+inline std::string GetType<unsigned int>() noexcept
+{
+    return "unsigned int";
+}
+template <>
+inline std::string GetType<long int>() noexcept
+{
+    return "long int";
+}
+template <>
+inline std::string GetType<unsigned long int>() noexcept
+{
+    return "unsigned long int";
+}
+template <>
+inline std::string GetType<long long int>() noexcept
+{
+    return "long long int";
+}
+template <>
+inline std::string GetType<unsigned long long int>() noexcept
+{
+    return "unsigned long long int";
+}
+template <>
+inline std::string GetType<float>() noexcept
+{
+    return "float";
+}
+template <>
+inline std::string GetType<double>() noexcept
+{
+    return "double";
+}
+template <>
+inline std::string GetType<long double>() noexcept
+{
+    return "long double";
+}
+template <>
+inline std::string GetType<std::complex<float>>() noexcept
+{
+    return "float complex";
+}
+template <>
+inline std::string GetType<std::complex<double>>() noexcept
+{
+    return "double complex";
+}
+template <>
+inline std::string GetType<std::complex<long double>>() noexcept
+{
+    return "long double complex";
+}
+
+template <class T>
+bool IsTypeAlias(
+    const std::string type,
+    const std::map<std::string, std::set<std::string>> &aliases) noexcept
+{
+    if (type == GetType<T>()) // is key itself
+    {
+        return true;
+    }
+
+    bool isAlias = false;
+    if (aliases.at(GetType<T>()).count(type) == 1)
+    {
+        isAlias = true;
+    }
+
+    return isAlias;
+}
+
+} // end namespace adios
+
+#endif /* ADIOS2_HELPER_ADIOSTYPE_INL_ */
diff --git a/source/adios2/core/adiosFunctions.cpp b/source/adios2/helper/adiosXML.cpp
similarity index 56%
rename from source/adios2/core/adiosFunctions.cpp
rename to source/adios2/helper/adiosXML.cpp
index ad8ed6ca418d9ecace76b1c8ffff325de851f26c..746a436145472b910e58d2dccec7e6adc8b9d363 100644
--- a/source/adios2/core/adiosFunctions.cpp
+++ b/source/adios2/helper/adiosXML.cpp
@@ -2,61 +2,21 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * adiosFunctions.cpp
+ * adiosXML.cpp
  *
- *  Created on: Oct 10, 2016
- *      Author: wfg
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#include "adiosFunctions.h"
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <sys/stat.h>  //stat
-#include <sys/types.h> //CreateDirectory
-#include <unistd.h>    //CreateDirectory
+#include "adiosXML.h"
 
-#include <algorithm> //std::count
-#include <cmath>     // std::ceil, std::pow, std::log
-#include <cstring>   //std::memcpy
-#include <fstream>
-#include <ios> //std::ios_base::failure
-#include <sstream>
-#include <stdexcept>
-#include <thread> //std::thread
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <stdexcept> //std::invalid_argument
 /// \endcond
 
-#include "adios2/ADIOSMPI.h"
-#include "adios2/ADIOSTypes.h"
-#include "adios2/core/Support.h"
-
-#ifdef ADIOS2_HAVE_BZIP2
-#include "adios2/transform/BZip2.h"
-#endif
-
 namespace adios
 {
 
-void DumpFileToString(const std::string fileName, std::string &fileContent)
-{
-    std::ifstream fileStream(fileName);
-
-    if (fileStream.good() == false)
-    { // check file
-        throw std::ios_base::failure(
-            "ERROR: file " + fileName +
-            " could not be opened. Check permissions or file existence\n");
-    }
-
-    std::ostringstream fileSS;
-    fileSS << fileStream.rdbuf();
-    fileStream.close();
-    fileContent = fileSS.str(); // convert to string and check
-
-    if (fileContent.empty())
-    {
-        throw std::invalid_argument("ERROR: file " + fileName + " is empty\n");
-    }
-}
-
 void GetSubString(const std::string initialTag, const std::string finalTag,
                   const std::string content, std::string &subString,
                   std::string::size_type &currentPosition)
@@ -96,7 +56,7 @@ void GetSubString(const std::string initialTag, const std::string finalTag,
     // find next
     bool isValue = true;
 
-    while (isValue == true)
+    while (isValue)
     {
         std::string::size_type singleQuotePosition =
             content.find('\'', currentPosition);
@@ -273,13 +233,13 @@ void GetPairsFromTag(
 //        if( pair.first == "host-language" )
 //            hostLanguage = pair.second;
 //
-//    if( debugMode == true )
+//    if( debugMode )
 //    {
 //        if( Support::HostLanguages.count( hostLanguage ) == 0 )
 //            throw std::invalid_argument("ERROR: host language " + hostLanguage
 //            + " not supported.\n" );
 //
-//        if( hostLanguage.empty() == true )
+//        if( hostLanguage.empty() )
 //            throw std::invalid_argument("ERROR: host language is empty.\n" );
 //    }
 //
@@ -298,7 +258,7 @@ void GetPairsFromTag(
 //        //get group name
 //        std::string::size_type groupPosition( 0 );
 //        GetSubString( "<adios-group ", ">", xmlGroup, tag, groupPosition );
-//        if( debugMode == true )
+//        if( debugMode )
 //        {
 //            if( tag.size() < 2 )
 //                throw std::invalid_argument( "ERROR: wrong tag " + tag + " in
@@ -315,7 +275,7 @@ void GetPairsFromTag(
 //                groupName = pair.second;
 //        }
 //
-//        if( debugMode == true )
+//        if( debugMode )
 //        {
 //            if( groupName.empty() )
 //                throw std::invalid_argument( "ERROR: group name not found. \n"
@@ -341,11 +301,11 @@ void GetPairsFromTag(
 //                            const bool debugMode, int& field )
 //    {
 //        field = 0;
-//        if( fieldStr.empty() == false )
+//        if( !fieldStr.empty())
 //        {
 //            field = std::stoi( fieldStr ); //throws invalid_argument
 //
-//            if( debugMode == true )
+//            if( debugMode )
 //            {
 //                if( field < 0 )
 //                    throw std::invalid_argument("ERROR: " + fieldName + " in
@@ -375,7 +335,7 @@ void GetPairsFromTag(
 //        }
 //
 //        auto itGroup = groups.find( groupName );
-//        if( debugMode == true )
+//        if( debugMode )
 //        {
 //            if( itGroup == groups.end() ) //not found
 //                throw std::invalid_argument( "ERROR: in transport " + method +
@@ -433,294 +393,4 @@ void GetPairsFromTag(
 //    groups );
 //}
 
-std::size_t GetTotalSize(const std::vector<std::size_t> &dimensions)
-{
-    std::size_t product = 1;
-
-    for (const auto dimension : dimensions)
-    {
-        product *= dimension;
-    }
-
-    return product;
-}
-
-void CreateDirectory(const std::string fullPath) noexcept
-{
-    auto lf_Mkdir = [](const std::string directory, struct stat &st) {
-        if (stat(directory.c_str(), &st) == -1)
-        {
-            mkdir(directory.c_str(), 0777);
-        }
-    };
-
-    auto directoryPosition = fullPath.find("/");
-
-    if (fullPath[0] == '/' || fullPath[0] == '.')
-    { // find the second '/'
-        directoryPosition = fullPath.find("/", directoryPosition + 1);
-    }
-
-    struct stat st = {0};
-    if (directoryPosition == fullPath.npos) // no subdirectories
-    {
-        lf_Mkdir(fullPath.c_str(), st);
-        return;
-    }
-
-    std::string directory(fullPath.substr(0, directoryPosition));
-    lf_Mkdir(directory.c_str(), st);
-
-    while (directoryPosition != fullPath.npos)
-    {
-        directoryPosition = fullPath.find("/", directoryPosition + 1);
-        directory = fullPath.substr(0, directoryPosition);
-        lf_Mkdir(directory.c_str(), st);
-    }
-}
-
-void SetTransformsHelper(const std::vector<std::string> &transformNames,
-                         std::vector<std::shared_ptr<Transform>> &transforms,
-                         const bool debugMode,
-                         std::vector<short> &transformIndices,
-                         std::vector<short> &parameters)
-{
-    // function to get a parameter from "method:parameter"
-    auto lf_GetParameter = [](const std::string transformName,
-                              std::string &transformMethod,
-                              const bool debugMode) -> short {
-        short parameter = -1;
-        auto colonPosition = transformName.find(":");
-
-        if (colonPosition != transformName.npos)
-        {
-            if (debugMode == true)
-            {
-                if (colonPosition == transformName.size() - 1)
-                {
-                    throw std::invalid_argument(
-                        "ERROR: wrong format for transform " + transformName +
-                        ", in call to SetTransform\n");
-                }
-            }
-
-            transformMethod = transformName.substr(0, colonPosition);
-            parameter = std::stoi(
-                transformName.substr(colonPosition + 1)); // need to test
-        }
-        return parameter;
-    };
-
-    // Get transform index from transforms, if not found return -1
-    auto lf_GetTransformIndex =
-        [](const std::string transformMethod,
-           const std::vector<std::shared_ptr<Transform>> &transforms) -> short {
-        short transformIndex = -1;
-        for (unsigned int i = 0; i < transforms.size(); ++i)
-        {
-            if (transforms[i]->m_Method == transformMethod)
-            {
-                transformIndex = i;
-                break;
-            }
-        }
-        return transformIndex;
-    };
-
-    // BODY of FUNCTION STARTS HERE
-    for (const std::string transformName : transformNames)
-    {
-        std::string transformMethod(transformName);
-        short parameter =
-            lf_GetParameter(transformName, transformMethod,
-                            debugMode); // from transform = "method:parameter"
-        short transformIndex =
-            lf_GetTransformIndex(transformMethod, transforms);
-
-        if (transformIndex == -1) // not found, then create a new transform
-        {
-            if (transformMethod == "bzip2")
-            {
-#ifdef ADIOS2_HAVE_BZIP2
-                transforms.push_back(
-                    std::make_shared<adios::transform::BZip2>());
-#endif
-            }
-
-            transformIndex = static_cast<short>(transforms.size() - 1);
-        }
-        transformIndices.push_back(transformIndex);
-        parameters.push_back(parameter);
-    }
-}
-
-std::map<std::string, std::string>
-BuildParametersMap(const std::vector<std::string> &parameters,
-                   const bool debugMode)
-{
-    auto lf_GetFieldValue = [](const std::string parameter, std::string &field,
-                               std::string &value, const bool debugMode) {
-        auto equalPosition = parameter.find("=");
-
-        if (debugMode == true)
-        {
-            if (equalPosition == parameter.npos)
-            {
-                throw std::invalid_argument(
-                    "ERROR: wrong format for parameter " + parameter +
-                    ", format must be field=value \n");
-            }
-
-            if (equalPosition == parameter.size() - 1)
-            {
-                throw std::invalid_argument("ERROR: empty value in parameter " +
-                                            parameter +
-                                            ", format must be field=value \n");
-            }
-        }
-
-        field = parameter.substr(0, equalPosition);
-        value = parameter.substr(equalPosition + 1); // need to test
-    };
-
-    // BODY OF FUNCTION STARTS HERE
-    std::map<std::string, std::string> parametersOutput;
-
-    for (const auto parameter : parameters)
-    {
-        std::string field, value;
-        lf_GetFieldValue(parameter, field, value, debugMode);
-
-        if (debugMode == true)
-        {
-            if (parametersOutput.count(field) == 1)
-            {
-                throw std::invalid_argument(
-                    "ERROR: parameter " + field +
-                    " already exists, must be unique\n");
-            }
-        }
-
-        parametersOutput[field] = value;
-    }
-
-    return parametersOutput;
-}
-
-std::vector<int> CSVToVectorInt(const std::string csv)
-{
-    std::vector<int> numbers;
-    if (csv.empty())
-    {
-        return numbers;
-    }
-
-    if (csv.find(",") == csv.npos) // check if no commas, one int
-    {
-        numbers.push_back(std::stoi(csv)); // might need to be checked
-    }
-    else
-    {
-        int count = std::count(csv.begin(), csv.end(), ',');
-        numbers.reserve(count);
-
-        std::istringstream csvSS(csv);
-        std::string value;
-        while (std::getline(csvSS, value, ',')) // need to test
-        {
-            numbers.push_back(std::stoi(csv));
-        }
-    }
-
-    return numbers;
-}
-
-std::string DimsToCSV(const std::vector<std::size_t> &dims)
-{
-    std::string dimsCSV;
-
-    for (const auto dim : dims)
-    {
-        dimsCSV += std::to_string(dim) + ",";
-    }
-
-    if (dimsCSV.empty() == false)
-    {
-        dimsCSV.pop_back();
-    }
-
-    return dimsCSV;
-}
-
-void ConvertUint64VectorToSizetVector(const std::vector<std::uint64_t> &in,
-                                      std::vector<std::size_t> &out)
-{
-    out.clear();
-    out.reserve(in.size());
-    for (const auto inElement : in)
-    {
-        out.push_back(static_cast<std::size_t>(inElement));
-    }
-}
-
-void Uint64ArrayToSizetVector(const std::size_t nElements, const uint64_t *in,
-                              std::vector<std::size_t> &out)
-{
-    out.resize(nElements);
-    for (std::size_t i = 0; i < nElements; i++)
-    {
-        out[i] = static_cast<std::size_t>(in[i]);
-    }
-}
-
-std::vector<std::size_t> Uint64ArrayToSizetVector(const std::size_t nElements,
-                                                  const uint64_t *in)
-{
-    std::vector<std::size_t> out(nElements);
-    for (std::size_t i = 0; i < nElements; i++)
-    {
-        out[i] = static_cast<std::size_t>(in[i]);
-    }
-    return out;
-}
-
-int GrowBuffer(const size_t incomingDataSize, const float growthFactor,
-               std::vector<char> &buffer, const size_t position)
-{
-    const size_t currentCapacity = buffer.capacity();
-    const size_t availableSpace = currentCapacity - position;
-    const double gf = static_cast<double>(growthFactor);
-
-    if (incomingDataSize < availableSpace)
-    {
-        return 0;
-    }
-
-    const size_t neededCapacity = incomingDataSize + position;
-    const double numerator = std::log(static_cast<double>(neededCapacity) /
-                                      static_cast<double>(currentCapacity));
-    const double denominator = std::log(gf);
-
-    const double n = std::ceil(numerator / denominator);
-    const size_t newSize =
-        static_cast<size_t>(std::ceil(std::pow(gf, n) * currentCapacity));
-
-    try
-    {
-        buffer.resize(newSize);
-    }
-    catch (std::bad_alloc &e)
-    {
-        return -1;
-    }
-
-    return 1;
-}
-
-bool IsLittleEndian() noexcept
-{
-    uint16_t hexa = 0x1234;
-    return *reinterpret_cast<uint8_t *>(&hexa) != 0x12; // NOLINT
-}
-
-} // namespace adios
+} // end namespace adios
diff --git a/source/adios2/helper/adiosXML.h b/source/adios2/helper/adiosXML.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3df2990549ed646f2f66457e82a3b2ec5ad55f0
--- /dev/null
+++ b/source/adios2/helper/adiosXML.h
@@ -0,0 +1,106 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosXML.h basic XML parsing functionality for ADIOS config file schema
+ *
+ *  Created on: May 17, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOSXML_H_
+#define ADIOS2_HELPER_ADIOSXML_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <string>
+#include <utility> //std::pair
+#include <vector>
+/// \endcond
+
+namespace adios
+{
+
+/**
+ * Extracts a substring between two tags from content
+ * @param initialTag
+ * @param finalTag
+ * @param content full string
+ * @param subString if found return substring between initialTag and finalTag,
+ * otherwise returns empty
+ * @param currentPosition to start the search, moved forward to finalTag
+ * position
+ */
+void GetSubString(const std::string initialTag, const std::string finalTag,
+                  const std::string content, std::string &subString,
+                  std::string::size_type &currentPosition);
+
+/**
+ * Extracts the value inside quotes in a string currentTag ( Example: currentTag
+ * --> field1="value1" field2="value2" )
+ * @param quote double " or single '
+ * @param quotePosition position of the opening quote in currentTag
+ * @param currentTag initial tag value, modified by cutting the first found " "
+ * portion, currentTag --> field2="value2"
+ * @param value value1 in the example above
+ */
+void GetQuotedValue(const char quote,
+                    const std::string::size_type &quotePosition,
+                    std::string &currentTag, std::string &value);
+
+/**
+ * Get attributes field1="value1" field2="value2" by looping through a single
+ * XML tag
+ * @param tag field0="value0" field1="value1" in a single string
+ * @param pairs pairs[0].first=field0 pairs[0].second=value0
+ * pairs[1].first=field1 pairs[1].second=value1
+ */
+void GetPairs(const std::string tag,
+              std::vector<std::pair<const std::string, const std::string>>
+                  &pairs) noexcept;
+
+/**
+ * Determine tag type and call GetPairs to populate pairs
+ * @param fileContent file Content in a single string
+ * @param tag field0="value0" field1="value1" in a single string
+ * @param pairs pairs[0].first=field0 pairs[0].second=value0
+ * pairs[1].first=field1 pairs[1].second=value1
+ */
+void GetPairsFromTag(
+    const std::string &fileContent, const std::string tag,
+    std::vector<std::pair<const std::string, const std::string>> &pairs);
+
+/**
+ * Set members m_Groups and m_HostLanguage from XML file content, called within
+ * Init functions
+ * @param fileContent file Content in a single string
+ * @param mpiComm MPI Communicator passed from application passed to Transport
+ * method if required
+ * @param hostLanguage return the host language from fileContent
+ * @param transforms return the modified transforms vector if there are
+ * variables with transformations
+ * @param groups passed returns the map of groups defined in fileContent
+ */
+// void SetMembers( const std::string& fileContent, const MPI_Comm mpiComm,
+//                 std::string& hostLanguage, std::vector<
+//                 std::shared_ptr<Transform> >& transforms,
+//                 std::map< std::string, Group >& groups );
+
+/**
+ * Called inside the ADIOS XML constructors to get contents from file, broadcast
+ * and set hostLanguage and groups from ADIOS class
+ * @param xmlConfigFile xml config file name
+ * @param mpiComm communicator used from broadcasting
+ * @param debugMode from ADIOS m_DebugMode passed to CGroup in groups
+ * @param hostLanguage set from host-language in xml file
+ * @param transforms return the modified transforms vector if there are
+ * variables with transformations
+ * @param groups passed returns the map of groups defined in fileContent
+ */
+// void InitXML( const std::string xmlConfigFile, const MPI_Comm mpiComm, const
+// bool debugMode,
+//              std::string& hostLanguage, std::vector<
+//              std::shared_ptr<Transform> >& transforms,
+//              std::map< std::string, Group >& groups );
+}
+
+#endif /* ADIOS2_HELPER_ADIOSXML_H_ */
diff --git a/source/adios2/core/Capsule.cpp b/source/adios2/toolkit/capsule/Capsule.cpp
similarity index 100%
rename from source/adios2/core/Capsule.cpp
rename to source/adios2/toolkit/capsule/Capsule.cpp
diff --git a/source/adios2/core/Capsule.h b/source/adios2/toolkit/capsule/Capsule.h
similarity index 88%
rename from source/adios2/core/Capsule.h
rename to source/adios2/toolkit/capsule/Capsule.h
index 51e7098dc61899e59b65a814f9c0785a877a337f..fc90bd09023e82034b36dec61b3f70843aaebe64 100644
--- a/source/adios2/core/Capsule.h
+++ b/source/adios2/toolkit/capsule/Capsule.h
@@ -5,17 +5,18 @@
  * Capsule.h
  *
  *  Created on: Dec 7, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#ifndef ADIOS2_CORE_CAPSULE_H_
-#define ADIOS2_CORE_CAPSULE_H_
+#ifndef ADIOS2_TOOLKIT_CAPSULE_CAPSULE_H_
+#define ADIOS2_TOOLKIT_CAPSULE_CAPSULE_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
 #include <string>
 /// \endcond
 
 #include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSTypes.h"
 
 namespace adios
 {
@@ -67,4 +68,4 @@ protected:
 
 } // end namespace
 
-#endif /* ADIOS2_CORE_CAPSULE_H_ */
+#endif /* ADIOS2_TOOLKIT_CAPSULE_CAPSULE_H_ */
diff --git a/source/adios2/capsule/heap/STLVector.cpp b/source/adios2/toolkit/capsule/heap/STLVector.cpp
similarity index 96%
rename from source/adios2/capsule/heap/STLVector.cpp
rename to source/adios2/toolkit/capsule/heap/STLVector.cpp
index 2873f3f0f4d4b9e7e1d2c32414d21239e40d8ee8..b5df6541a1e4e6ca0738b2e5bdab80ca792e20f8 100644
--- a/source/adios2/capsule/heap/STLVector.cpp
+++ b/source/adios2/toolkit/capsule/heap/STLVector.cpp
@@ -35,7 +35,7 @@ size_t STLVector::GetMetadataSize() const { return m_Metadata.size(); }
 
 void STLVector::ResizeData(const size_t size)
 {
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         try
         {
@@ -56,7 +56,7 @@ void STLVector::ResizeData(const size_t size)
 
 void STLVector::ResizeMetadata(const size_t size)
 {
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         try
         {
diff --git a/source/adios2/capsule/heap/STLVector.h b/source/adios2/toolkit/capsule/heap/STLVector.h
similarity index 88%
rename from source/adios2/capsule/heap/STLVector.h
rename to source/adios2/toolkit/capsule/heap/STLVector.h
index ae00013690608e90a87597a6a52185ad08a8c0c1..f4c7c4bc165bd6bc9cd855ec54150f7d66750787 100644
--- a/source/adios2/capsule/heap/STLVector.h
+++ b/source/adios2/toolkit/capsule/heap/STLVector.h
@@ -8,15 +8,15 @@
  *      Author: wfg
  */
 
-#ifndef ADIOS2_CAPSULE_HEAP_STLVECTOR_H_
-#define ADIOS2_CAPSULE_HEAP_STLVECTOR_H_
+#ifndef ADIOS2_TOOLKIT_CAPSULE_HEAP_STLVECTOR_H_
+#define ADIOS2_TOOLKIT_CAPSULE_HEAP_STLVECTOR_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
 #include <vector>
 /// \endcond
 
 #include "adios2/ADIOSConfig.h"
-#include "adios2/core/Capsule.h"
+#include "adios2/toolkit/capsule/Capsule.h"
 
 namespace adios
 {
diff --git a/source/adios2/capsule/shmem/ShmSystemV.cpp b/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp
similarity index 97%
rename from source/adios2/capsule/shmem/ShmSystemV.cpp
rename to source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp
index 4562cbc0e96e62508d42622af4182151129d614c..f746517180fab2dcc1a56ab6aac72976e21d9fb5 100644
--- a/source/adios2/capsule/shmem/ShmSystemV.cpp
+++ b/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp
@@ -10,7 +10,7 @@
 
 #include "ShmSystemV.h"
 
-#include <sys/shm.h>
+#include <sys/shm.h> //shmget
 
 /// \cond EXCLUDE_FROM_DOXYGEN
 #include <ios> //std::ios_base::failure
@@ -29,6 +29,7 @@ ShmSystemV::ShmSystemV(const std::string &pathName, const int rankMPI,
     // Data Shared memory sector
     const std::string dataPath(pathName + "/adios.shm.data." +
                                std::to_string(rankMPI));
+
     // 2nd field must be greater than zero and unique
     m_DataKey = ftok(dataPath.c_str(), rankMPI + 1);
     m_DataShmID = shmget(m_DataKey, m_DataSize, IPC_CREAT | 0666);
@@ -42,7 +43,7 @@ ShmSystemV::ShmSystemV(const std::string &pathName, const int rankMPI,
     m_MetadataShmID = shmget(m_MetadataKey, m_MetadataSize, IPC_CREAT | 0666);
     m_Metadata = static_cast<char *>(shmat(m_MetadataShmID, nullptr, 0));
 
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         CheckShm();
     }
@@ -56,6 +57,7 @@ size_t ShmSystemV::GetDataSize() const { return m_DataSize; }
 
 size_t ShmSystemV::GetMetadataSize() const { return m_MetadataSize; }
 
+// PRIVATE
 void ShmSystemV::CheckShm() const
 {
     if (m_DataShmID < 0)
diff --git a/source/adios2/capsule/shmem/ShmSystemV.h b/source/adios2/toolkit/capsule/shmem/ShmSystemV.h
similarity index 91%
rename from source/adios2/capsule/shmem/ShmSystemV.h
rename to source/adios2/toolkit/capsule/shmem/ShmSystemV.h
index ca8872bfcb32d073c685c5cd7e44aed7a62064c4..7f9de77cd3398f7cf906f5dacbdf45cce43b0897 100644
--- a/source/adios2/capsule/shmem/ShmSystemV.h
+++ b/source/adios2/toolkit/capsule/shmem/ShmSystemV.h
@@ -3,14 +3,14 @@
  * accompanying file Copyright.txt for details.
  */
 
-#ifndef ADIOS2_CAPSULE_SHMEM_SHMSYSTEMV_H_
-#define ADIOS2_CAPSULE_SHMEM_SHMSYSTEMV_H_
+#ifndef ADIOS2_TOOLKIT_CAPSULE_SHMEM_SHMSYSTEMV_H_
+#define ADIOS2_TOOLKIT_CAPSULE_SHMEM_SHMSYSTEMV_H_
 
 #include <sys/ipc.h>
 #include <sys/types.h>
 
 #include "adios2/ADIOSConfig.h"
-#include "adios2/core/Capsule.h"
+#include "adios2/toolkit/capsule/Capsule.h"
 
 namespace adios
 {
@@ -63,4 +63,4 @@ private:
 
 } // end namespace adios
 
-#endif /* ADIOS2_CAPSULE_SHMEM_SHMSYSTEMV_H_ */
+#endif /* ADIOS2_TOOLKIT_CAPSULE_SHMEM_SHMSYSTEMV_H_ */
diff --git a/source/adios2/toolkit/format/bp1/BP1.h b/source/adios2/toolkit/format/bp1/BP1.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2221030dca686cacc0df648d38617db3b668c08
--- /dev/null
+++ b/source/adios2/toolkit/format/bp1/BP1.h
@@ -0,0 +1,17 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * BP1.h
+ *
+ *  Created on: Apr 4, 2017
+ *      Author: wfg
+ */
+
+#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1_H_
+#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1_H_
+
+#include "adios2/toolkit/format/bp1/BP1Writer.h"
+/** TODO  #include "adios2/toolkit/format/bp1/BP1Reader.h" */
+
+#endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1_H_ */
diff --git a/source/adios2/utilities/format/bp1/BP1Aggregator.cpp b/source/adios2/toolkit/format/bp1/BP1Aggregator.cpp
similarity index 63%
rename from source/adios2/utilities/format/bp1/BP1Aggregator.cpp
rename to source/adios2/toolkit/format/bp1/BP1Aggregator.cpp
index b1e8693c228dcd1fec2f539da43cbb4a25ca431c..255e9ce234b0ff3a961d4db9071513d924717443 100644
--- a/source/adios2/utilities/format/bp1/BP1Aggregator.cpp
+++ b/source/adios2/toolkit/format/bp1/BP1Aggregator.cpp
@@ -5,14 +5,19 @@
  * BP1Aggregator.cpp
  *
  *  Created on: Mar 21, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "BP1Aggregator.h"
 
+/// \cond EXCLUDE_FROM_DOXYGEN
 #include <fstream>
+#include <ios>
 #include <stdexcept>
 #include <vector>
+/// \endcond
+
+#include <iostream>
 
 #include "adios2/ADIOSMPI.h"
 
@@ -22,15 +27,16 @@ namespace format
 {
 
 BP1Aggregator::BP1Aggregator(MPI_Comm mpiComm, const bool debugMode)
-: m_MPIComm{mpiComm}, m_DebugMode{debugMode}
+: m_MPIComm(mpiComm), m_DebugMode(debugMode)
 {
     MPI_Comm_rank(m_MPIComm, &m_RankMPI);
     MPI_Comm_size(m_MPIComm, &m_SizeMPI);
 }
 
-void BP1Aggregator::WriteProfilingLog(const std::string fileName,
-                                      const std::string &rankLog)
+std::string BP1Aggregator::GetGlobalProfilingLog(const std::string &rankLog)
 {
+    std::string profilingLog;
+
     if (m_RankMPI == 0)
     {
         const unsigned int sizeMPI = static_cast<const unsigned int>(m_SizeMPI);
@@ -49,7 +55,7 @@ void BP1Aggregator::WriteProfilingLog(const std::string fileName,
         for (unsigned int i = 1; i < sizeMPI; ++i)
         {
             MPI_Wait(&requests[i], &statuses[i]);
-            if (m_DebugMode == true)
+            if (m_DebugMode)
             {
                 if (rankLogsSizes[i - 1] == -1)
                     throw std::runtime_error(
@@ -72,30 +78,40 @@ void BP1Aggregator::WriteProfilingLog(const std::string fileName,
             MPI_Wait(&requests[i], &statuses[i]);
         }
 
-        // write file
-        std::string logFile("{\n");
-        logFile += rankLog + "\n";
+        // write global string
+        // key is to reserve memory first
+        profilingLog.reserve(rankLog.size() * m_SizeMPI);
+
+        profilingLog += "{\n";
+        profilingLog += rankLog + "\n";
         for (unsigned int i = 1; i < sizeMPI; ++i)
         {
-            if (i == sizeMPI - 1) // last one, eliminate trailing comma
+            const std::string rankLogStr(rankLogs[i - 1].data(),
+                                         rankLogs[i - 1].size());
+            profilingLog += rankLogStr + ",";
+            if (i < sizeMPI - 1)
             {
-                const std::string rankLogStr(rankLogs[i - 1].data(),
-                                             rankLogs[i - 1].size() - 1);
-                logFile += rankLogStr + "\n";
-            }
-            else
-            {
-                const std::string rankLogStr(rankLogs[i - 1].data(),
-                                             rankLogs[i - 1].size());
-                logFile += rankLogStr + "\n";
+                profilingLog += "\n";
             }
         }
-        logFile += "}\n";
+        profilingLog.pop_back(); // eliminate trailing comma
+        profilingLog += "\n";
+        profilingLog += "}\n";
 
-        // write to file
-        std::ofstream logStream(fileName);
-        logStream.write(logFile.c_str(), logFile.size());
-        logStream.close();
+        //        // write to file
+        //        std::ofstream logStream(fileName);
+        //        if (m_DebugMode)
+        //        {
+        //            if (!logStream)
+        //            {
+        //                throw std::ios_base::failure(
+        //                    "ERROR: couldn't open profiling file " + fileName
+        //                    + "\n");
+        //            }
+        //        }
+        //
+        //        logStream.write(logFile.c_str(), logFile.size());
+        //        logStream.close();
     }
     else
     {
@@ -107,6 +123,8 @@ void BP1Aggregator::WriteProfilingLog(const std::string fileName,
         MPI_Isend(const_cast<char *>(rankLog.c_str()), rankLogSize, MPI_CHAR, 0,
                   1, m_MPIComm, &requestRankLog);
     }
+
+    return profilingLog;
 }
 
 } // end namespace format
diff --git a/source/adios2/utilities/format/bp1/BP1Aggregator.h b/source/adios2/toolkit/format/bp1/BP1Aggregator.h
similarity index 65%
rename from source/adios2/utilities/format/bp1/BP1Aggregator.h
rename to source/adios2/toolkit/format/bp1/BP1Aggregator.h
index de82b269533cfdc5e5f554d1c59ed102af216ee5..ee8e160c726aa7e32e19699e358760eb53f11b33 100644
--- a/source/adios2/utilities/format/bp1/BP1Aggregator.h
+++ b/source/adios2/toolkit/format/bp1/BP1Aggregator.h
@@ -5,11 +5,11 @@
  * BP1Aggregator.h
  *
  *  Created on: Mar 1, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#ifndef ADIOS2_UTILITIES_FORMAT_BP1_BP1AGGREGATOR_H_
-#define ADIOS2_UTILITIES_FORMAT_BP1_BP1AGGREGATOR_H_
+#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1AGGREGATOR_H_
+#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1AGGREGATOR_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
 #include <string>
@@ -23,16 +23,15 @@ namespace adios
 namespace format
 {
 
-/**
- * Does all MPI related spatial aggregation tasks
- */
+/** Does all MPI aggregation tasks */
 class BP1Aggregator
 {
 
 public:
-    MPI_Comm m_MPIComm; ///< MPI communicator from Engine
-    int m_RankMPI = 0;  ///< current MPI rank process
-    int m_SizeMPI = 1;  ///< current MPI processes size
+    MPI_Comm m_MPIComm;  ///< MPI communicator from Engine
+    int m_RankMPI = 0;   ///< current MPI rank process
+    int m_SizeMPI = 1;   ///< current MPI processes size
+    int m_Processes = 1; ///< number of aggregated MPI processes
 
     /**
      * Unique constructor
@@ -47,8 +46,7 @@ public:
      * python dictionary format
      * @param rankLog contain rank profiling info to be aggregated
      */
-    void WriteProfilingLog(const std::string fileName,
-                           const std::string &rankLog);
+    std::string GetGlobalProfilingLog(const std::string &rankLog);
 
 private:
     const bool m_DebugMode = false;
diff --git a/source/adios2/toolkit/format/bp1/BP1Base.cpp b/source/adios2/toolkit/format/bp1/BP1Base.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81e71392d7e88b84a59f06cc15931c9fd6ee16ed
--- /dev/null
+++ b/source/adios2/toolkit/format/bp1/BP1Base.cpp
@@ -0,0 +1,343 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * BP1Base.cpp
+ *
+ *  Created on: Feb 7, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "BP1Base.h"
+#include "BP1Base.tcc"
+
+#include "adios2/helper/adiosFunctions.h" //CreateDirectory, StringToTimeUnit
+
+namespace adios
+{
+namespace format
+{
+
+BP1Base::BP1Base(MPI_Comm mpiComm, const bool debugMode)
+: m_HeapBuffer(debugMode), m_BP1Aggregator(mpiComm, debugMode),
+  m_DebugMode(debugMode)
+{
+}
+
+void BP1Base::InitParameters(const Params &parameters)
+{
+    // flags for defaults that require constructors
+    bool useDefaultBufferSize = true;
+    bool useDefaultProfileUnits = true;
+
+    for (const auto &pair : parameters)
+    {
+        const std::string key(pair.first);
+        const std::string value(pair.second);
+
+        if (key == "Profile")
+        {
+            InitParameterProfile(value);
+        }
+        else if (key == "ProfileUnits")
+        {
+            InitParameterProfileUnits(value);
+            useDefaultProfileUnits = false;
+        }
+        else if (key == "BufferGrowth")
+        {
+            InitParameterBufferGrowth(value);
+        }
+        else if (key == "BufferSize")
+        {
+            InitParameterInitBufferSize(value);
+            useDefaultBufferSize = false;
+        }
+        else if (key == "MaxBufferSize")
+        {
+            InitParameterMaxBufferSize(value);
+        }
+        else if (key == "Verbose")
+        {
+            InitParameterVerbose(value);
+        }
+    }
+
+    // default timer for buffering
+    if (m_Profiler.IsActive && useDefaultProfileUnits)
+    {
+        m_Profiler.Timers.emplace(
+            "buffering",
+            profiling::Timer("buffering", DefaultTimeUnitEnum, m_DebugMode));
+
+        m_Profiler.Bytes.emplace("buffering", 0);
+    }
+
+    if (useDefaultBufferSize)
+    {
+        m_HeapBuffer.ResizeData(DefaultBufferSize);
+    }
+}
+
+std::vector<std::string>
+BP1Base::GetBPBaseNames(const std::vector<std::string> &names) const noexcept
+{
+    std::vector<std::string> bpBaseNames;
+    bpBaseNames.reserve(names.size());
+
+    for (const auto &name : names)
+    {
+        bpBaseNames.push_back(GetBPBaseName(name));
+    }
+    return bpBaseNames;
+}
+
+std::string BP1Base::GetBPBaseName(const std::string &name) const noexcept
+{
+    return AddExtension(name, ".bp");
+}
+
+std::vector<std::string>
+BP1Base::GetBPNames(const std::vector<std::string> &names) const noexcept
+{
+    std::vector<std::string> bpNames;
+    bpNames.reserve(names.size());
+
+    for (const auto &name : names)
+    {
+        bpNames.push_back(GetBPName(name));
+    }
+    return bpNames;
+}
+
+std::string BP1Base::GetBPName(const std::string &name) const noexcept
+{
+    const std::string baseName = AddExtension(name, ".bp");
+    // opens a file transport under name.bp/name.bp.rank
+    const std::string bpName(baseName + "/" + baseName + "." +
+                             std::to_string(m_BP1Aggregator.m_RankMPI));
+    return bpName;
+}
+
+// PROTECTED
+void BP1Base::InitParameterProfile(const std::string value)
+{
+    if (value == "off")
+    {
+        m_Profiler.IsActive = false;
+    }
+    else if (value == "on")
+    {
+        m_Profiler.IsActive = true; // default
+    }
+    else
+    {
+        if (m_DebugMode)
+        {
+            throw std::invalid_argument("ERROR: IO SetParameters profile "
+                                        "invalid value, valid: "
+                                        "profile=on or "
+                                        "profile=off, in call to Open\n");
+        }
+    }
+}
+
+void BP1Base::InitParameterProfileUnits(const std::string value)
+{
+    TimeUnit timeUnit = StringToTimeUnit(value, m_DebugMode);
+
+    if (m_Profiler.Timers.count("buffering") == 1)
+    {
+        m_Profiler.Timers.erase("buffering");
+    }
+
+    m_Profiler.Timers.emplace(
+        "buffering", profiling::Timer("buffering", timeUnit, m_DebugMode));
+
+    m_Profiler.Bytes.emplace("buffering", 0);
+}
+
+void BP1Base::InitParameterBufferGrowth(const std::string value)
+{
+    if (m_DebugMode)
+    {
+        bool success = true;
+        try
+        {
+            m_GrowthFactor = std::stof(value);
+        }
+        catch (std::exception &e)
+        {
+            success = false;
+        }
+
+        if (!success || m_GrowthFactor <= 1.f)
+        {
+            throw std::invalid_argument(
+                "ERROR: IO SetParameter buffer_growth value "
+                "can't be less or equal than 1 (default = 1.5), or couldn't "
+                "convert number, in call to Open\n");
+        }
+    }
+    else
+    {
+        m_GrowthFactor = std::stof(value);
+    }
+}
+
+void BP1Base::InitParameterInitBufferSize(const std::string value)
+{
+    const std::string errorMessage(
+        "ERROR: couldn't convert value of init_buffer_size IO "
+        "SetParameter, valid syntax: init_buffer_size=10Gb, "
+        "init_buffer_size=1000Mb, init_buffer_size=16Kb (minimum default), "
+        " in call to Open");
+
+    if (m_DebugMode)
+    {
+        if (value.size() < 2)
+        {
+            throw std::invalid_argument(errorMessage);
+        }
+    }
+
+    const std::string number(value.substr(0, value.size() - 2));
+    const std::string units(value.substr(value.size() - 2));
+    const size_t factor = BytesFactor(units, m_DebugMode);
+    size_t bufferSize = DefaultBufferSize; // from ADIOSTypes.h
+
+    if (m_DebugMode)
+    {
+        bool success = true;
+        try
+        {
+            bufferSize = static_cast<size_t>(std::stoul(number) * factor);
+        }
+        catch (std::exception &e)
+        {
+            success = false;
+        }
+
+        if (!success || bufferSize < 16 * 1024) // 16384b
+        {
+            throw std::invalid_argument(errorMessage);
+        }
+    }
+    else
+    {
+        bufferSize = static_cast<size_t>(std::stoul(number) * factor);
+    }
+
+    m_HeapBuffer.ResizeData(bufferSize);
+}
+
+void BP1Base::InitParameterMaxBufferSize(const std::string value)
+{
+    const std::string errorMessage(
+        "ERROR: couldn't convert value of max_buffer_size IO "
+        "SetParameter, valid syntax: MaxBufferSize=10Gb, "
+        "MaxBufferSize=1000Mb, MaxBufferSize=16Kb (minimum default), "
+        " in call to Open");
+
+    if (m_DebugMode)
+    {
+        if (value.size() < 2)
+        {
+            throw std::invalid_argument(errorMessage);
+        }
+    }
+
+    const std::string number(value.substr(0, value.size() - 2));
+    const std::string units(value.substr(value.size() - 2));
+    const size_t factor = BytesFactor(units, m_DebugMode);
+
+    if (m_DebugMode)
+    {
+        bool success = true;
+        try
+        {
+            m_MaxBufferSize = static_cast<size_t>(std::stoul(number) * factor);
+        }
+        catch (std::exception &e)
+        {
+            success = false;
+        }
+
+        if (!success || m_MaxBufferSize < 16 * 1024) // 16384b
+        {
+            throw std::invalid_argument(errorMessage);
+        }
+    }
+    else
+    {
+        m_MaxBufferSize = static_cast<size_t>(std::stoul(number) * factor);
+    }
+}
+
+void BP1Base::InitParameterVerbose(const std::string value)
+{
+    if (m_DebugMode)
+    {
+        bool success = true;
+        try
+        {
+            m_Verbosity = static_cast<unsigned int>(std::stoi(value));
+        }
+        catch (std::exception &e)
+        {
+            success = false;
+        }
+
+        if (!success || m_Verbosity < 0 || m_Verbosity > 5)
+        {
+            throw std::invalid_argument(
+                "ERROR: value in Verbose=value in IO SetParameters must be "
+                "an integer in the range [0,5], in call to Open\n");
+        }
+    }
+    else
+    {
+        m_Verbosity = static_cast<unsigned int>(std::stoi(value));
+    }
+}
+
+std::vector<uint8_t>
+BP1Base::GetTransportIDs(const std::vector<std::string> &transportsTypes) const
+    noexcept
+{
+    auto lf_GetTransportID = [](const std::string method) -> uint8_t {
+
+        int id = METHOD_UNKNOWN;
+        if (method == "NULL")
+        {
+            id = METHOD_NULL;
+        }
+        else if (method == "FileDescriptor")
+        {
+            id = METHOD_POSIX;
+        }
+        else if (method == "FileStream")
+        {
+            id = METHOD_FSTREAM;
+        }
+        else if (method == "FilePointer")
+        {
+            id = METHOD_FILE;
+        }
+
+        return static_cast<uint8_t>(id);
+    };
+
+    std::vector<uint8_t> transportsIDs;
+    transportsIDs.reserve(transportsTypes.size());
+
+    for (const auto transportType : transportsTypes)
+    {
+        transportsIDs.push_back(lf_GetTransportID(transportType));
+    }
+
+    return transportsIDs;
+}
+
+} // end namespace format
+} // end namespace adios
diff --git a/source/adios2/utilities/format/bp1/BP1Base.h b/source/adios2/toolkit/format/bp1/BP1Base.h
similarity index 65%
rename from source/adios2/utilities/format/bp1/BP1Base.h
rename to source/adios2/toolkit/format/bp1/BP1Base.h
index 2308c3498ea68a9a659e78d34665b6c3324443b4..d2e9024fcd3b529d4b261b77faa36e6819d3e3cd 100644
--- a/source/adios2/utilities/format/bp1/BP1Base.h
+++ b/source/adios2/toolkit/format/bp1/BP1Base.h
@@ -2,28 +2,28 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * BP1.h
+ * BP1Base.h  base class for BP1Writer and BP1Reader
  *
  *  Created on: Feb 2, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#ifndef ADIOS2_UTILITIES_FORMAT_BP1_BP1BASE_H_
-#define ADIOS2_UTILITIES_FORMAT_BP1_BP1BASE_H_
+#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_H_
+#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
 #include <memory> //std::shared_ptr
-#include <unordered_map>
 #include <vector>
 /// \endcond
 
-#include "BP1Aggregator.h"
-#include "BP1Structs.h"
 #include "adios2/ADIOSConfig.h"
 #include "adios2/ADIOSMPICommOnly.h"
+#include "adios2/ADIOSMacros.h"
 #include "adios2/ADIOSTypes.h"
-#include "adios2/capsule/heap/STLVector.h"
-#include "adios2/core/Transport.h"
+#include "adios2/toolkit/capsule/heap/STLVector.h"
+#include "adios2/toolkit/format/bp1/BP1Aggregator.h"
+#include "adios2/toolkit/format/bp1/BP1Structs.h"
+#include "adios2/toolkit/profiling/iochrono/IOChrono.h"
 
 namespace adios
 {
@@ -41,20 +41,27 @@ public:
     unsigned int m_Verbosity = 0;
 
     /** contains data buffer and position */
-    capsule::STLVector m_Heap = capsule::STLVector(true);
+    capsule::STLVector m_HeapBuffer;
 
-    /** memory growth factor */
+    /** memory growth factor,s set by the user */
     float m_GrowthFactor = 1.5;
 
-    /** max buffer size */
+    /** max buffer size, set by the user */
     size_t m_MaxBufferSize = 0;
 
-    /** contains bp1 format metadata */
+    /** contains bp1 format metadata indices*/
     BP1MetadataSet m_MetadataSet;
 
-    /** aggregation tasks */
+    /** object that takes care of all MPI aggregation tasks */
     BP1Aggregator m_BP1Aggregator;
 
+    /** true: Close was called, Engine will call this many times for different
+     * transports */
+    bool m_IsClosed = false;
+
+    /** buffering and MPI aggregation profiling info, set by user */
+    profiling::IOChrono m_Profiler;
+
     /**
      * Unique constructor
      * @param mpiComm for m_BP1Aggregator
@@ -64,23 +71,39 @@ public:
 
     virtual ~BP1Base() = default;
 
+    void InitParameters(const Params &parameters);
+
     /**
-     * Checks if input name has .bp extension and returns a .bp directory name
+     * Vector version of BPBaseName
+     * @param names
+     * @return vector of base (name.bp) names
+     */
+    std::vector<std::string>
+    GetBPBaseNames(const std::vector<std::string> &names) const noexcept;
+
+    /**
+     * Checks if input name has .bp extension and returns a .bp directory
+     * name
      * @param name input (might or not have .bp)
-     * @return either name.bp (name has no .bp) or name (name has .bp extension)
+     * @return either name.bp (name has no .bp) or name (name has .bp
+     * extension)
+     */
+    std::string GetBPBaseName(const std::string &name) const noexcept;
+
+    /**
+     * Vector version of GetBPName
+     * @param names
+     * @return
      */
-    std::string GetDirectoryName(const std::string name) const noexcept;
+    std::vector<std::string>
+    GetBPNames(const std::vector<std::string> &names) const noexcept;
 
     /**
-     * Opens rank files in the following format:
-     * if transport.m_MPIComm different from MPI_Comm_SELF -->
-     * name.bp.dir/name.bp.rank
-     * @param name might contain .bp or not, if not .bp will be added
-     * @param accessMode "write" "w", "r" "read",  "append" "a"
-     * @param transport file I/O transport
+     * Gets the name for bp buffer based on rank
+     * @param name
+     * @return name.bp/name.bp.rank
      */
-    void OpenRankFiles(const std::string name, const std::string accessMode,
-                       Transport &file) const;
+    std::string GetBPName(const std::string &name) const noexcept;
 
     /**
      * Return type of the CheckAllocation function.
@@ -96,6 +119,7 @@ public:
 protected:
     /** might be used in large payload copies to buffer */
     unsigned int m_Threads = 1;
+    const bool m_DebugMode = false;
 
     /** method type for file I/O */
     enum IO_METHOD
@@ -165,10 +189,11 @@ protected:
         type_double = 6,      //!< type_double
         type_long_double = 7, //!< type_long_double
 
-        type_string = 9,          //!< type_string
-        type_complex = 10,        //!< type_complex
-        type_double_complex = 11, //!< type_double_complex
-        type_string_array = 12    //!< type_string_array
+        type_string = 9,              //!< type_string
+        type_complex = 10,            //!< type_complex
+        type_double_complex = 11,     //!< type_double_complex
+        type_string_array = 12,       //!< type_string_array
+        type_long_double_complex = 13 //!< type_double_complex
     };
 
     /**
@@ -219,87 +244,40 @@ protected:
         // bool finite??
     };
 
+    /** profile=on (default) generate profiling.log
+         *  profile=off */
+    void InitParameterProfile(const std::string value);
+
+    /** profile_units=s (default) (mus, ms, s,m,h) from ADIOSTypes.h TimeUnit */
+    void InitParameterProfileUnits(const std::string value);
+
+    /** growth_factor=1.5 (default), must be > 1.0 */
+    void InitParameterBufferGrowth(const std::string value);
+
+    /** set initial buffer size */
+    void InitParameterInitBufferSize(const std::string value);
+
+    /** unlimited (default), set max buffer size in Gb or Mb
+     *  max_buffer_size=100Mb or  max_buffer_size=1Gb */
+    void InitParameterMaxBufferSize(const std::string value);
+
+    /** verbose file level=0 (default) */
+    void InitParameterVerbose(const std::string value);
+
     /**
      * Returns data type index from enum Datatypes
      * @param variable input variable
      * @return data type
      */
     template <class T>
-    inline int8_t GetDataType() const noexcept
-    {
-        return type_unknown;
-    }
+    int8_t GetDataType() const noexcept;
 
-    std::vector<uint8_t> GetMethodIDs(
-        const std::vector<std::shared_ptr<Transport>> &transports) const
+    std::vector<uint8_t>
+    GetTransportIDs(const std::vector<std::string> &transportsTypes) const
         noexcept;
 };
 
-// Moving template BP1Writer::GetDataType template specializations outside of
-// the class
-template <>
-inline int8_t BP1Base::GetDataType<char>() const noexcept
-{
-    return type_byte;
-}
-
-template <>
-inline int8_t BP1Base::GetDataType<short>() const noexcept
-{
-    return type_short;
-}
-
-template <>
-inline int8_t BP1Base::GetDataType<int>() const noexcept
-{
-    return type_integer;
-}
-template <>
-inline int8_t BP1Base::GetDataType<long int>() const noexcept
-{
-    return type_long;
-}
-
-template <>
-inline int8_t BP1Base::GetDataType<unsigned char>() const noexcept
-{
-    return type_unsigned_byte;
-}
-template <>
-inline int8_t BP1Base::GetDataType<unsigned short>() const noexcept
-{
-    return type_unsigned_short;
-}
-template <>
-inline int8_t BP1Base::GetDataType<unsigned int>() const noexcept
-{
-    return type_unsigned_integer;
-}
-template <>
-inline int8_t BP1Base::GetDataType<unsigned long int>() const noexcept
-{
-    return type_unsigned_long;
-}
-
-template <>
-inline int8_t BP1Base::GetDataType<float>() const noexcept
-{
-    return type_real;
-}
-
-template <>
-inline int8_t BP1Base::GetDataType<double>() const noexcept
-{
-    return type_double;
-}
-
-template <>
-inline int8_t BP1Base::GetDataType<long double>() const noexcept
-{
-    return type_long_double;
-}
-
 } // end namespace format
 } // end namespace adios
 
-#endif /* ADIOS2_UTILITIES_FORMAT_BP1_BP1BASE_H_ */
+#endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_H_ */
diff --git a/source/adios2/toolkit/format/bp1/BP1Base.tcc b/source/adios2/toolkit/format/bp1/BP1Base.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..dfd39f6363985ac63b4055464065111c1d84d9bc
--- /dev/null
+++ b/source/adios2/toolkit/format/bp1/BP1Base.tcc
@@ -0,0 +1,118 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * BP1Base.tcc
+ *
+ *  Created on: May 19, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_TCC_
+#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_TCC_
+
+#include "BP1Base.h"
+
+namespace adios
+{
+namespace format
+{
+
+template <>
+int8_t BP1Base::GetDataType<char>() const noexcept
+{
+    return type_byte;
+}
+
+template <>
+int8_t BP1Base::GetDataType<short>() const noexcept
+{
+    return type_short;
+}
+
+template <>
+int8_t BP1Base::GetDataType<int>() const noexcept
+{
+    return type_integer;
+}
+
+template <>
+int8_t BP1Base::GetDataType<long int>() const noexcept
+{
+    return type_long;
+}
+
+template <>
+int8_t BP1Base::GetDataType<long long int>() const noexcept
+{
+    return type_long;
+}
+
+template <>
+int8_t BP1Base::GetDataType<unsigned char>() const noexcept
+{
+    return type_unsigned_byte;
+}
+template <>
+int8_t BP1Base::GetDataType<unsigned short>() const noexcept
+{
+    return type_unsigned_short;
+}
+template <>
+int8_t BP1Base::GetDataType<unsigned int>() const noexcept
+{
+    return type_unsigned_integer;
+}
+
+template <>
+int8_t BP1Base::GetDataType<unsigned long int>() const noexcept
+{
+    return type_unsigned_long;
+}
+
+template <>
+int8_t BP1Base::GetDataType<unsigned long long int>() const noexcept
+{
+    return type_unsigned_long;
+}
+
+template <>
+int8_t BP1Base::GetDataType<float>() const noexcept
+{
+    return type_real;
+}
+
+template <>
+int8_t BP1Base::GetDataType<double>() const noexcept
+{
+    return type_double;
+}
+
+template <>
+int8_t BP1Base::GetDataType<long double>() const noexcept
+{
+    return type_long_double;
+}
+
+template <>
+int8_t BP1Base::GetDataType<cfloat>() const noexcept
+{
+    return type_complex;
+}
+
+template <>
+int8_t BP1Base::GetDataType<cdouble>() const noexcept
+{
+    return type_double_complex;
+}
+
+template <>
+int8_t BP1Base::GetDataType<cldouble>() const noexcept
+{
+    return type_long_double_complex;
+}
+
+} // end namespace format
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_TCC_ */
diff --git a/source/adios2/utilities/format/bp1/BP1Structs.h b/source/adios2/toolkit/format/bp1/BP1Structs.h
similarity index 88%
rename from source/adios2/utilities/format/bp1/BP1Structs.h
rename to source/adios2/toolkit/format/bp1/BP1Structs.h
index 825a446fbcde647c36f682c18808fa92b3128cf0..19e9c5ed19f5dce3ca61b94b16661027178cd41c 100644
--- a/source/adios2/utilities/format/bp1/BP1Structs.h
+++ b/source/adios2/toolkit/format/bp1/BP1Structs.h
@@ -5,22 +5,23 @@
  * BP1Structs.h
  *
  *  Created on: Apr 3, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#ifndef ADIOS2_UTILITIES_FORMAT_BP1_BP1STRUCTS_H_
-#define ADIOS2_UTILITIES_FORMAT_BP1_BP1STRUCTS_H_
+#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1STRUCTS_H_
+#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1STRUCTS_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
 #include <cstdint>
 #include <string>
 #include <unordered_map>
 #include <vector>
+
 /// \endcond
 
 #include "adios2/ADIOSConfig.h"
 #include "adios2/ADIOSTypes.h"
-#include "adios2/core/IOChrono.h"
+#include "adios2/toolkit/profiling/iochrono/IOChrono.h"
 
 namespace adios
 {
@@ -81,11 +82,9 @@ struct BP1MetadataSet
 
     /** true: currently writing to a pg, false: no current pg */
     bool DataPGIsOpen = false;
-
-    profiling::IOChrono Log; ///< object that takes buffering profiling info
 };
 
 } // end namespace format
 } // end namespace adios
 
-#endif /* ADIOS2_UTILITIES_FORMAT_BP1_BP1STRUCTS_H_ */
+#endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1STRUCTS_H_ */
diff --git a/source/adios2/utilities/format/bp1/BP1Writer.cpp b/source/adios2/toolkit/format/bp1/BP1Writer.cpp
similarity index 72%
rename from source/adios2/utilities/format/bp1/BP1Writer.cpp
rename to source/adios2/toolkit/format/bp1/BP1Writer.cpp
index 666a3e6edd755087feceee18adb3b9ae202a2c06..34639d7fb59eff38671c7d433feec5d72c24d2ef 100644
--- a/source/adios2/utilities/format/bp1/BP1Writer.cpp
+++ b/source/adios2/toolkit/format/bp1/BP1Writer.cpp
@@ -5,7 +5,7 @@
  * BP1Writer.cpp
  *
  *  Created on: Feb 1, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "BP1Writer.h"
@@ -24,23 +24,31 @@ BP1Writer::BP1Writer(MPI_Comm mpiComm, const bool debugMode)
 {
 }
 
-std::size_t BP1Writer::GetProcessGroupIndexSize(
-    const std::string name, const std::string timeStepName,
-    const std::size_t numberOfTransports) const noexcept
+size_t BP1Writer::GetProcessGroupIndexSize(const std::string name,
+                                           const std::string timeStepName,
+                                           const size_t transportsSize) const
+    noexcept
 {
     // pgIndex + list of methods (transports)
-    return (name.length() + timeStepName.length() + 23) +
-           (3 + numberOfTransports);
+    size_t pgSize =
+        (name.length() + timeStepName.length() + 23) + (3 + transportsSize);
+
+    return pgSize;
 }
 
 void BP1Writer::WriteProcessGroupIndex(
-    const bool isFortran, const std::string name, const uint32_t processID,
-    const std::vector<std::shared_ptr<Transport>> &transports) noexcept
+    const std::string hostLanguage,
+    const std::vector<std::string> &transportsTypes) noexcept
 {
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Resume();
+    }
+
     std::vector<char> &metadataBuffer = m_MetadataSet.PGIndex.Buffer;
 
-    std::vector<char> &dataBuffer = m_Heap.m_Data;
-    size_t &dataPosition = m_Heap.m_DataPosition;
+    std::vector<char> &dataBuffer = m_HeapBuffer.m_Data;
+    size_t &dataPosition = m_HeapBuffer.m_DataPosition;
 
     m_MetadataSet.DataPGLengthPosition = dataPosition;
     dataPosition += 8; // skip pg length (8)
@@ -49,15 +57,18 @@ void BP1Writer::WriteProcessGroupIndex(
     metadataBuffer.insert(metadataBuffer.end(), 2, 0); // skip pg length (2)
 
     // write name to metadata
+    const std::string name(std::to_string(m_BP1Aggregator.m_RankMPI));
+
     WriteNameRecord(name, metadataBuffer);
     // write if host language Fortran in metadata and data
-    const char hostFortran = (isFortran) ? 'y' : 'n';
+    const char hostFortran = (hostLanguage == "Fortran") ? 'y' : 'n';
     InsertToBuffer(metadataBuffer, &hostFortran);
     CopyToBuffer(dataBuffer, dataPosition, &hostFortran);
     // write name in data
     WriteNameRecord(name, dataBuffer, dataPosition);
 
     // processID in metadata,
+    const uint32_t processID = static_cast<uint32_t>(m_BP1Aggregator.m_RankMPI);
     InsertToBuffer(metadataBuffer, &processID);
     // skip coordination var in data ....what is coordination var?
     dataPosition += 4;
@@ -73,7 +84,7 @@ void BP1Writer::WriteProcessGroupIndex(
 
     // offset to pg in data in metadata which is the current absolute position
     InsertToBuffer(metadataBuffer, reinterpret_cast<uint64_t *>(
-                                       &m_Heap.m_DataAbsolutePosition));
+                                       &m_HeapBuffer.m_DataAbsolutePosition));
 
     // Back to writing metadata pg index length (length of group)
     const uint16_t metadataPGIndexLength =
@@ -83,7 +94,7 @@ void BP1Writer::WriteProcessGroupIndex(
     // DONE With metadataBuffer
 
     // here write method in data
-    const std::vector<uint8_t> methodIDs = GetMethodIDs(transports);
+    const std::vector<uint8_t> methodIDs = GetTransportIDs(transportsTypes);
     const uint8_t methodsCount = methodIDs.size();
     CopyToBuffer(dataBuffer, dataPosition, &methodsCount); // count
     // methodID (1) + method params length(2), no parameters for now
@@ -98,80 +109,120 @@ void BP1Writer::WriteProcessGroupIndex(
     }
 
     // update absolute position
-    m_Heap.m_DataAbsolutePosition +=
+    m_HeapBuffer.m_DataAbsolutePosition +=
         dataPosition - m_MetadataSet.DataPGLengthPosition;
     // pg vars count and position
     m_MetadataSet.DataPGVarsCount = 0;
     m_MetadataSet.DataPGVarsCountPosition = dataPosition;
     // add vars count and length
     dataPosition += 12;
-    m_Heap.m_DataAbsolutePosition += 12; // add vars count and length
+    m_HeapBuffer.m_DataAbsolutePosition += 12; // add vars count and length
 
     ++m_MetadataSet.DataPGCount;
     m_MetadataSet.DataPGIsOpen = true;
+
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Pause();
+    }
 }
 
-void BP1Writer::Advance() { FlattenData(); }
+void BP1Writer::Advance()
+{
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Resume();
+    }
 
-void BP1Writer::Close(Transport &transport, bool &isFirstClose,
-                      const bool doAggregation) noexcept
+    FlattenData();
+
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Pause();
+    }
+}
+
+void BP1Writer::Close() noexcept
 {
-    if (m_MetadataSet.Log.IsActive == true)
+    if (m_Profiler.IsActive)
     {
-        m_MetadataSet.Log.Timers[0].SetInitialTime();
+        m_Profiler.Timers.at("buffering").Resume();
     }
 
-    if (isFirstClose == true)
+    if (!m_IsClosed)
     {
-        if (m_MetadataSet.DataPGIsOpen == true)
+        if (m_MetadataSet.DataPGIsOpen)
         {
             FlattenData();
         }
 
         FlattenMetadata();
+        m_IsClosed = true;
+    }
+
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Pause();
+    }
+}
 
-        if (m_MetadataSet.Log.IsActive == true)
+std::string BP1Writer::GetRankProfilingLog(
+    const std::vector<std::string> &transportsTypes,
+    const std::vector<profiling::IOChrono *> &transportsProfilers) noexcept
+{
+    auto lf_WriterTimer = [](std::string &rankLog,
+                             const profiling::Timer &timer) {
+        rankLog += "'" + timer.m_Process + "_" + timer.GetShortUnits() + "': " +
+                   std::to_string(timer.m_ProcessTime) + ", ";
+    };
+
+    // prepare string dictionary per rank
+    std::string rankLog("'rank_" + std::to_string(m_BP1Aggregator.m_RankMPI) +
+                        "': { ");
+
+    auto &profiler = m_Profiler;
+    rankLog +=
+        "'bytes': " + std::to_string(profiler.Bytes.at("buffering")) + ", ";
+    lf_WriterTimer(rankLog, profiler.Timers.at("buffering"));
+
+    const size_t transportsSize = transportsTypes.size();
+
+    for (unsigned int t = 0; t < transportsSize; ++t)
+    {
+        rankLog += "'transport_" + std::to_string(t) + "': { ";
+        rankLog += "'lib': '" + transportsTypes[t] + "', ";
+
+        for (const auto &transportTimerPair : transportsProfilers[t]->Timers)
         {
-            m_MetadataSet.Log.Timers[0].SetInitialTime();
+            lf_WriterTimer(rankLog, transportTimerPair.second);
+            rankLog += ", ";
         }
+        // replace last comma with space
+        rankLog.pop_back();
+        rankLog.pop_back();
+        rankLog += " ";
 
-        // N-to-M  where 1 <= M <= N-1, might need a new
-        // Log metadataSet.Log.m_Timers just for aggregation
-        if (doAggregation == true)
+        if (t == transportsSize - 1) // last element
         {
-            // here call aggregator
+            rankLog += "}";
+        }
+        else
+        {
+            rankLog += "},";
         }
-        isFirstClose = false;
-    }
-
-    if (doAggregation == true) // N-to-M  where 1 <= M <= N-1
-    {
-        // here call aggregator to select transports for Write and Close
-    }
-    else // N-to-N
-    {
-        // single write
-        transport.Write(m_Heap.m_Data.data(), m_Heap.m_Data.size());
-        transport.Close();
     }
-}
+    rankLog += " }";
 
-void BP1Writer::WriteProfilingLogFile(
-    const std::string &name, const unsigned int rank,
-    const std::vector<std::shared_ptr<Transport>> &transports) noexcept
-{
-    const std::string fileName(GetDirectoryName(name) + "/profiling.log");
-    const std::string rankLog(GetRankProfilingLog(rank, transports));
-    m_BP1Aggregator.WriteProfilingLog(fileName, rankLog);
+    return rankLog;
 }
 
 // PRIVATE FUNCTIONS
-void BP1Writer::WriteDimensionsRecord(
-    const std::vector<size_t> &localDimensions,
-    const std::vector<size_t> &globalDimensions,
-    const std::vector<size_t> &offsets, std::vector<char> &buffer) noexcept
+void BP1Writer::WriteDimensionsRecord(const Dims localDimensions,
+                                      const Dims globalDimensions,
+                                      const Dims offsets,
+                                      std::vector<char> &buffer) noexcept
 {
-    if (offsets.empty() == true)
+    if (offsets.empty())
     {
         for (const auto &localDimension : localDimensions)
         {
@@ -194,11 +245,12 @@ void BP1Writer::WriteDimensionsRecord(
     }
 }
 
-void BP1Writer::WriteDimensionsRecord(
-    const std::vector<size_t> &localDimensions,
-    const std::vector<size_t> &globalDimensions,
-    const std::vector<size_t> &offsets, const unsigned int skip,
-    std::vector<char> &buffer, size_t &position) noexcept
+void BP1Writer::WriteDimensionsRecord(const Dims localDimensions,
+                                      const Dims globalDimensions,
+                                      const Dims offsets,
+                                      const unsigned int skip,
+                                      std::vector<char> &buffer,
+                                      size_t &position) noexcept
 {
     auto lf_WriteFlaggedDim = [](std::vector<char> &buffer, size_t &position,
                                  const size_t dimension) {
@@ -209,7 +261,7 @@ void BP1Writer::WriteDimensionsRecord(
     };
 
     // BODY Starts here
-    if (offsets.empty() == true)
+    if (offsets.empty())
     {
         for (const auto &localDimension : localDimensions)
         {
@@ -264,8 +316,8 @@ BP1Writer::GetBP1Index(const std::string name,
 
 void BP1Writer::FlattenData() noexcept
 {
-    auto &buffer = m_Heap.m_Data;
-    auto &position = m_Heap.m_DataPosition;
+    auto &buffer = m_HeapBuffer.m_Data;
+    auto &position = m_HeapBuffer.m_DataPosition;
 
     // vars count and Length (only for PG)
     CopyToBuffer(buffer, m_MetadataSet.DataPGVarsCountPosition,
@@ -278,7 +330,7 @@ void BP1Writer::FlattenData() noexcept
     // attributes (empty for now) count (4) and length (8) are zero by moving
     // positions in time step zero
     position += 12;
-    m_Heap.m_DataAbsolutePosition += 12;
+    m_HeapBuffer.m_DataAbsolutePosition += 12;
 
     // Finish writing pg group length
     // without record itself, 12 due to empty attributes
@@ -344,12 +396,13 @@ void BP1Writer::FlattenMetadata() noexcept
                               (attributesLength + 12) +
                               m_MetadataSet.MiniFooterSize;
 
-    auto &buffer = m_Heap.m_Data;
-    auto &position = m_Heap.m_DataPosition;
+    auto &buffer = m_HeapBuffer.m_Data;
+    auto &position = m_HeapBuffer.m_DataPosition;
 
     // reserve data to fit metadata,
-    buffer.resize(position + footerSize);
-    // must replace with growth buffer strategy?
+    // must replace with growth buffer strategy
+    m_HeapBuffer.ResizeData(position + footerSize);
+    // buffer.resize(position + footerSize);
 
     // write pg index
     CopyToBuffer(buffer, position, &pgCount);
@@ -365,7 +418,7 @@ void BP1Writer::FlattenMetadata() noexcept
                       m_MetadataSet.AttributesIndices, buffer, position);
 
     // getting absolute offsets, minifooter is 28 bytes for now
-    const uint64_t offsetPGIndex = m_Heap.m_DataAbsolutePosition;
+    const uint64_t offsetPGIndex = m_HeapBuffer.m_DataAbsolutePosition;
     const uint64_t offsetVarsIndex = offsetPGIndex + (pgLength + 16);
     const uint64_t offsetAttributeIndex = offsetVarsIndex + (varsLength + 12);
 
@@ -385,64 +438,15 @@ void BP1Writer::FlattenMetadata() noexcept
     {
     }
 
-    m_Heap.m_DataAbsolutePosition += footerSize;
+    m_HeapBuffer.m_DataAbsolutePosition += footerSize;
 
-    if (m_MetadataSet.Log.IsActive == true)
+    if (m_Profiler.IsActive)
     {
-        m_MetadataSet.Log.TotalBytes.push_back(m_Heap.m_DataAbsolutePosition);
+        m_Profiler.Bytes.emplace("buffering",
+                                 m_HeapBuffer.m_DataAbsolutePosition);
     }
 }
 
-std::string BP1Writer::GetRankProfilingLog(
-    const unsigned int rank,
-    const std::vector<std::shared_ptr<Transport>> &transports) noexcept
-{
-    auto lf_WriterTimer = [](std::string &rankLog,
-                             const profiling::Timer &timer) {
-        rankLog += "'" + timer.m_Process + "_" + timer.GetUnits() + "': " +
-                   std::to_string(timer.m_ProcessTime);
-    };
-
-    // prepare string dictionary per rank
-    std::string rankLog("'rank_" + std::to_string(rank) + "': { ");
-
-    auto &profiler = m_MetadataSet.Log;
-    rankLog += "'bytes': " + std::to_string(profiler.TotalBytes[0]) + ", ";
-    lf_WriterTimer(rankLog, profiler.Timers[0]);
-    rankLog += ", ";
-
-    for (unsigned int t = 0; t < transports.size(); ++t)
-    {
-        rankLog += "'transport_" + std::to_string(t) + "': { ";
-        rankLog += "'lib': '" + transports[t]->m_Type + "', ";
-
-        for (unsigned int i = 0; i < 3; ++i)
-        {
-            lf_WriterTimer(rankLog, transports[t]->m_Profiler.Timers[i]);
-            if (i < 2)
-            {
-                rankLog += ", ";
-            }
-            else
-            {
-                rankLog += " ";
-            }
-        }
-
-        if (t == transports.size() - 1) // last element
-        {
-            rankLog += "}";
-        }
-        else
-        {
-            rankLog += "},";
-        }
-    }
-    rankLog += " },";
-
-    return rankLog;
-}
-
 //------------------------------------------------------------------------------
 // Explicit instantiation of only public templates
 
@@ -450,13 +454,13 @@ std::string BP1Writer::GetRankProfilingLog(
     template BP1Writer::ResizeResult BP1Writer::ResizeBuffer(                  \
         const Variable<T> &variable);                                          \
                                                                                \
-    template void BP1Writer::WriteVariablePayload(                             \
+    template void BP1Writer::WriteVariableMetadata(                            \
         const Variable<T> &variable) noexcept;                                 \
                                                                                \
-    template void BP1Writer::WriteVariableMetadata(                            \
+    template void BP1Writer::WriteVariablePayload(                             \
         const Variable<T> &variable) noexcept;
 
-ADIOS_FOREACH_TYPE_1ARG(declare_template_instantiation)
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
 #undef declare_template_instantiation
 
 //------------------------------------------------------------------------------
diff --git a/source/adios2/utilities/format/bp1/BP1Writer.h b/source/adios2/toolkit/format/bp1/BP1Writer.h
similarity index 75%
rename from source/adios2/utilities/format/bp1/BP1Writer.h
rename to source/adios2/toolkit/format/bp1/BP1Writer.h
index b3bd946fc6aa38a2483c26ebc5c131d7fa5bc811..d3caf67f36b9970e38c7221f3e5df7451aa21d5c 100644
--- a/source/adios2/utilities/format/bp1/BP1Writer.h
+++ b/source/adios2/toolkit/format/bp1/BP1Writer.h
@@ -2,14 +2,14 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * BP1.h
+ * BP1Writer.h
  *
  *  Created on: Jan 24, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#ifndef ADIOS2_UTILITIES_FORMAT_BP1_BP1WRITER_H_
-#define ADIOS2_UTILITIES_FORMAT_BP1_BP1WRITER_H_
+#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_H_
+#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
 #include <algorithm> //std::count, std::copy, std::for_each
@@ -20,12 +20,10 @@
 #include "adios2/ADIOSConfig.h"
 #include "adios2/ADIOSMacros.h"
 #include "adios2/ADIOSTypes.h"
-#include "adios2/capsule/heap/STLVector.h"
 #include "adios2/core/Variable.h"
-#include "adios2/core/adiosFunctions.h"
-#include "adios2/core/adiosTemplates.h"
-#include "adios2/utilities/format/bp1/BP1Base.h"
-#include "adios2/utilities/format/bp1/BP1Structs.h"
+#include "adios2/toolkit/capsule/heap/STLVector.h"
+#include "adios2/toolkit/format/bp1/BP1Base.h"
+#include "adios2/toolkit/format/bp1/BP1Structs.h"
 
 namespace adios
 {
@@ -48,14 +46,12 @@ public:
     /**
      * Writes a process group index PGIndex and list of methods (from
      * transports). Done at Open or Advance.
-     * @param isFortran
-     * @param name group name, taking the rank
-     * @param processID
-     * @param transports
+     * @param hostLanguage from ADIOS class passed to IO
+     * @param transportsTypes passed to get list of transport "bp methods"
      */
     void WriteProcessGroupIndex(
-        const bool isFortran, const std::string name, const uint32_t processID,
-        const std::vector<std::shared_ptr<Transport>> &transports) noexcept;
+        const std::string hostLanguage,
+        const std::vector<std::string> &transportsTypes) noexcept;
 
     /**
      *
@@ -88,37 +84,35 @@ public:
     void Advance();
 
     /**
-     * Function that sets metadata (if first close) and writes to a single
-     * transport
-     * @param metadataSet current rank metadata set
-     * @param heap contains data buffer
-     * @param transport does a write after data and metadata is setup
-     * @param isFirstClose true: metadata has been set and aggregated
-     * @param doAggregation true: for N-to-M, false: for N-to-N
+     * @param isFirstClose true: first time close, false: already closed buffer
      */
-    void Close(Transport &transport, bool &isFirstClose,
-               const bool doAggregation) noexcept;
+    void Close() noexcept;
 
-    void WriteProfilingLogFile(
-        const std::string &name, const unsigned int rank,
-        const std::vector<std::shared_ptr<Transport>> &transports) noexcept;
+    /**
+     * Get a string with profiling information for this rank
+     * @param name stream name
+     * @param transportsTypes list of transport types
+     * @param transportsProfilers list of references to transport profilers
+     */
+    std::string GetRankProfilingLog(
+        const std::vector<std::string> &transportsTypes,
+        const std::vector<profiling::IOChrono *> &transportsProfilers) noexcept;
 
 private:
     /** BP format version */
-    const std::uint8_t m_Version = 3;
+    const uint8_t m_Version = 3;
 
     /**
      * Calculates the Process Index size in bytes according to the BP format,
      * including list of method with no parameters (for now)
      * @param name
      * @param timeStepName
-     * @param numberOfTransports
+     * @param transportsSize
      * @return size of pg index
      */
     size_t GetProcessGroupIndexSize(const std::string name,
                                     const std::string timeStepName,
-                                    const size_t numberOfTransports) const
-        noexcept;
+                                    const size_t transportsSize) const noexcept;
 
     /**
      * Returns the estimated variable index size
@@ -185,15 +179,13 @@ private:
      * data
      * characteristic
      */
-    void WriteDimensionsRecord(const std::vector<size_t> &localDimensions,
-                               const std::vector<size_t> &globalDimensions,
-                               const std::vector<size_t> &offsets,
+    void WriteDimensionsRecord(const Dims localDimensions,
+                               const Dims globalDimensions, const Dims offsets,
                                std::vector<char> &buffer) noexcept;
 
     /** Overloaded version for data buffer */
-    void WriteDimensionsRecord(const std::vector<size_t> &localDimensions,
-                               const std::vector<size_t> &globalDimensions,
-                               const std::vector<size_t> &offsets,
+    void WriteDimensionsRecord(const Dims localDimensions,
+                               const Dims globalDimensions, const Dims offsets,
                                const unsigned int skip,
                                std::vector<char> &buffer,
                                size_t &position) noexcept;
@@ -206,7 +198,7 @@ private:
 
     /** Overloaded version for data buffer */
     template <class T>
-    void WriteBoundsRecord(const bool isScalar, const Stats<T> &stats,
+    void WriteBoundsRecord(const bool singleValue, const Stats<T> &stats,
                            uint8_t &characteristicsCounter,
                            std::vector<char> &buffer,
                            size_t &position) noexcept;
@@ -260,19 +252,6 @@ private:
      * @param buffer
      */
     void FlattenMetadata() noexcept;
-
-    /**
-     * Writes the ADIOS log information (buffering, open, write and close) for a
-     * rank process
-     * @param rank current rank
-     * @param metadataSet contains Profile info for buffering
-     * @param transports  contains Profile info for transport open, writes and
-     * close
-     * @return string for this rank that will be aggregated into profiling.log
-     */
-    std::string GetRankProfilingLog(
-        const unsigned int rank,
-        const std::vector<std::shared_ptr<Transport>> &transports) noexcept;
 };
 
 #define declare_template_instantiation(T)                                      \
@@ -285,7 +264,7 @@ private:
     extern template void BP1Writer::WriteVariableMetadata(                     \
         const Variable<T> &variable) noexcept;
 
-ADIOS_FOREACH_TYPE_1ARG(declare_template_instantiation)
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
 #undef declare_template_instantiation
 
 } // end namespace format
diff --git a/source/adios2/utilities/format/bp1/BP1Writer.tcc b/source/adios2/toolkit/format/bp1/BP1Writer.tcc
similarity index 88%
rename from source/adios2/utilities/format/bp1/BP1Writer.tcc
rename to source/adios2/toolkit/format/bp1/BP1Writer.tcc
index 79315b10eb67a0d42f47172c885391c130c3cd51..31eac673a05c903ac5b71193d846aafad31cadac 100644
--- a/source/adios2/utilities/format/bp1/BP1Writer.tcc
+++ b/source/adios2/toolkit/format/bp1/BP1Writer.tcc
@@ -5,13 +5,15 @@
  * BP1Writer.tcc
  *
  *  Created on: Apr 11, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
-#ifndef ADIOS2_UTILITIES_FORMAT_BP1_BP1WRITER_TCC_
-#define ADIOS2_UTILITIES_FORMAT_BP1_BP1WRITER_TCC_
+#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_TCC_
+#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_TCC_
 
 #include "BP1Writer.h"
 
+#include "adios2/helper/adiosFunctions.h"
+
 namespace adios
 {
 namespace format
@@ -23,13 +25,13 @@ BP1Writer::ResizeResult BP1Writer::ResizeBuffer(const Variable<T> &variable)
 {
     size_t variableData =
         GetVariableIndexSize(variable) + variable.PayLoadSize();
-    size_t requiredCapacity = variableData + m_Heap.m_DataPosition;
+    size_t requiredCapacity = variableData + m_HeapBuffer.m_DataPosition;
 
     if (requiredCapacity > m_MaxBufferSize && m_MaxBufferSize > 0) // is set
     {
-        if (m_Heap.GetDataSize() < m_MaxBufferSize)
+        if (m_HeapBuffer.GetDataSize() < m_MaxBufferSize)
         {
-            m_Heap.ResizeData(m_MaxBufferSize);
+            m_HeapBuffer.ResizeData(m_MaxBufferSize);
             return ResizeResult::FLUSH;
         }
     }
@@ -40,6 +42,11 @@ BP1Writer::ResizeResult BP1Writer::ResizeBuffer(const Variable<T> &variable)
 template <class T>
 void BP1Writer::WriteVariableMetadata(const Variable<T> &variable) noexcept
 {
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Resume();
+    }
+
     Stats<typename TypeInfo<T>::ValueType> stats = GetStats(variable);
 
     stats.TimeIndex = m_MetadataSet.TimeStep;
@@ -50,23 +57,37 @@ void BP1Writer::WriteVariableMetadata(const Variable<T> &variable) noexcept
     stats.MemberID = variableIndex.MemberID;
 
     // write metadata header in data and extract offsets
-    stats.Offset = m_Heap.m_DataAbsolutePosition;
+    stats.Offset = m_HeapBuffer.m_DataAbsolutePosition;
     WriteVariableMetadataInData(variable, stats);
-    stats.PayloadOffset = m_Heap.m_DataAbsolutePosition;
+    stats.PayloadOffset = m_HeapBuffer.m_DataAbsolutePosition;
 
     // write to metadata  index
     WriteVariableMetadataInIndex(variable, stats, isNew, variableIndex);
 
     ++m_MetadataSet.DataPGVarsCount;
+
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Pause();
+    }
 }
 
 template <class T>
 void BP1Writer::WriteVariablePayload(const Variable<T> &variable) noexcept
 {
-    // EXPENSIVE part, might want to use threads if large, serial for now
-    CopyToBufferThreads(m_Heap.m_Data, m_Heap.m_DataPosition,
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Resume();
+    }
+
+    CopyToBufferThreads(m_HeapBuffer.m_Data, m_HeapBuffer.m_DataPosition,
                         variable.m_AppValues, variable.TotalSize(), m_Threads);
-    m_Heap.m_DataAbsolutePosition += variable.PayLoadSize();
+    m_HeapBuffer.m_DataAbsolutePosition += variable.PayLoadSize();
+
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("buffering").Pause();
+    }
 }
 
 // PRIVATE
@@ -80,7 +101,7 @@ size_t BP1Writer::GetVariableIndexSize(const Variable<T> &variable) const
     indexSize += variable.m_Name.size();
 
     // characteristics 3 and 4, check variable number of dimensions
-    const size_t dimensions = variable.DimensionsSize();
+    const size_t dimensions = variable.m_Count.size();
     indexSize += 28 * dimensions; // 28 bytes per dimension
     indexSize += 1;               // id
 
@@ -127,8 +148,8 @@ void BP1Writer::WriteVariableMetadataInData(
     const Variable<T> &variable,
     const Stats<typename TypeInfo<T>::ValueType> &stats) noexcept
 {
-    auto &buffer = m_Heap.m_Data;
-    auto &position = m_Heap.m_DataPosition;
+    auto &buffer = m_HeapBuffer.m_Data;
+    auto &position = m_HeapBuffer.m_DataPosition;
 
     // for writing length at the end
     const size_t varLengthPosition = position;
@@ -168,7 +189,7 @@ void BP1Writer::WriteVariableMetadataInData(
     size_t backPosition = varLengthPosition;
     CopyToBuffer(buffer, backPosition, &varLength);
 
-    m_Heap.m_DataAbsolutePosition += position - varLengthPosition;
+    m_HeapBuffer.m_DataAbsolutePosition += position - varLengthPosition;
 }
 
 template <class T>
@@ -179,8 +200,8 @@ void BP1Writer::WriteVariableMetadataInIndex(
 {
     auto &buffer = index.Buffer;
 
-    if (isNew == true) // write variable header (might be shared with
-                       // attributes index)
+    if (isNew) // write variable header (might be shared with
+               // attributes index)
     {
         buffer.insert(buffer.end(), 4, 0); // skip var length (4)
         InsertToBuffer(buffer, &stats.MemberID);
@@ -213,7 +234,7 @@ void BP1Writer::WriteBoundsRecord(const bool isScalar, const Stats<T> &stats,
                                   std::uint8_t &characteristicsCounter,
                                   std::vector<char> &buffer) noexcept
 {
-    if (isScalar == true)
+    if (isScalar)
     {
         // stats.min = stats.max = value, need to test
         WriteCharacteristicRecord(characteristic_value, characteristicsCounter,
@@ -233,12 +254,12 @@ void BP1Writer::WriteBoundsRecord(const bool isScalar, const Stats<T> &stats,
 }
 
 template <class T>
-void BP1Writer::WriteBoundsRecord(const bool isScalar, const Stats<T> &stats,
+void BP1Writer::WriteBoundsRecord(const bool singleValue, const Stats<T> &stats,
                                   std::uint8_t &characteristicsCounter,
                                   std::vector<char> &buffer,
                                   size_t &position) noexcept
 {
-    if (isScalar == true)
+    if (singleValue)
     {
         // stats.min = stats.max = value, need to test
         WriteCharacteristicRecord(characteristic_value, characteristicsCounter,
@@ -311,7 +332,7 @@ void BP1Writer::WriteVariableCharacteristics(
                           buffer);
     ++characteristicsCounter;
 
-    WriteBoundsRecord(variable.m_IsScalar, stats, characteristicsCounter,
+    WriteBoundsRecord(variable.m_SingleValue, stats, characteristicsCounter,
                       buffer);
 
     WriteCharacteristicRecord(characteristic_time_index, characteristicsCounter,
@@ -365,7 +386,7 @@ void BP1Writer::WriteVariableCharacteristics(
     ++characteristicsCounter;
 
     // VALUE for SCALAR or STAT min, max for ARRAY
-    WriteBoundsRecord(variable.m_IsScalar, stats, characteristicsCounter,
+    WriteBoundsRecord(variable.m_SingleValue, stats, characteristicsCounter,
                       buffer, position);
     // TIME INDEX
     WriteCharacteristicRecord(characteristic_time_index, characteristicsCounter,
diff --git a/source/adios2/toolkit/interop/adios1/ADIOS1Common.cpp b/source/adios2/toolkit/interop/adios1/ADIOS1Common.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2f981e94c22d67b2595ca17e9bdc403a23803ed4
--- /dev/null
+++ b/source/adios2/toolkit/interop/adios1/ADIOS1Common.cpp
@@ -0,0 +1,212 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * ADIOS1Common.cpp
+ *
+ *  Created on: Jun 1, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
+ */
+
+#include "ADIOS1Common.h"
+#include "ADIOS1Common.tcc"
+
+#include "adios2/ADIOSMPI.h"
+#include "adios2/helper/adiosFunctions.h" //OpenModeToString, GetType
+
+extern int adios_verbose_level;
+extern int adios_errno;
+
+namespace adios
+{
+namespace interop
+{
+
+ADIOS1Common::ADIOS1Common(const std::string &groupName,
+                           const std::string &fileName, MPI_Comm mpiComm,
+                           const bool debugMode)
+: m_GroupName(groupName), m_FileName(fileName), m_MPIComm(mpiComm),
+  m_DebugMode(debugMode)
+{
+    Init();
+}
+
+ADIOS1Common::~ADIOS1Common() { Close(); }
+
+void ADIOS1Common::Advance() { Close(); }
+
+void ADIOS1Common::Close()
+{
+    if (m_IsFileOpen)
+    {
+        adios_close(m_ADIOSFile);
+        m_IsFileOpen = false;
+    }
+}
+
+// PRIVATE
+void ADIOS1Common::Init()
+{
+    if (!m_IsInitialized)
+    {
+        adios_init_noxml(m_MPIComm);
+        m_IsInitialized = true;
+    }
+    adios_declare_group(&m_ADIOSGroup, m_GroupName.c_str(), "",
+                        adios_stat_default);
+}
+
+void ADIOS1Common::InitParameters(const Params &parameters)
+{
+    auto itMaxBufferSize = parameters.find("max_size_MB");
+    if (itMaxBufferSize != parameters.end())
+    {
+        adios_set_max_buffer_size(std::stoul(itMaxBufferSize->second));
+    }
+
+    auto itVerbosity = parameters.find("verbose");
+    if (itVerbosity != parameters.end())
+    {
+        int verbosity = std::stoi(itVerbosity->second);
+        if (m_DebugMode)
+        {
+            if (verbosity < 0 || verbosity > 5)
+                throw std::invalid_argument(
+                    "ERROR: Method verbose argument must be an "
+                    "integer in the range [0,5], in call to "
+                    "Open or Engine constructor\n");
+        }
+        adios_verbose_level = verbosity;
+    }
+}
+
+void ADIOS1Common::InitTransports(
+    const std::vector<Params> &transportsParameters)
+{
+    for (const auto &parameters : transportsParameters)
+    {
+        auto itTransport = parameters.find("transport");
+
+        if (itTransport->second == "file" || itTransport->second == "File")
+        {
+            auto itLibrary = parameters.find("library");
+            if (itLibrary == parameters.end() ||
+                itLibrary->second == "POSIX") // use default POSIX
+            {
+                adios_select_method(m_ADIOSGroup, "POSIX", "", "");
+            }
+            else if (itLibrary->second == "MPI_File" ||
+                     itLibrary->second == "MPI-IO" ||
+                     itLibrary->second == "MPI")
+            {
+                adios_select_method(m_ADIOSGroup, "MPI", "", "");
+            }
+            else
+            {
+                if (m_DebugMode)
+                {
+                    throw std::invalid_argument(
+                        "ERROR: file transport library " + itLibrary->second +
+                        " for file " + m_FileName +
+                        " not supported, in ADIOS1 " + ", in call to Open\n");
+                }
+            }
+        }
+        else
+        {
+            if (m_DebugMode)
+                throw std::invalid_argument("ERROR: invalid transport " +
+                                            itTransport->second +
+                                            ", only transports of type "
+                                            "file supported in ADIOS1, in call "
+                                            "to Open\n");
+        }
+    }
+}
+
+bool ADIOS1Common::Open(const OpenMode openMode)
+{
+    adios_open(&m_ADIOSFile, m_GroupName.c_str(), m_FileName.c_str(),
+               OpenModeToString(openMode, true).c_str(), m_MPIComm);
+    if (adios_errno == err_no_error)
+    {
+        m_IsFileOpen = true;
+    }
+    return m_IsFileOpen;
+}
+
+bool ADIOS1Common::ReOpenAsNeeded()
+{
+    if (!m_IsFileOpen)
+    {
+        // Re-open in APPEND mode
+        adios_open(&m_ADIOSFile, m_GroupName.c_str(), m_FileName.c_str(), "a",
+                   m_MPIComm);
+        if (adios_errno == err_no_error)
+        {
+            m_IsFileOpen = true;
+            adios_delete_vardefs(m_ADIOSGroup);
+        }
+    }
+    return m_IsFileOpen;
+}
+
+void ADIOS1Common::DefineVariable(const std::string &name,
+                                  const ShapeID shapeID,
+                                  enum ADIOS_DATATYPES vartype,
+                                  const std::string ldims,
+                                  const std::string gdims,
+                                  const std::string offsets)
+{
+    switch (shapeID)
+    {
+    case ShapeID::GlobalValue:
+        adios_define_var(m_ADIOSGroup, name.c_str(), "", vartype, "", "", "");
+        break;
+    case ShapeID::LocalValue:
+        adios_define_var(m_ADIOSGroup, name.c_str(), "", vartype, "", "", "");
+        adios_define_attribute(m_ADIOSGroup, "ReadAsArray", name.c_str(),
+                               adios_byte, "1", nullptr);
+        break;
+    case ShapeID::GlobalArray:
+    case ShapeID::LocalArray:
+    case ShapeID::JoinedArray:
+        adios_define_var(m_ADIOSGroup, name.c_str(), "", vartype, ldims.c_str(),
+                         gdims.c_str(), offsets.c_str());
+        break;
+    }
+}
+
+std::string ADIOS1Common::DimsToCSVLocalAware(const Dims &dims)
+{
+    std::string dimsCSV;
+    bool localVariable = false;
+
+    for (const auto dim : dims)
+    {
+        dimsCSV += std::to_string(dim) + ",";
+        if (dim == JoinedDim || dim == IrregularDim)
+        {
+            localVariable = true;
+        }
+    }
+
+    if (!dimsCSV.empty())
+    {
+        dimsCSV.pop_back();
+    }
+
+    return dimsCSV;
+}
+
+// Explicit declaration of the public template methods
+#define declare_template_instantiation(T)                                      \
+    template void ADIOS1Common::WriteVariable<T>(                              \
+        const std::string &name, const ShapeID shapeID, const Dims ldims,      \
+        const Dims gdims, const Dims offsets, const T *values);
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
+} // end namespace interop
+} // end namespace adios
diff --git a/source/adios2/toolkit/interop/adios1/ADIOS1Common.h b/source/adios2/toolkit/interop/adios1/ADIOS1Common.h
new file mode 100644
index 0000000000000000000000000000000000000000..6e821fe768055ba45b45d145d751ab2d610b418c
--- /dev/null
+++ b/source/adios2/toolkit/interop/adios1/ADIOS1Common.h
@@ -0,0 +1,102 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * ADIOS1Common.h
+ *
+ *  Created on: Jun 1, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_INTEROP_ADIOS1_ADIOS1COMMON_H_
+#define ADIOS2_TOOLKIT_INTEROP_ADIOS1_ADIOS1COMMON_H_
+
+// Fake out the include guard from ADIOS1's mpidummy.h to prevent it from
+// getting included
+#ifdef _NOMPI
+#define __MPI_DUMMY_H__
+#define MPI_Comm int
+#endif
+#include <adios.h>
+#ifdef _NOMPI
+#undef MPI_Comm
+#undef __MPI_DUMMY_H__
+#endif
+
+#include "adios2/ADIOSMPICommOnly.h"
+#include "adios2/ADIOSMacros.h"
+#include "adios2/ADIOSTypes.h"
+
+namespace adios
+{
+namespace interop
+{
+
+class ADIOS1Common
+{
+public:
+    /** ADIOS1 unique group name created from IO class object name */
+    const std::string m_GroupName;
+
+    /**Save file name from constructor for Advance when re-open in ADIOS1 */
+    const std::string m_FileName;
+
+    const std::string m_OpenModeString;
+
+    bool m_IsInitialized = false; ///< set to true after calling adios_init()
+    int64_t m_ADIOSFile = 0;  ///< ADIOS1 file handler returned by adios_open()
+    int64_t m_ADIOSGroup = 0; ///< ADIOS1 group pointer that holds the ADIOS1
+                              /// variable definitions
+    bool m_IsFileOpen = false;
+
+    int m_VerboseLevel = 0;
+    ADIOS_ERRCODES m_ErrorNumber = static_cast<ADIOS_ERRCODES>(-1);
+
+    ADIOS1Common(const std::string &groupName, const std::string &fileName,
+                 MPI_Comm mpiComm, const bool debugMode);
+
+    ~ADIOS1Common();
+
+    void InitParameters(const Params &parameters);
+    void InitTransports(const std::vector<Params> &transportsParameters);
+    bool Open(const OpenMode openMode); // return true if file is opened
+    bool ReOpenAsNeeded(); // return true if file is open or reopened
+
+    template <class T>
+    void WriteVariable(const std::string &name, const ShapeID shapeID,
+                       const Dims ldims, const Dims gdims, const Dims offsets,
+                       const T *values);
+
+    void Advance();
+
+    void Close();
+
+private:
+    MPI_Comm m_MPIComm;
+    const bool m_DebugMode = false;
+
+    void Init();
+
+    void DefineVariable(const std::string &name, const ShapeID shapeID,
+                        enum ADIOS_DATATYPES vartype, const std::string ldims,
+                        const std::string gdims, const std::string offsets);
+
+    template <class T>
+    enum ADIOS_DATATYPES GetADIOS1Type() const;
+
+    std::string DimsToCSVLocalAware(const Dims &dims);
+};
+
+// Explicit declaration of the public template methods
+#define declare_template_instantiation(T)                                      \
+    extern template void ADIOS1Common::WriteVariable<T>(                       \
+        const std::string &name, const ShapeID shapeID, const Dims ldims,      \
+        const Dims gdims, const Dims offsets, const T *values);
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
+} // end namespace interop
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_INTEROP_ADIOS1_ADIOS1COMMON_H_ */
diff --git a/source/adios2/toolkit/interop/adios1/ADIOS1Common.tcc b/source/adios2/toolkit/interop/adios1/ADIOS1Common.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..877805bbb044c24d0b662d36b17969504dd89790
--- /dev/null
+++ b/source/adios2/toolkit/interop/adios1/ADIOS1Common.tcc
@@ -0,0 +1,131 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * ADIOS1Common.tcc
+ *
+ *  Created on: Jun 1, 2017
+ *      Author: Norbert Podhorszki pnorbert@ornl.gov
+ *              William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_INTEROP_ADIOS1_ADIOS1COMMON_TCC_
+#define ADIOS2_TOOLKIT_INTEROP_ADIOS1_ADIOS1COMMON_TCC_
+
+#include "ADIOS1Common.h"
+
+#include "adios2/helper/adiosFunctions.h" //GetType
+
+namespace adios
+{
+namespace interop
+{
+
+template <class T>
+void ADIOS1Common::WriteVariable(const std::string &name, const ShapeID shapeID,
+                                 const Dims ldims, const Dims gdims,
+                                 const Dims offsets, const T *values)
+{
+    if (ReOpenAsNeeded())
+    {
+        if (GetADIOS1Type<T>() != adios_unknown)
+        {
+            DefineVariable(
+                name, shapeID, GetADIOS1Type<T>(), DimsToCSVLocalAware(ldims),
+                DimsToCSVLocalAware(gdims), DimsToCSVLocalAware(offsets));
+            adios_write(m_ADIOSFile, name.c_str(), values);
+        }
+        else
+        {
+            throw std::invalid_argument("ERROR: ADIOS1 doesn't support type " +
+                                        GetType<T>() + ", in call to Write\n");
+        }
+    }
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<char>() const {
+    return adios_byte;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<unsigned char>() const {
+    return adios_unsigned_byte;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<short>() const {
+    return adios_short;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<unsigned short>() const {
+    return adios_unsigned_short;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<int>() const {
+    return adios_integer;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<unsigned int>() const {
+    return adios_unsigned_integer;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<long int>() const {
+    return adios_long;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<unsigned long int>() const {
+    return adios_unsigned_long;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<long long int>() const {
+
+    return adios_long;
+}
+
+template <>
+enum ADIOS_DATATYPES
+ADIOS1Common::GetADIOS1Type<unsigned long long int>() const {
+    return adios_unsigned_long;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<float>() const {
+    return adios_real;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<double>() const {
+    return adios_double;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<long double>() const {
+    return adios_unknown;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<cfloat>() const {
+    return adios_complex;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<cdouble>() const {
+    return adios_double_complex;
+}
+
+template <>
+enum ADIOS_DATATYPES ADIOS1Common::GetADIOS1Type<cldouble>() const {
+    return adios_unknown;
+}
+
+} // end namespace interop
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_INTEROP_ADIOS1_ADIOS1COMMON_TCC_ */
diff --git a/source/adios2/toolkit/interop/hdf5/HDF5Common.cpp b/source/adios2/toolkit/interop/hdf5/HDF5Common.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9edf3a4cee97fe92cdc3f1061eb6520da53f037a
--- /dev/null
+++ b/source/adios2/toolkit/interop/hdf5/HDF5Common.cpp
@@ -0,0 +1,242 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * HDF5Common.cpp
+ *
+ *  Created on: April 20, 2017
+ *      Author: Junmin
+ */
+
+#include "HDF5Common.h"
+#include "HDF5Common.tcc"
+
+#include <complex>
+#include <ios>
+#include <iostream>
+#include <stdexcept>
+
+#include "adios2/ADIOSMPI.h"
+
+namespace adios
+{
+namespace interop
+{
+
+HDF5Common::HDF5Common(const bool debugMode) : m_DebugMode(debugMode)
+{
+    m_DefH5TypeComplexFloat =
+        H5Tcreate(H5T_COMPOUND, sizeof(std::complex<float>));
+    H5Tinsert(m_DefH5TypeComplexFloat, "freal", 0, H5T_NATIVE_FLOAT);
+    H5Tinsert(m_DefH5TypeComplexFloat, "fimg", H5Tget_size(H5T_NATIVE_FLOAT),
+              H5T_NATIVE_FLOAT);
+
+    m_DefH5TypeComplexDouble =
+        H5Tcreate(H5T_COMPOUND, sizeof(std::complex<double>));
+    H5Tinsert(m_DefH5TypeComplexDouble, "dreal", 0, H5T_NATIVE_DOUBLE);
+    H5Tinsert(m_DefH5TypeComplexDouble, "dimg", H5Tget_size(H5T_NATIVE_DOUBLE),
+              H5T_NATIVE_DOUBLE);
+
+    m_DefH5TypeComplexLongDouble =
+        H5Tcreate(H5T_COMPOUND, sizeof(std::complex<long double>));
+    H5Tinsert(m_DefH5TypeComplexLongDouble, "ldouble real", 0,
+              H5T_NATIVE_LDOUBLE);
+    H5Tinsert(m_DefH5TypeComplexLongDouble, "ldouble img",
+              H5Tget_size(H5T_NATIVE_LDOUBLE), H5T_NATIVE_LDOUBLE);
+}
+
+void HDF5Common::Init(const std::string &name, MPI_Comm comm, bool toWrite)
+{
+    m_WriteMode = toWrite;
+    m_PropertyListId = H5Pcreate(H5P_FILE_ACCESS);
+
+#ifdef ADIOS2_HAVE_MPI
+    H5Pset_fapl_mpio(m_PropertyListId, comm, MPI_INFO_NULL);
+#endif
+
+    std::string ts0 = "/TimeStep0";
+
+    if (toWrite)
+    {
+        /*
+         * Create a new file collectively and release property list identifier.
+         */
+        m_FileId = H5Fcreate(name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT,
+                             m_PropertyListId);
+        if (m_FileId >= 0)
+        {
+            m_GroupId = H5Gcreate2(m_FileId, ts0.c_str(), H5P_DEFAULT,
+                                   H5P_DEFAULT, H5P_DEFAULT);
+
+            if (m_DebugMode)
+            {
+                if (m_GroupId < 0)
+                {
+                    throw std::ios_base::failure(
+                        "ERROR: Unable to create HDF5 group " + ts0 +
+                        " in call to Open\n");
+                }
+            }
+        }
+    }
+    else
+    {
+        // read a file collectively
+        m_FileId = H5Fopen(name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
+        if (m_FileId >= 0)
+        {
+            m_GroupId = H5Gopen(m_FileId, ts0.c_str(), H5P_DEFAULT);
+        }
+    }
+
+    H5Pclose(m_PropertyListId);
+}
+
+void HDF5Common::WriteTimeSteps()
+{
+    if (m_FileId < 0)
+    {
+        if (m_DebugMode)
+        {
+            throw std::invalid_argument("ERROR: invalid HDF5 file to record "
+                                        "timestep to, in call to Write\n");
+        }
+    }
+
+    if (!m_WriteMode)
+    {
+        return;
+    }
+
+    hid_t s = H5Screate(H5S_SCALAR);
+
+    hid_t attr = H5Acreate(m_FileId, "NumTimeSteps", H5T_NATIVE_UINT, s,
+                           H5P_DEFAULT, H5P_DEFAULT);
+    uint totalTimeSteps = m_CurrentTimeStep + 1;
+
+    if (m_GroupId < 0)
+    {
+        totalTimeSteps = m_CurrentTimeStep;
+    }
+
+    H5Awrite(attr, H5T_NATIVE_UINT, &totalTimeSteps);
+
+    H5Sclose(s);
+    H5Aclose(attr);
+}
+
+unsigned int HDF5Common::GetNumTimeSteps()
+{
+    if (m_WriteMode)
+    {
+        return -1;
+    }
+
+    if (m_FileId < 0)
+    {
+        if (m_DebugMode)
+        {
+            throw std::invalid_argument(
+                "ERROR: invalid HDF5 file to read timestep attribute.\n");
+        }
+    }
+
+    if (m_NumTimeSteps <= 0)
+    {
+        hid_t attr = H5Aopen(m_FileId, "NumTimeSteps", H5P_DEFAULT);
+
+        H5Aread(attr, H5T_NATIVE_UINT, &m_NumTimeSteps);
+        H5Aclose(attr);
+    }
+
+    return m_NumTimeSteps;
+}
+
+void HDF5Common::Close()
+{
+    if (m_FileId < 0)
+    {
+        return;
+    }
+
+    WriteTimeSteps();
+
+    if (m_GroupId >= 0)
+    {
+        H5Gclose(m_GroupId);
+    }
+
+    H5Fclose(m_FileId);
+    m_FileId = -1;
+    m_GroupId = -1;
+}
+
+void HDF5Common::Advance()
+{
+    if (m_GroupId >= 0)
+    {
+        H5Gclose(m_GroupId);
+        m_GroupId = -1;
+    }
+
+    if (m_WriteMode)
+    {
+        // m_GroupId = H5Gcreate2(m_FileId, tsname.c_str(), H5P_DEFAULT,
+        //                       H5P_DEFAULT, H5P_DEFAULT);
+    }
+    else
+    {
+        if (m_NumTimeSteps == 0)
+        {
+            GetNumTimeSteps();
+        }
+        if (m_CurrentTimeStep + 1 >= m_NumTimeSteps)
+        {
+            return;
+        }
+
+        std::string timeStepName =
+            "/TimeStep" + std::to_string(m_CurrentTimeStep + 1);
+        m_GroupId = H5Gopen(m_FileId, timeStepName.c_str(), H5P_DEFAULT);
+        if (m_GroupId < 0)
+        {
+            throw std::ios_base::failure("ERROR: unable to open HDF5 group " +
+                                         timeStepName + ", in call to Open\n");
+        }
+    }
+    ++m_CurrentTimeStep;
+}
+
+void HDF5Common::CheckWriteGroup()
+{
+    if (!m_WriteMode)
+    {
+        return;
+    }
+    if (m_GroupId >= 0)
+    {
+        return;
+    }
+
+    std::string timeStepName = "/TimeStep" + std::to_string(m_CurrentTimeStep);
+    m_GroupId = H5Gcreate2(m_FileId, timeStepName.c_str(), H5P_DEFAULT,
+                           H5P_DEFAULT, H5P_DEFAULT);
+
+    if (m_DebugMode)
+    {
+        if (m_GroupId < 0)
+        {
+            throw std::ios_base::failure(
+                "ERROR: HDF5: Unable to create group " + timeStepName);
+        }
+    }
+}
+
+#define declare_template_instantiation(T)                                      \
+    template void HDF5Common::Write(Variable<T> &variable, const T *value);
+
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
+} // end namespace interop
+} // end namespace adios
diff --git a/source/adios2/toolkit/interop/hdf5/HDF5Common.h b/source/adios2/toolkit/interop/hdf5/HDF5Common.h
new file mode 100644
index 0000000000000000000000000000000000000000..84151a2ec9d569f7bf5d3b474dd173cceb4b5907
--- /dev/null
+++ b/source/adios2/toolkit/interop/hdf5/HDF5Common.h
@@ -0,0 +1,81 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * HDF5CommonP.h
+ *
+ *  Created on: March 20, 2017
+ *      Author: Junmin
+ */
+
+#ifndef ADIOS2_TOOLKIT_INTEROP_HDF5_HDF5COMMON_H_
+#define ADIOS2_TOOLKIT_INTEROP_HDF5_HDF5COMMON_H_
+
+#include <hdf5.h>
+
+#include <string>
+
+#include "adios2/ADIOSMPICommOnly.h"
+#include "adios2/ADIOSMacros.h"
+#include "adios2/ADIOSTypes.h"
+#include "adios2/core/Variable.h"
+
+namespace adios
+{
+namespace interop
+{
+
+class HDF5Common
+{
+
+public:
+    /**
+     * Unique constructor for HDF5 file
+     * @param debugMode true: extra exception checks
+     */
+    HDF5Common(const bool debugMode);
+
+    void Init(const std::string &name, MPI_Comm comm, bool toWrite);
+
+    template <class T>
+    void Write(Variable<T> &variable, const T *values);
+
+    void Close();
+    void Advance();
+
+    unsigned int GetNumTimeSteps();
+    void WriteTimeSteps();
+
+    hid_t m_PropertyListId = -1;
+    hid_t m_FileId = -1;
+    hid_t m_GroupId = -1;
+
+    hid_t m_DefH5TypeComplexDouble;
+    hid_t m_DefH5TypeComplexFloat;
+    hid_t m_DefH5TypeComplexLongDouble;
+
+    unsigned int m_CurrentTimeStep = 0;
+
+    void CheckWriteGroup();
+
+    template <class T>
+    hid_t GetHDF5Type(); // should this be public?
+
+private:
+    const bool m_DebugMode;
+    bool m_WriteMode = false;
+    unsigned int m_NumTimeSteps = 0;
+};
+
+// Explicit declaration of the public template methods
+#define declare_template_instantiation(T)                                      \
+    extern template void HDF5Common::Write(Variable<T> &variable,              \
+                                           const T *value);
+
+ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation)
+#undef declare_template_instantiation
+
+} // end namespace interop
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_INTEROP_HDF5_HDF5COMMON_H_ */
diff --git a/source/adios2/toolkit/interop/hdf5/HDF5Common.tcc b/source/adios2/toolkit/interop/hdf5/HDF5Common.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..0a8c9ecd1ef76d040cf3776fac0ce229c9c4f170
--- /dev/null
+++ b/source/adios2/toolkit/interop/hdf5/HDF5Common.tcc
@@ -0,0 +1,184 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * HDF5Common.tcc
+ *
+ *  Created on: Jun 1, 2017
+ *      Author: Junmin
+ */
+
+#ifndef ADIOS2_TOOLKIT_INTEROP_HDF5_HDF5COMMON_TCC_
+#define ADIOS2_TOOLKIT_INTEROP_HDF5_HDF5COMMON_TCC_
+
+#include "HDF5Common.h"
+
+#include <vector>
+
+namespace adios
+{
+namespace interop
+{
+
+template <class T>
+void HDF5Common::Write(Variable<T> &variable, const T *values)
+{
+    CheckWriteGroup();
+    int dimSize = std::max(variable.m_Shape.size(), variable.m_Count.size());
+
+    std::vector<hsize_t> dimsf, count, offset;
+
+    for (int i = 0; i < dimSize; ++i)
+    {
+        if (variable.m_Shape.size() == dimSize)
+        {
+            dimsf.push_back(variable.m_Shape[i]);
+        }
+        else
+        {
+            dimsf.push_back(variable.m_Count[i]);
+        }
+
+        if (variable.m_Count.size() == dimSize)
+        {
+            count.push_back(variable.m_Count[i]);
+            if (variable.m_Start.size() == dimSize)
+            {
+                offset.push_back(variable.m_Start[i]);
+            }
+            else
+            {
+                offset.push_back(0);
+            }
+        }
+        else
+        {
+            count.push_back(variable.m_Shape[i]);
+            offset.push_back(0);
+        }
+    }
+
+    hid_t fileSpace = H5Screate_simple(dimSize, dimsf.data(), NULL);
+
+    hid_t h5Type = GetHDF5Type<T>();
+    hid_t dsetID = H5Dcreate(m_GroupId, variable.m_Name.c_str(), h5Type,
+                             fileSpace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+    // H5Sclose(fileSpace);
+
+    hid_t memSpace = H5Screate_simple(dimSize, count.data(), NULL);
+
+    // Select hyperslab
+    fileSpace = H5Dget_space(dsetID);
+    H5Sselect_hyperslab(fileSpace, H5S_SELECT_SET, offset.data(), NULL,
+                        count.data(), NULL);
+
+    //  Create property list for collective dataset write.
+
+    hid_t plistID = H5Pcreate(H5P_DATASET_XFER);
+#ifdef ADIOS2_HAVE_MPI
+    H5Pset_dxpl_mpio(plistID, H5FD_MPIO_COLLECTIVE);
+#endif
+    herr_t status;
+
+    status = H5Dwrite(dsetID, h5Type, memSpace, fileSpace, plistID, values);
+
+    if (status < 0)
+    {
+        if (m_DebugMode)
+        {
+            throw std::ios_base::failure(
+                "ERROR: HDF5 file Write failed, in call to Write\n");
+        }
+    }
+
+    H5Dclose(dsetID);
+    H5Sclose(fileSpace);
+    H5Sclose(memSpace);
+    H5Pclose(plistID);
+}
+
+template <>
+hid_t HDF5Common::GetHDF5Type<char>()
+{
+    return H5T_NATIVE_CHAR;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<unsigned char>()
+{
+    return H5T_NATIVE_UCHAR;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<short>()
+{
+    return H5T_NATIVE_SHORT;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<unsigned short>()
+{
+    return H5T_NATIVE_USHORT;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<int>()
+{
+    return H5T_NATIVE_INT;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<unsigned int>()
+{
+    return H5T_NATIVE_UINT;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<long int>()
+{
+    return H5T_NATIVE_LONG;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<unsigned long int>()
+{
+    return H5T_NATIVE_ULONG;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<long long int>()
+{
+    return H5T_NATIVE_LLONG;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<unsigned long long int>()
+{
+    return H5T_NATIVE_ULLONG;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<float>()
+{
+    return H5T_NATIVE_FLOAT;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<double>()
+{
+    return H5T_NATIVE_DOUBLE;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<long double>()
+{
+    return H5T_NATIVE_LDOUBLE;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<std::complex<float>>()
+{
+    return m_DefH5TypeComplexFloat;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<std::complex<double>>()
+{
+    return m_DefH5TypeComplexDouble;
+}
+template <>
+hid_t HDF5Common::GetHDF5Type<std::complex<long double>>()
+{
+    return m_DefH5TypeComplexLongDouble;
+}
+
+} // end namespace interop
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_INTEROP_HDF5_HDF5COMMON_H_ */
diff --git a/source/adios2/toolkit/profiling/iochrono/IOChrono.h b/source/adios2/toolkit/profiling/iochrono/IOChrono.h
new file mode 100644
index 0000000000000000000000000000000000000000..7898dd829c36dd6ba9230ba5daeac51f03772b9e
--- /dev/null
+++ b/source/adios2/toolkit/profiling/iochrono/IOChrono.h
@@ -0,0 +1,53 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * IOChrono.h
+ *
+ *  Created on: Mar 9, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_PROFILING_IOCHRONO_IOCHRONO_H_
+#define ADIOS2_TOOLKIT_PROFILING_IOCHRONO_IOCHRONO_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <unordered_map>
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/toolkit/profiling/iochrono/Timer.h"
+
+namespace adios
+{
+namespace profiling
+{
+
+/**
+ * Struct used to track
+ */
+struct IOChrono
+{
+
+    /**
+     * Create timers for each process
+     * <pre>
+     * Key: process name
+     * Value: see Timer class public API, use to track process time as a
+     * chronometer with Resume() and Pause() functions
+     * </pre>
+     */
+    std::unordered_map<std::string, Timer> Timers;
+
+    /** Create byte tracking counter for each process*/
+    std::unordered_map<std::string, size_t> Bytes;
+
+    /** flag to determine if IOChrono object is used */
+    bool IsActive = true;
+};
+
+} // end namespace profiling
+} // end namespace adios
+
+#endif /* ADIOS2_CORE_IOCHRONO_H_ */
diff --git a/source/adios2/toolkit/profiling/iochrono/Timer.cpp b/source/adios2/toolkit/profiling/iochrono/Timer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..627842fa8b6709383beafc9c5ba1d5b872f33b89
--- /dev/null
+++ b/source/adios2/toolkit/profiling/iochrono/Timer.cpp
@@ -0,0 +1,115 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Timer.cpp
+ *
+ *  Created on: Apr 4, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "Timer.h"
+
+#include "adios2/helper/adiosFunctions.h" //LocalTimeDate
+
+namespace adios
+{
+namespace profiling
+{
+
+Timer::Timer(const std::string process, const TimeUnit timeUnit,
+             const bool debug)
+: m_Process(process), m_TimeUnit(timeUnit), m_LocalTimeDate(LocalTimeDate()),
+  m_DebugMode(debug)
+{
+}
+
+void Timer::Resume() noexcept
+{
+    m_InitialTime = std::chrono::high_resolution_clock::now();
+    m_InitialTimeSet = true;
+}
+
+void Timer::Pause() noexcept
+{
+    m_ElapsedTime = std::chrono::high_resolution_clock::now();
+    m_ProcessTime += GetElapsedTime();
+}
+
+std::string Timer::GetShortUnits() const noexcept
+{
+    std::string units;
+    switch (m_TimeUnit)
+    {
+    case TimeUnit::Microseconds:
+        units = "mus";
+        break;
+    case TimeUnit::Milliseconds:
+        units = "ms";
+        break;
+    case TimeUnit::Seconds:
+        units = "s";
+        break;
+    case TimeUnit::Minutes:
+        units = "m";
+        break;
+    case TimeUnit::Hours:
+        units = "h";
+        break;
+    }
+    return units;
+}
+
+// PRIVATE
+int64_t Timer::GetElapsedTime()
+{
+    if (m_DebugMode)
+    {
+        if (!m_InitialTimeSet)
+        {
+            throw std::invalid_argument("ERROR: Resume() in process " +
+                                        m_Process + " not called\n");
+        }
+    }
+
+    int64_t time = -1;
+
+    switch (m_TimeUnit)
+    {
+
+    case TimeUnit::Microseconds:
+        time = std::chrono::duration_cast<std::chrono::microseconds>(
+                   m_ElapsedTime - m_InitialTime)
+                   .count();
+        break;
+
+    case TimeUnit::Milliseconds:
+        time = std::chrono::duration_cast<std::chrono::milliseconds>(
+                   m_ElapsedTime - m_InitialTime)
+                   .count();
+        break;
+
+    case TimeUnit::Seconds:
+        time = std::chrono::duration_cast<std::chrono::seconds>(m_ElapsedTime -
+                                                                m_InitialTime)
+                   .count();
+        break;
+
+    case TimeUnit::Minutes:
+        time = std::chrono::duration_cast<std::chrono::minutes>(m_ElapsedTime -
+                                                                m_InitialTime)
+                   .count();
+        break;
+
+    case TimeUnit::Hours:
+        time = std::chrono::duration_cast<std::chrono::hours>(m_ElapsedTime -
+                                                              m_InitialTime)
+                   .count();
+        break;
+    }
+
+    return time;
+}
+
+} // end namespace
+} // end namespace
diff --git a/source/adios2/toolkit/profiling/iochrono/Timer.h b/source/adios2/toolkit/profiling/iochrono/Timer.h
new file mode 100644
index 0000000000000000000000000000000000000000..88ea9671391796b33de6d9634eab2a1ac4c36700
--- /dev/null
+++ b/source/adios2/toolkit/profiling/iochrono/Timer.h
@@ -0,0 +1,79 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Timer.h
+ *
+ *  Created on: Apr 4, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_PROFILING_IOCHRONO_TIMER_H_
+#define ADIOS2_TOOLKIT_PROFILING_IOCHRONO_TIMER_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <chrono>
+#include <string>
+/// \endcond
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSTypes.h"
+
+namespace adios
+{
+namespace profiling
+{
+
+class Timer
+{
+
+public:
+    /** process name */
+    const std::string m_Process;
+
+    /** process elapsed time */
+    int64_t m_ProcessTime = 0;
+
+    /** time unit for elapsed time from ADIOSTypes.h */
+    const TimeUnit m_TimeUnit;
+
+    /** creation timedate from std::ctime */
+    std::string m_LocalTimeDate;
+
+    /**
+     * Timer object constructor using std::chrono class
+     * @param process name of process to be measured
+     * @param timeUnit (mus, ms, s, etc.) from ADIOSTypes.h TimeUnit
+     * @param debugMode true: additional exception checks (recommended)
+     */
+    Timer(const std::string process, const TimeUnit timeUnit,
+          const bool debugMode = false);
+
+    ~Timer() = default;
+
+    /** sets timer active to start counting */
+    void Resume() noexcept;
+
+    /** pauses timer (set to inactive) */
+    void Pause() noexcept;
+
+    /** Returns TimeUnit as a short std::string  */
+    std::string GetShortUnits() const noexcept;
+
+private:
+    /** true: extra exceptions */
+    const bool m_DebugMode = false;
+    /** Set at Resume */
+    std::chrono::time_point<std::chrono::high_resolution_clock> m_InitialTime;
+    /** Set at Pause */
+    std::chrono::time_point<std::chrono::high_resolution_clock> m_ElapsedTime;
+    /** Checks if m_InitialTime is set, timer is running */
+    bool m_InitialTimeSet = false;
+    /** called by Pause to get time between Pause and Resume */
+    int64_t GetElapsedTime();
+};
+
+} // end namespace profiling
+} // end namespace adios
+
+#endif /* ADIOS2_CORE_TIMER_H_ */
diff --git a/source/adios2/toolkit/transport/Transport.cpp b/source/adios2/toolkit/transport/Transport.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0320a0ccaa32ebce752367b4176eb5c64f9b505d
--- /dev/null
+++ b/source/adios2/toolkit/transport/Transport.cpp
@@ -0,0 +1,68 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Transport.cpp
+ *
+ *  Created on: Dec 5, 2016
+ *      Author: wfg
+ */
+
+#include "Transport.h"
+
+#include "adios2/ADIOSMPI.h"
+
+namespace adios
+{
+
+Transport::Transport(const std::string type, const std::string library,
+                     MPI_Comm mpiComm, const bool debugMode)
+: m_Type(type), m_Library(library), m_MPIComm(mpiComm), m_DebugMode(debugMode)
+{
+    MPI_Comm_rank(m_MPIComm, &m_RankMPI);
+    MPI_Comm_size(m_MPIComm, &m_SizeMPI);
+}
+
+void Transport::InitProfiler(const OpenMode openMode, const TimeUnit timeUnit)
+{
+    m_Profiler.Timers.emplace(std::make_pair(
+        "open", profiling::Timer("open", TimeUnit::Microseconds, m_DebugMode)));
+
+    if (openMode == OpenMode::Write)
+    {
+        m_Profiler.Timers.emplace(
+            "write", profiling::Timer("write", timeUnit, m_DebugMode));
+
+        m_Profiler.Bytes.emplace("write", 0);
+    }
+    else if (openMode == OpenMode::Append)
+    {
+        m_Profiler.Timers.emplace(
+            "append", profiling::Timer("append", timeUnit, m_DebugMode));
+        m_Profiler.Bytes.emplace("append", 0);
+    }
+    else if (openMode == OpenMode::Read)
+    {
+        m_Profiler.Timers.emplace(
+            "read", profiling::Timer("read", timeUnit, m_DebugMode));
+        m_Profiler.Bytes.emplace("read", 0);
+    }
+
+    m_Profiler.Timers.emplace(
+        "close",
+        profiling::Timer("close", TimeUnit::Microseconds, m_DebugMode));
+
+    m_Profiler.IsActive = true;
+}
+
+void Transport::SetBuffer(char * /*buffer*/, size_t /*size*/)
+{
+    if (m_DebugMode)
+    {
+        std::invalid_argument("ERROR: " + m_Name + " transport type " + m_Type +
+                              " using library " + m_Library +
+                              " doesn't implement the SetBuffer function\n");
+    }
+}
+
+} // end namespace adios
diff --git a/source/adios2/toolkit/transport/Transport.h b/source/adios2/toolkit/transport/Transport.h
new file mode 100644
index 0000000000000000000000000000000000000000..ac7a2c89426d5629dac4556a3f8d840461e88df4
--- /dev/null
+++ b/source/adios2/toolkit/transport/Transport.h
@@ -0,0 +1,88 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Transport.h defines Transport abstract base class
+ *
+ *  Created on: Oct 6, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_TRANSPORT_TRANSPORT_H_
+#define ADIOS2_TOOLKIT_TRANSPORT_TRANSPORT_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <string>
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSMPICommOnly.h"
+#include "adios2/ADIOSTypes.h"
+#include "adios2/toolkit/profiling/iochrono/IOChrono.h"
+
+namespace adios
+{
+/** Abstract Base class for transports */
+class Transport
+{
+
+public:
+    const std::string m_Type;    ///< transport type from derived class
+    const std::string m_Library; ///< library implementation (POSIX, Mdtm, etc.)
+    std::string m_Name; ///< from Open, unique identifier (e.g. filename)
+    OpenMode m_OpenMode = OpenMode::Undefined; ///< at Open from ADIOSTypes.h
+    bool m_IsOpen = false; ///< true: open for communication, false: unreachable
+    MPI_Comm m_MPIComm;    ///< current MPI communicator
+    int m_RankMPI = 0;     ///< from MPI_Comm_Rank
+    int m_SizeMPI = 1;     ///< from MPI_Comm_Size
+    profiling::IOChrono m_Profiler; ///< profiles Open, Write/Read, Close
+
+    /**
+     * Base constructor that all derived classes pass
+     * @param type from derived class
+     * @param mpiComm passed to m_MPIComm
+     * @param debugMode passed to m_DebugMode
+     */
+    Transport(const std::string type, const std::string library,
+              MPI_Comm mpiComm, const bool debugMode);
+
+    virtual ~Transport() = default;
+
+    void InitProfiler(const OpenMode openMode, const TimeUnit timeUnit);
+
+    /**
+     * Opens transport, required before SetBuffer, Write, Read, Flush, Close
+     * @param name
+     * @param openMode
+     */
+    virtual void Open(const std::string &name, const OpenMode openMode) = 0;
+
+    /**
+     * If OS buffered (FILE* or fstream), sets the buffer size
+     * @param buffer address for OS buffering
+     * @param size of OS buffer
+     */
+    virtual void SetBuffer(char *buffer, size_t size);
+
+    /**
+     * Writes to file stream
+     * @param buffer raw data to be written to file stream
+     * @param size number of bytes to be written to file stream
+     */
+    virtual void Write(const char *buffer, size_t size) = 0;
+
+    /** flushes current contents to physical medium without closing */
+    virtual void Flush() = 0;
+
+    /** closes current file, after this file becomes unreachable */
+    virtual void Close() = 0;
+
+protected:
+    /** true: turn on exceptions */
+    const bool m_DebugMode = false;
+};
+
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_TRANSPORT_TRANSPORT_H_ */
diff --git a/source/adios2/transport/file/FileDescriptor.cpp b/source/adios2/toolkit/transport/file/FileDescriptor.cpp
similarity index 52%
rename from source/adios2/transport/file/FileDescriptor.cpp
rename to source/adios2/toolkit/transport/file/FileDescriptor.cpp
index c64d6a4cfcdddcdd1b4de723f12c25c93046b495..1829d9c37c150a2d22d1e747141327cb80fc8b2b 100644
--- a/source/adios2/transport/file/FileDescriptor.cpp
+++ b/source/adios2/toolkit/transport/file/FileDescriptor.cpp
@@ -2,28 +2,31 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * FileDescriptor.cpp file descriptor
+ * FileDescriptor.cpp file I/O using POSIX I/O library
  *
  *  Created on: Oct 6, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "FileDescriptor.h"
 
 #include <fcntl.h>     // open
-#include <ios>         // std::ios_base::failure
 #include <stddef.h>    // write output
 #include <sys/stat.h>  // open
 #include <sys/types.h> // open
 #include <unistd.h>    // write, close
 
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <ios> //std::ios_base::failure
+/// \endcond
+
 namespace adios
 {
 namespace transport
 {
 
 FileDescriptor::FileDescriptor(MPI_Comm mpiComm, const bool debugMode)
-: Transport("POSIX_IO", mpiComm, debugMode)
+: Transport("File", "POSIX", mpiComm, debugMode)
 {
 }
 
@@ -35,90 +38,93 @@ FileDescriptor::~FileDescriptor()
     }
 }
 
-void FileDescriptor::Open(const std::string &name, const std::string accessMode)
+void FileDescriptor::Open(const std::string &name, const OpenMode openMode)
 {
     m_Name = name;
-    m_AccessMode = accessMode;
+    m_OpenMode = openMode;
 
-    if (accessMode == "w" || accessMode == "write")
+    if (openMode == OpenMode::Write)
     {
-        if (m_Profiler.IsActive == true)
+        if (m_Profiler.IsActive)
         {
-            m_Profiler.Timers[0].SetInitialTime();
+            m_Profiler.Timers.at("open").Resume();
         }
 
         m_FileDescriptor = open(m_Name.c_str(), O_WRONLY | O_CREAT, 0777);
 
-        if (m_Profiler.IsActive == true)
+        if (m_Profiler.IsActive)
         {
-            m_Profiler.Timers[0].SetTime();
+            m_Profiler.Timers.at("open").Pause();
         }
     }
-    else if (accessMode == "a" || accessMode == "append")
+    else if (openMode == OpenMode::Append)
     {
-        if (m_Profiler.IsActive == true)
+        if (m_Profiler.IsActive)
         {
-            m_Profiler.Timers[0].SetInitialTime();
+            m_Profiler.Timers.at("open").Resume();
         }
 
-        m_FileDescriptor = open(m_Name.c_str(),
-                                O_WRONLY | O_APPEND); // we need to change this
+        // TODO we need to change this to read/write
+        m_FileDescriptor = open(m_Name.c_str(), O_WRONLY | O_APPEND);
 
-        if (m_Profiler.IsActive == true)
+        if (m_Profiler.IsActive)
         {
-            m_Profiler.Timers[0].SetTime();
+            m_Profiler.Timers.at("open").Pause();
         }
     }
-    else if (accessMode == "r" || accessMode == "read")
+    else if (openMode == OpenMode::Read)
     {
-        if (m_Profiler.IsActive == true)
+        if (m_Profiler.IsActive)
         {
-            m_Profiler.Timers[0].SetInitialTime();
+            m_Profiler.Timers.at("open").Resume();
         }
 
         m_FileDescriptor = open(m_Name.c_str(), O_RDONLY);
 
-        if (m_Profiler.IsActive == true)
+        if (m_Profiler.IsActive)
         {
-            m_Profiler.Timers[0].SetTime();
+            m_Profiler.Timers.at("open").Pause();
         }
     }
 
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         if (m_FileDescriptor == -1)
         {
             throw std::ios_base::failure(
                 "ERROR: couldn't open file " + m_Name +
-                ", from call to Open in FD transport using "
+                ", from call to Open in FileDescriptor transport using "
                 "POSIX open. Does file exists?\n");
         }
     }
+
+    m_IsOpen = true;
 }
 
 void FileDescriptor::Write(const char *buffer, std::size_t size)
 {
-    if (m_Profiler.IsActive == true)
+    if (m_Profiler.IsActive)
     {
-        m_Profiler.Timers[1].SetInitialTime();
+        m_Profiler.Timers.at("write").Resume();
     }
 
     auto writtenSize = write(m_FileDescriptor, buffer, size);
 
-    if (m_Profiler.IsActive == true)
+    if (m_Profiler.IsActive)
     {
-        m_Profiler.Timers[1].SetTime();
+        m_Profiler.Timers.at("write").Pause();
     }
 
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         if (writtenSize == -1)
         {
-            throw std::ios_base::failure("ERROR: couldn't write to file " +
-                                         m_Name + ", in call to POSIX write\n");
+            throw std::ios_base::failure(
+                "ERROR: couldn't write to file " + m_Name +
+                ", in call to POSIX FileDescriptor write\n");
         }
 
-        if (static_cast<std::size_t>(writtenSize) != size)
+        if (static_cast<size_t>(writtenSize) != size)
         {
             throw std::ios_base::failure(
                 "ERROR: written size + " + std::to_string(writtenSize) +
@@ -128,21 +134,23 @@ void FileDescriptor::Write(const char *buffer, std::size_t size)
     }
 }
 
+void FileDescriptor::Flush() {}
+
 void FileDescriptor::Close()
 {
-    if (m_Profiler.IsActive == true)
+    if (m_Profiler.IsActive)
     {
-        m_Profiler.Timers[2].SetInitialTime();
+        m_Profiler.Timers.at("close").Resume();
     }
 
     int status = close(m_FileDescriptor);
 
-    if (m_Profiler.IsActive == true)
+    if (m_Profiler.IsActive)
     {
-        m_Profiler.Timers[2].SetTime();
+        m_Profiler.Timers.at("close").Pause();
     }
 
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         if (status == -1)
         {
diff --git a/source/adios2/toolkit/transport/file/FileDescriptor.h b/source/adios2/toolkit/transport/file/FileDescriptor.h
new file mode 100644
index 0000000000000000000000000000000000000000..065b2301ad2f2d5b6d1e5e445dec616b9b04e103
--- /dev/null
+++ b/source/adios2/toolkit/transport/file/FileDescriptor.h
@@ -0,0 +1,47 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * FileDescriptor.h wrapper of POSIX library functions for file I/O
+ *
+ *  Created on: Oct 6, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEDESCRIPTOR_H_
+#define ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEDESCRIPTOR_H_
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/toolkit/transport/Transport.h"
+
+namespace adios
+{
+namespace transport
+{
+
+/** File descriptor transport using the POSIX library */
+class FileDescriptor : public Transport
+{
+
+public:
+    FileDescriptor(MPI_Comm mpiComm, const bool debugMode);
+
+    ~FileDescriptor();
+
+    void Open(const std::string &name, const OpenMode openMode) final;
+
+    void Write(const char *buffer, size_t size) final;
+
+    /** Does nothing, each write is supposed to flush */
+    void Flush() final;
+
+    void Close() final;
+
+private:
+    /** POSIX file handle returned by Open */
+    int m_FileDescriptor = -1;
+};
+
+} // end namespace transport
+} // end namespace
+#endif /* ADIOS2_TRANSPORT_FILE_FILEDESCRIPTOR_H_ */
diff --git a/source/adios2/transport/file/FilePointer.cpp b/source/adios2/toolkit/transport/file/FilePointer.cpp
similarity index 58%
rename from source/adios2/transport/file/FilePointer.cpp
rename to source/adios2/toolkit/transport/file/FilePointer.cpp
index 3e889420b7d7a36f8b0bb99dde1d73f8254203ab..e637693ca8cacad55fa498748bb384bcce7ec742 100644
--- a/source/adios2/transport/file/FilePointer.cpp
+++ b/source/adios2/toolkit/transport/file/FilePointer.cpp
@@ -2,15 +2,17 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * FP.cpp
+ * FilePointer.cpp
  *
  *  Created on: Jan 6, 2017
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "FilePointer.h"
 
+/// \cond EXCLUDE_FROM_DOXYGEN
 #include <ios> //std::ios_base::failure
+/// \endcond
 
 namespace adios
 {
@@ -18,53 +20,54 @@ namespace transport
 {
 
 FilePointer::FilePointer(MPI_Comm mpiComm, const bool debugMode)
-: Transport("FILE*", mpiComm, debugMode)
+: Transport("File", "C stdio.h", mpiComm, debugMode)
 {
 }
 
 FilePointer::~FilePointer()
 {
-    if (m_File != nullptr)
+    if (m_File)
     {
         fclose(m_File);
     }
 }
 
-void FilePointer::Open(const std::string &name, const std::string accessMode)
+void FilePointer::Open(const std::string &name, const OpenMode openMode)
 {
     m_Name = name;
-    m_AccessMode = accessMode;
+    m_OpenMode = openMode;
 
-    if (accessMode == "w" || accessMode == "write")
+    if (m_OpenMode == OpenMode::Write)
     {
         m_File = fopen(name.c_str(), "w");
     }
-    else if (accessMode == "a" || accessMode == "append")
+    else if (m_OpenMode == OpenMode::Append)
     {
-        m_File = fopen(name.c_str(), "a");
+        m_File = fopen(name.c_str(), "a"); // need to change
     }
-    else if (accessMode == "r" || accessMode == "read")
+    else if (m_OpenMode == OpenMode::Read)
     {
         m_File = fopen(name.c_str(), "r");
     }
 
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         if (m_File == nullptr)
         {
             throw std::ios_base::failure(
                 "ERROR: couldn't open file " + name +
                 ", "
-                "in call to Open from File* transport\n");
+                "in call to Open from stdio.h FilePointer* transport\n");
         }
     }
+    m_IsOpen = true;
 }
 
-void FilePointer::SetBuffer(char *buffer, std::size_t size)
+void FilePointer::SetBuffer(char *buffer, size_t size)
 {
     int status = setvbuf(m_File, buffer, _IOFBF, size);
 
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         if (status == 1)
         {
@@ -75,16 +78,17 @@ void FilePointer::SetBuffer(char *buffer, std::size_t size)
     }
 }
 
-void FilePointer::Write(const char *buffer, std::size_t size)
+void FilePointer::Write(const char *buffer, size_t size)
 {
     fwrite(buffer, sizeof(char), size, m_File);
 
-    if (m_DebugMode == true)
+    if (m_DebugMode)
     {
         if (ferror(m_File))
         {
-            throw std::ios_base::failure("ERROR: couldn't write to file " +
-                                         m_Name + ", in call to File* write\n");
+            throw std::ios_base::failure(
+                "ERROR: couldn't write to file " + m_Name +
+                ", in call to FilePointer* transport write\n");
         }
     }
 }
diff --git a/source/adios2/toolkit/transport/file/FilePointer.h b/source/adios2/toolkit/transport/file/FilePointer.h
new file mode 100644
index 0000000000000000000000000000000000000000..414a1a71897ce845577bb4c554caaffa1e23eaae
--- /dev/null
+++ b/source/adios2/toolkit/transport/file/FilePointer.h
@@ -0,0 +1,55 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * FilePointer.h wrapper of C/C++ stdio.h for file I/O
+ *
+ *  Created on: Jan 6, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEPOINTER_H_
+#define ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEPOINTER_H_
+
+#include <stdio.h> // FILE*
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/toolkit/transport/Transport.h"
+
+namespace adios
+{
+namespace transport
+{
+
+/**
+ * Class that defines a transport method using C file pointer (FP) to
+ * streams
+ * FILE*
+ */
+class FilePointer : public Transport
+{
+
+public:
+    FilePointer(MPI_Comm mpiComm, const bool debugMode);
+
+    ~FilePointer();
+
+    void Open(const std::string &name, const OpenMode openMode) final;
+
+    void SetBuffer(char *buffer, size_t size) final;
+
+    void Write(const char *buffer, size_t size) final;
+
+    void Flush();
+
+    void Close();
+
+private:
+    /** C File pointer */
+    FILE *m_File = nullptr; // NULL or nullptr?
+};
+
+} // end namespace transport
+} // end namespace
+
+#endif /* ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEPOINTER_H_ */
diff --git a/source/adios2/toolkit/transport/file/FileStream.cpp b/source/adios2/toolkit/transport/file/FileStream.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e8adce2bc1dcbfbac509ffb76cdaaa14314777be
--- /dev/null
+++ b/source/adios2/toolkit/transport/file/FileStream.cpp
@@ -0,0 +1,116 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * FileStream.cpp
+ *
+ *  Created on: Oct 24, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "FileStream.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <ios> // std::ios_base::failure
+/// \endcond
+
+namespace adios
+{
+namespace transport
+{
+
+FileStream::FileStream(MPI_Comm mpiComm, const bool debugMode)
+: Transport("File", "fstream", mpiComm, debugMode)
+{
+}
+
+void FileStream::Open(const std::string &name, const OpenMode openMode)
+{
+    m_Name = name;
+    m_OpenMode = openMode;
+
+    if (m_OpenMode == OpenMode::Write)
+    {
+        m_FileStream.open(name, std::fstream::out);
+    }
+    else if (m_OpenMode == OpenMode::Append)
+    {
+        // to be changed to rw?
+        m_FileStream.open(name, std::fstream::out | std::fstream::app);
+    }
+    else if (m_OpenMode == OpenMode::Read)
+    {
+        m_FileStream.open(name, std::fstream::in);
+    }
+
+    if (m_DebugMode)
+    {
+        if (!m_FileStream)
+        {
+            throw std::ios_base::failure("ERROR: couldn't open file " + name +
+                                         ", in call to FileStream Open\n");
+        }
+    }
+    m_IsOpen = true;
+}
+
+void FileStream::SetBuffer(char *buffer, size_t size)
+{
+    m_FileStream.rdbuf()->pubsetbuf(buffer, size);
+    if (m_DebugMode)
+    {
+        if (!m_FileStream)
+        {
+            throw std::ios_base::failure("ERROR: couldn't SetBuffer to file " +
+                                         m_Name +
+                                         ", in call to FileStream SetBuffer\n");
+        }
+    }
+}
+
+void FileStream::Write(const char *buffer, size_t size)
+{
+    m_FileStream.write(buffer, size);
+
+    if (m_DebugMode)
+    {
+        if (!m_FileStream)
+        {
+            throw std::ios_base::failure("ERROR: couldn't write to file " +
+                                         m_Name +
+                                         ", in call to FileStream write\n");
+        }
+    }
+}
+
+void FileStream::Flush()
+{
+    m_FileStream.flush();
+    if (m_DebugMode)
+    {
+        if (!m_FileStream)
+        {
+            throw std::ios_base::failure("ERROR: couldn't flush to file " +
+                                         m_Name +
+                                         ", in call to FileStream Flush\n");
+        }
+    }
+}
+
+void FileStream::Close()
+{
+    m_FileStream.close();
+    if (m_DebugMode)
+    {
+        if (!m_FileStream)
+        {
+            throw std::ios_base::failure("ERROR: couldn't close file " +
+                                         m_Name +
+                                         ", in call to FileStream Close\n");
+        }
+    }
+    m_IsOpen = false;
+}
+
+} // end namespace transport
+} // end namespace adios
diff --git a/source/adios2/toolkit/transport/file/FileStream.h b/source/adios2/toolkit/transport/file/FileStream.h
new file mode 100644
index 0000000000000000000000000000000000000000..5708292b20d5b48d683cf51dbd2894bdabd4ad22
--- /dev/null
+++ b/source/adios2/toolkit/transport/file/FileStream.h
@@ -0,0 +1,51 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * FileStream.h wrapper of C++ fstream for file I/O
+ *
+ *  Created on: Oct 18, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_TRANSPORT_FILE_FILESTREAM_H_
+#define ADIOS2_TOOLKIT_TRANSPORT_FILE_FILESTREAM_H_
+
+#include <fstream>
+
+#include "adios2/ADIOSConfig.h"
+#include "adios2/toolkit/transport/Transport.h"
+
+namespace adios
+{
+namespace transport
+{
+
+/** File stream transport using C++ fstream */
+class FileStream : public Transport
+{
+
+public:
+    FileStream(MPI_Comm mpiComm, const bool debugMode);
+
+    ~FileStream() = default;
+
+    void Open(const std::string &name, const OpenMode openMode) final;
+
+    void SetBuffer(char *buffer, size_t size) final;
+
+    void Write(const char *buffer, size_t size) final;
+
+    void Flush() final;
+
+    void Close() final;
+
+private:
+    /** file stream using fstream library */
+    std::fstream m_FileStream;
+};
+
+} // end namespace transport
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEPOINTER_H_ */
diff --git a/source/adios2/toolkit/transport/wan/WANZmq.cpp b/source/adios2/toolkit/transport/wan/WANZmq.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb72e8c9fbdf91c12e99e592499c3aedd2348bf6
--- /dev/null
+++ b/source/adios2/toolkit/transport/wan/WANZmq.cpp
@@ -0,0 +1,144 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * WANZmq.cpp
+ *
+ *  Created on: May 26, 2017
+ *      Author: Jason Wang wangr1@ornl.gov
+ */
+
+#include "WANZmq.h"
+
+#include <zmq.h>
+
+namespace adios
+{
+namespace transport
+{
+
+WANZmq::WANZmq(const std::string ipAddress, const std::string port,
+               MPI_Comm mpiComm, const bool debugMode)
+: Transport("wan", "zmq", mpiComm, debugMode), m_IPAddress(ipAddress),
+  m_Port(port)
+{
+
+    if (m_DebugMode)
+    {
+        // TODO verify port is unsigned int
+    }
+}
+
+WANZmq::~WANZmq()
+{
+    if (m_Socket)
+    {
+        zmq_close(m_Socket);
+    }
+}
+
+void WANZmq::Open(const std::string &name, const OpenMode openMode)
+{
+    m_Name = name;
+    m_OpenMode = openMode;
+
+    if (m_OpenMode == OpenMode::Write || m_OpenMode == OpenMode::w)
+    {
+        if (m_Profiler.IsActive)
+        {
+            m_Profiler.Timers.at("open").Resume();
+        }
+
+        m_Socket = zmq_socket(m_Context, ZMQ_REQ);
+        const std::string fullIP("tcp://" + m_IPAddress + ":" + m_Port);
+        zmq_connect(m_Socket, fullIP.c_str());
+
+        if (m_Profiler.IsActive)
+        {
+            m_Profiler.Timers.at("open").Pause();
+        }
+    }
+    else if (m_OpenMode == OpenMode::Append || m_OpenMode == OpenMode::a)
+    {
+        if (m_DebugMode)
+        {
+            throw std::invalid_argument(
+                "ERROR: WAN transport " + m_Name +
+                " only supports "
+                "OpenMode:w (write/sender) and "
+                "OpenMode:r (read/receiver), in call to Open\n");
+        }
+    }
+    else if (m_OpenMode == OpenMode::Read || m_OpenMode == OpenMode::r)
+    {
+        if (m_Profiler.IsActive)
+        {
+            m_Profiler.Timers.at("open").Resume();
+        }
+
+        m_Socket = zmq_socket(m_Context, ZMQ_REP);
+        const std::string fullIP("tcp://" + m_IPAddress + ":" + m_Port);
+        zmq_bind(m_Socket, fullIP.c_str());
+
+        if (m_Profiler.IsActive)
+        {
+            m_Profiler.Timers.at("open").Pause();
+        }
+    }
+
+    if (m_DebugMode)
+    {
+        if (m_Socket == NULL) // something goes wrong
+        {
+            throw std::ios_base::failure(
+                "ERROR: couldn't open socket for address " + m_Name +
+                ", in call to WANZmq Open\n");
+        }
+    }
+    m_IsOpen = true;
+}
+
+void WANZmq::SetBuffer(char *buffer, size_t size) {}
+
+void WANZmq::Write(const char *buffer, size_t size)
+{
+
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("write").Resume();
+    }
+
+    int status = zmq_send(m_Socket, buffer, size, 0);
+    char ret[10];
+    zmq_recv(m_Socket, ret, 10, 0);
+
+    if (m_Profiler.IsActive)
+    {
+        m_Profiler.Timers.at("write").Pause();
+    }
+
+    if (m_DebugMode)
+    {
+        const std::string retString(ret);
+
+        if (status == -1 || retString != "OK") // TODO : verify this
+        {
+            throw std::ios_base::failure("ERROR: couldn't send message " +
+                                         m_Name +
+                                         ", in call to WANZmq write\n");
+        }
+    }
+}
+
+void WANZmq::Flush() {}
+
+void WANZmq::Close()
+{
+    if (m_Socket)
+    {
+        zmq_close(m_Socket);
+    }
+}
+
+} // end namespace transport
+} // end namespace adios
diff --git a/source/adios2/toolkit/transport/wan/WANZmq.h b/source/adios2/toolkit/transport/wan/WANZmq.h
new file mode 100644
index 0000000000000000000000000000000000000000..aacbcaeb5c36969783cd56247cbc021de13ebbf2
--- /dev/null
+++ b/source/adios2/toolkit/transport/wan/WANZmq.h
@@ -0,0 +1,63 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * WANZmq.h
+ *
+ *  Created on: May 26, 2017
+ *      Author: Jason Wang wangr1@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_TRANSPORT_WAN_WANZMQ_H_
+#define ADIOS2_TOOLKIT_TRANSPORT_WAN_WANZMQ_H_
+
+#include "adios2/toolkit/transport/Transport.h"
+
+namespace adios
+{
+namespace transport
+{
+
+class WANZmq : public Transport
+{
+
+public:
+    /**
+     *
+     * @param ipAddress
+     * @param port
+     * @param mpiComm
+     * @param debugMode
+     */
+    WANZmq(const std::string ipAddress, const std::string port,
+           MPI_Comm mpiComm, const bool debugMode);
+
+    ~WANZmq();
+
+    void Open(const std::string &name, const OpenMode openMode) final;
+
+    void SetBuffer(char *buffer, size_t size) final;
+
+    void Write(const char *buffer, size_t size) final;
+
+    void Flush() final;
+
+    void Close() final;
+
+    void SetAddress(const std::string address);
+
+private:
+    const std::string m_IPAddress;
+    std::string m_Port;
+
+    /** TODO: find out if is provided externally */
+    void *m_Context = NULL;
+
+    /** handler created by zmq */
+    void *m_Socket = NULL;
+};
+
+} // end namespace transport
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_TRANSPORT_WAN_WANZMQ_H_ */
diff --git a/source/adios2/toolkit/transportman/TransportMan.cpp b/source/adios2/toolkit/transportman/TransportMan.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..49a45a71e37d8f5892152986289241eeccf1d8ca
--- /dev/null
+++ b/source/adios2/toolkit/transportman/TransportMan.cpp
@@ -0,0 +1,240 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * TransportMan.cpp
+ *
+ *  Created on: May 23, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "TransportMan.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <set>
+/// \endcond
+
+#include "adios2/helper/adiosFunctions.h" //CreateDirectory
+#include "adios2/toolkit/transport/file/FileDescriptor.h"
+#include "adios2/toolkit/transport/file/FilePointer.h"
+#include "adios2/toolkit/transport/file/FileStream.h"
+
+namespace adios
+{
+namespace transportman
+{
+
+TransportMan::TransportMan(MPI_Comm mpiComm, const bool debugMode)
+: m_MPIComm(mpiComm), m_DebugMode(debugMode)
+{
+}
+
+void TransportMan::OpenFiles(const std::vector<std::string> &baseNames,
+                             const std::vector<std::string> &names,
+                             const OpenMode openMode,
+                             const std::vector<Params> &parametersVector,
+                             const bool profile)
+{
+    const unsigned int size = baseNames.size();
+
+    for (unsigned int i = 0; i < size; ++i)
+    {
+        const Params &parameters = parametersVector[i];
+        const std::string type(parameters.at("transport"));
+
+        if (type == "File" || type == "file") // need to create directory
+        {
+            CreateDirectory(baseNames[i]);
+            OpenFileTransport(names[i], openMode, parameters, profile);
+        }
+    }
+}
+
+std::vector<std::string> TransportMan::GetFilesBaseNames(
+    const std::string &baseName,
+    const std::vector<Params> &parametersVector) const
+{
+    if (parametersVector.size() <= 1)
+    {
+        return {baseName};
+    }
+
+    std::map<std::string, std::set<std::string>> typeTransportNames;
+    std::vector<std::string> baseNames;
+    baseNames.reserve(parametersVector.size());
+
+    for (const auto &parameters : parametersVector)
+    {
+        // Get transport name from user
+        std::string name(baseName);
+        SetParameterValue("Name", parameters, name); // if found in map
+
+        const std::string type(parameters.at("Transport"));
+        auto itType = typeTransportNames.find(type);
+
+        if (m_DebugMode)
+        {
+            // check if name exists for this transport type
+            if (itType->second.count(name) == 1)
+            {
+                throw std::invalid_argument(
+                    "ERROR: two IO AddTransport of the same type can't "
+                    "have the same name : " +
+                    name + ", use Name=value parameter, in "
+                           "call to Open");
+            }
+        }
+        itType->second.insert(name);
+        baseNames.push_back(name);
+    }
+    return baseNames;
+}
+
+bool TransportMan::CheckTransportIndex(const int index) const noexcept
+{
+    const int upperLimit = static_cast<int>(m_Transports.size());
+    const int lowerLimit = -1;
+    return CheckIndexRange(index, upperLimit, lowerLimit);
+}
+
+std::vector<std::string> TransportMan::GetTransportsTypes() noexcept
+{
+    std::vector<std::string> types;
+    types.reserve(m_Transports.size());
+
+    for (const auto &transport : m_Transports)
+    {
+        types.push_back(transport->m_Type);
+    }
+    return types;
+}
+
+std::vector<profiling::IOChrono *>
+TransportMan::GetTransportsProfilers() noexcept
+{
+    std::vector<profiling::IOChrono *> profilers;
+    profilers.reserve(m_Transports.size());
+
+    for (const auto &transport : m_Transports)
+    {
+        profilers.push_back(&transport->m_Profiler);
+    }
+    return profilers;
+}
+
+void TransportMan::CloseFiles(const int transportIndex, const char *buffer,
+                              const size_t size) noexcept
+{
+    if (transportIndex == -1)
+    {
+        for (auto &transport : m_Transports)
+        {
+            if (transport->m_Type == "File")
+            {
+                // make this truly asynch?
+                transport->Write(buffer, size);
+                transport->Close();
+            }
+        }
+    }
+    else
+    {
+        if (m_DebugMode)
+        {
+            if (m_Transports[transportIndex]->m_Type != "File")
+            {
+                throw std::invalid_argument(
+                    "ERROR: index " + std::to_string(transportIndex) +
+                    " doesn't come from a file transport in IO AddTransport, "
+                    "in call to Close\n");
+            }
+        }
+
+        m_Transports[transportIndex]->Write(buffer, size);
+        m_Transports[transportIndex]->Close();
+    }
+}
+
+bool TransportMan::AllTransportsClosed() const noexcept
+{
+    bool allClose = true;
+    for (const auto &transport : m_Transports)
+    {
+        if (transport->m_IsOpen)
+        {
+            allClose = false;
+            break;
+        }
+    }
+    return allClose;
+}
+
+// PRIVATE
+void TransportMan::OpenFileTransport(const std::string &fileName,
+                                     const OpenMode openMode,
+                                     const Params &parameters,
+                                     const bool profile)
+{
+    auto lf_SetFileTransport = [&](const std::string library,
+                                   std::shared_ptr<Transport> &transport) {
+        if (library == "POSIX")
+        {
+            transport = std::make_shared<transport::FileDescriptor>(
+                m_MPIComm, m_DebugMode);
+        }
+        else if (library == "stdio")
+        {
+            transport = std::make_shared<transport::FilePointer>(m_MPIComm,
+                                                                 m_DebugMode);
+        }
+        else if (library == "fstream")
+        {
+            transport =
+                std::make_shared<transport::FileStream>(m_MPIComm, m_DebugMode);
+        }
+        else
+        {
+            if (m_DebugMode)
+            {
+                throw std::invalid_argument(
+                    "ERROR: invalid IO AddTransport library " + library +
+                    ", only POSIX, stdio, fstream are supported\n");
+            }
+        }
+    };
+
+    auto lf_GetLibrary = [](const std::string defaultLibrary,
+                            const Params &parameters) -> std::string {
+
+        std::string library(defaultLibrary);
+        SetParameterValue("Library", parameters, library);
+        return library;
+    };
+
+    auto lf_GetTimeUnits = [&](const std::string defaultTimeUnit,
+                               const Params &parameters) -> TimeUnit {
+
+        std::string profileUnits(defaultTimeUnit);
+        SetParameterValue("ProfileUnits", parameters, profileUnits);
+        return StringToTimeUnit(profileUnits, m_DebugMode);
+    };
+
+    // BODY OF FUNCTION starts here
+    std::shared_ptr<Transport> transport;
+    lf_SetFileTransport(lf_GetLibrary(DefaultFileLibrary, parameters),
+                        transport);
+
+    // Default or user ProfileUnits in parameters
+    if (profile)
+    {
+        transport->InitProfiler(openMode,
+                                lf_GetTimeUnits(DefaultTimeUnit, parameters));
+    }
+
+    // open and move transport to container
+    transport->Open(fileName, openMode);
+    m_Transports.push_back(std::move(transport)); // is move needed?
+}
+
+} // end namespace transport
+} // end namespace adios
diff --git a/source/adios2/toolkit/transportman/TransportMan.h b/source/adios2/toolkit/transportman/TransportMan.h
new file mode 100644
index 0000000000000000000000000000000000000000..23c728b14513420afb6dfbd4076871d3a34b5d23
--- /dev/null
+++ b/source/adios2/toolkit/transportman/TransportMan.h
@@ -0,0 +1,114 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * TransportMan.h : manages a vector of transports
+ *
+ *  Created on: May 23, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_TRANSPORT_TRANSPORTMANAGER_H_
+#define ADIOS2_TOOLKIT_TRANSPORT_TRANSPORTMANAGER_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <memory> //std::shared_ptr
+#include <string>
+#include <unordered_map>
+#include <vector>
+/// \endcond
+
+#include "adios2/ADIOSMPICommOnly.h"
+#include "adios2/toolkit/transport/Transport.h"
+
+namespace adios
+{
+namespace transportman
+{
+
+class TransportMan
+{
+
+public:
+    /** contains all transports from IO AddTransport
+     * <pre>
+     * key : unique id from IO AddTransport
+     * value : obejct derived from Transport.h class
+     * </pre>
+     */
+    std::vector<std::shared_ptr<Transport>> m_Transports;
+
+    /**
+     * Unique base constructor
+     * @param mpiComm
+     * @param debugMode
+     */
+    TransportMan(MPI_Comm mpiComm, const bool debugMode);
+
+    virtual ~TransportMan() = default;
+
+    /**
+     *
+     * @param baseNames passed from Open( name )
+     * @param names actual filenames (from BP)
+     * @param openMode
+     * @param parametersVector from IO
+     * @param profile
+     */
+    void OpenFiles(const std::vector<std::string> &baseNames,
+                   const std::vector<std::string> &names,
+                   const OpenMode openMode,
+                   const std::vector<Params> &parametersVector,
+                   const bool profile);
+
+    /**
+     * Gets each transport base name from either baseName at Open or name key in
+     * parameters
+     * Checks if transport name rules IO AddTransport have unique names for
+     * every type (for now)
+     * @param baseName from Open
+     * @param parameters from IO TransportsParameters (from AddTransport
+     * function)
+     * @return transport base names
+     */
+    std::vector<std::string>
+    GetFilesBaseNames(const std::string &baseName,
+                      const std::vector<Params> &parametersVector) const;
+
+    /**
+     * Checks if index is in range
+     * @param index input to be checked against m_Transports range or it's -1
+     * @param true: in range, false: out of range
+     */
+    bool CheckTransportIndex(const int index) const noexcept;
+
+    /**
+     * m_Type from m_Transports based on derived classes of Transport
+     * @return m_Type for each transport in m_Transports (e.g.
+     * {FileDescriptor,
+     * FilePointer} )
+     */
+    std::vector<std::string> GetTransportsTypes() noexcept;
+
+    /** Returns a vector of pointer references (not owning the memory) to
+     * m_Transports.m_Profiler */
+    std::vector<profiling::IOChrono *> GetTransportsProfilers() noexcept;
+
+    void CloseFiles(const int transportIndex, const char *buffer,
+                    const size_t size) noexcept;
+
+    /** Checks if all transports are closed */
+    bool AllTransportsClosed() const noexcept;
+
+protected:
+    MPI_Comm m_MPIComm;
+    const bool m_DebugMode = false;
+
+    void OpenFileTransport(const std::string &fileName, const OpenMode openMode,
+                           const Params &parameters, const bool profile);
+};
+
+} // end namespace transport
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_TRANSPORT_TRANSPORTMANAGER_H_ */
diff --git a/source/adios2/toolkit/transportman/dataman/DataMan.cpp b/source/adios2/toolkit/transportman/dataman/DataMan.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cd2774bbdbb9adfedb23bc92ba85c13d8995f1fe
--- /dev/null
+++ b/source/adios2/toolkit/transportman/dataman/DataMan.cpp
@@ -0,0 +1,110 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * DataMan.cpp
+ *
+ *  Created on: Jun 1, 2017
+ *      Author: Jason Wang wangr1@ornl.gov
+ */
+
+#include "DataMan.h"
+
+namespace adios
+{
+namespace transportman
+{
+
+DataMan::DataMan(MPI_Comm mpiComm, const bool debugMode)
+: TransportMan(mpiComm, debugMode)
+{
+}
+
+void DataMan::OpenWANTransports(const std::string &name,
+                                const OpenMode openMode,
+                                const std::vector<Params> &parametersVector,
+                                const bool profile)
+{
+    auto lf_GetParameter = [](const std::string key, const Params &params,
+                              const bool isMandatory,
+                              const bool debugMode) -> std::string {
+
+        std::string value;
+        auto itParameter = params.find(key);
+        if (itParameter == params.end())
+        {
+            if (debugMode && isMandatory)
+            {
+                throw std::invalid_argument(
+                    "ERROR: wan transport doesn't have mandatory parameter " +
+                    key +
+                    ", provide one in IO AddTransport, in call to Open\n");
+            }
+        }
+        else
+        {
+            value = itParameter->second;
+        }
+        return value;
+    };
+
+    for (const auto &parameters : parametersVector)
+    {
+        std::shared_ptr<Transport> wanTransport;
+
+        const std::string type(
+            lf_GetParameter("transport", parameters, true, m_DebugMode));
+
+        const std::string lib(
+            lf_GetParameter("lib", parameters, true, m_DebugMode));
+
+        const std::string ipAddress(
+            lf_GetParameter("ipaddress", parameters, true, m_DebugMode));
+
+        const std::string port(
+            lf_GetParameter("port", parameters, false, m_DebugMode));
+
+        if (port.empty())
+        {
+            port = m_DefaultPort;
+        }
+
+        const std::string messageName(
+            lf_GetParameter("name", parameters, false, m_DebugMode));
+
+        if (messageName.empty())
+        {
+            messageName = name;
+        }
+
+        if (type == "wan") // need to create directory
+        {
+            if (lib == "zmq")
+            {
+#ifdef ADIOS_HAVE_ZMQ
+                wanTransport = std::make_shared<transport::WANZmq>(
+                    ipAddress, port, m_MPIComm, m_DebugMode);
+#else
+                throw std::invalid_argument(
+                    "ERROR: this version of ADIOS2 didn't compile with "
+                    "ZMQ library, in call to Open\n");
+#endif
+            }
+            else
+            {
+                if (m_DebugMode)
+                {
+                    throw std::invalid_argument("ERROR: wan library " + lib +
+                                                " not supported or not "
+                                                "provided in IO AddTransport, "
+                                                "in call to Open\n");
+                }
+            }
+        }
+        wanTransport->Open(messageName, openMode);
+        m_Transports.push_back(std::move(wanTransport));
+    }
+}
+
+} // end namespace transportman
+} // end namespace adios
diff --git a/source/adios2/toolkit/transportman/dataman/DataMan.h b/source/adios2/toolkit/transportman/dataman/DataMan.h
new file mode 100644
index 0000000000000000000000000000000000000000..0954fb0c42d37c0e66da15492faf097f475314c5
--- /dev/null
+++ b/source/adios2/toolkit/transportman/dataman/DataMan.h
@@ -0,0 +1,45 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * DataMan.h
+ *
+ *  Created on: Jun 1, 2017
+ *      Author: Jason Wang wangr1@ornl.gov
+ */
+
+#ifndef ADIOS2_TOOLKIT_TRANSPORTMAN_DATAMAN_DATAMAN_H_
+#define ADIOS2_TOOLKIT_TRANSPORTMAN_DATAMAN_DATAMAN_H_
+
+#include "adios2/toolkit/transportman/TransportMan.h"
+
+#include <json.hpp>
+
+namespace adios
+{
+namespace transportman
+{
+
+class DataMan : public TransportMan
+{
+
+public:
+    DataMan(MPI_Comm mpiComm, const bool debugMode);
+
+    virtual ~DataMan() = default;
+
+    void OpenWANTransports(const std::string &name, const OpenMode openMode,
+                           const std::vector<Params> &parametersVector,
+                           const bool profile);
+
+private:
+    nlohmann::json m_JMessage;
+
+    /** Pick the appropriate default */
+    const std::string m_DefaultPort = "22";
+};
+
+} // end namespace transportman
+} // end namespace adios
+
+#endif /* ADIOS2_TOOLKIT_TRANSPORTMAN_DATAMAN_DATAMAN_H_ */
diff --git a/source/adios2/transform/BZip2.cpp b/source/adios2/transform/compression/BZip2.cpp
similarity index 92%
rename from source/adios2/transform/BZip2.cpp
rename to source/adios2/transform/compression/BZip2.cpp
index d0991b3a44fc85dad6ba92195d381f427b3c4148..e1d28134eafbb86f6424ef3b10cbf1cc1d124e16 100644
--- a/source/adios2/transform/BZip2.cpp
+++ b/source/adios2/transform/compression/BZip2.cpp
@@ -5,7 +5,7 @@
  * BZIP2.cpp
  *
  *  Created on: Oct 19, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "BZip2.h"
diff --git a/source/adios2/transform/BZip2.h b/source/adios2/transform/compression/BZip2.h
similarity index 84%
rename from source/adios2/transform/BZip2.h
rename to source/adios2/transform/compression/BZip2.h
index bf16fa75750c6e102ca920df3056352b9323273d..215f7d398730206486f72293abf01ed231ef0401 100644
--- a/source/adios2/transform/BZip2.h
+++ b/source/adios2/transform/compression/BZip2.h
@@ -5,11 +5,11 @@
  * BZip2.h
  *
  *  Created on: Oct 17, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
-#ifndef ADIOS2_TRANSFORM_BZIP2_H_
-#define ADIOS2_TRANSFORM_BZIP2_H_
+#ifndef ADIOS2_TRANSFORM_COMPRESSION_BZIP2_H_
+#define ADIOS2_TRANSFORM_COMPRESSION_BZIP2_H_
 
 #include "adios2/ADIOSConfig.h"
 #include "adios2/core/Transform.h"
diff --git a/source/adios2/transport/file/FStream.cpp b/source/adios2/transport/file/FStream.cpp
deleted file mode 100644
index a22f83da196504c55a520d7927920902cc08ff75..0000000000000000000000000000000000000000
--- a/source/adios2/transport/file/FStream.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * CFStream.cpp
- *
- *  Created on: Oct 24, 2016
- *      Author: wfg
- */
-
-#include "FStream.h"
-
-#include <ios> // std::ios_base::failure
-#include <stdexcept>
-
-namespace adios
-{
-namespace transport
-{
-
-FStream::FStream(MPI_Comm mpiComm, const bool debugMode)
-: Transport("fstream", mpiComm, debugMode)
-{
-}
-
-void FStream::Open(const std::string &name, const std::string accessMode)
-{
-    m_Name = name;
-    m_AccessMode = accessMode;
-
-    if (accessMode == "w" || accessMode == "write")
-    {
-        m_FStream.open(name, std::fstream::out);
-    }
-    else if (accessMode == "a" || accessMode == "append")
-    {
-        m_FStream.open(name, std::fstream::out | std::fstream::app);
-    }
-    else if (accessMode == "r" || accessMode == "read")
-    {
-        m_FStream.open(name, std::fstream::in);
-    }
-
-    if (m_DebugMode == true)
-    {
-        if (!m_FStream)
-        {
-            throw std::ios_base::failure(
-                "ERROR: couldn't open file " + name +
-                ", in call to Open from FStream transport\n");
-        }
-    }
-}
-
-void FStream::SetBuffer(char *buffer, std::size_t size)
-{
-    m_FStream.rdbuf()->pubsetbuf(buffer, size);
-}
-
-void FStream::Write(const char *buffer, std::size_t size)
-{
-    m_FStream.write(buffer, size);
-
-    if (m_DebugMode == true)
-    {
-        if (!m_FStream)
-        {
-            throw std::ios_base::failure("ERROR: couldn't write to file " +
-                                         m_Name +
-                                         ", in call to FStream write\n");
-        }
-    }
-}
-
-void FStream::Flush() { m_FStream.flush(); }
-
-void FStream::Close() { m_FStream.close(); }
-
-} // end namespace transport
-} // end namespace adios
diff --git a/source/adios2/transport/file/FStream.h b/source/adios2/transport/file/FStream.h
deleted file mode 100644
index a0436d788f0dde895d0ad44f08057b0b5d2f9d52..0000000000000000000000000000000000000000
--- a/source/adios2/transport/file/FStream.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * FStream.h
- *
- *  Created on: Oct 18, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_TRANSPORT_FILE_FSTREAM_H_
-#define ADIOS2_TRANSPORT_FILE_FSTREAM_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <fstream>
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Transport.h"
-
-namespace adios
-{
-namespace transport
-{
-
-/**
- * File stream transport using C++ fstream
- */
-class FStream : public Transport
-{
-
-public:
-    FStream(MPI_Comm mpiComm, const bool debugMode);
-
-    virtual ~FStream() = default;
-
-    void Open(const std::string &name, const std::string accessMode);
-
-    void SetBuffer(char *buffer, std::size_t size);
-
-    void Write(const char *buffer, std::size_t size);
-
-    void Flush();
-
-    void Close();
-
-private:
-    std::fstream m_FStream; ///< file stream under name.bp.dir/name.bp.rank
-};
-
-} // end namespace transport
-} // end namespace adios
-
-#endif /* ADIOS2_TRANSPORT_FILE_FSTREAM_H_ */
diff --git a/source/adios2/transport/file/FileDescriptor.h b/source/adios2/transport/file/FileDescriptor.h
deleted file mode 100644
index 7b87d13c3c959ffa9feb908e416a89c06aa901fc..0000000000000000000000000000000000000000
--- a/source/adios2/transport/file/FileDescriptor.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * FileDescriptor.h uses POSIX as the underlying library
- *
- *  Created on: Oct 6, 2016
- *      Author: wfg
- */
-
-#ifndef ADIOS2_TRANSPORT_FILE_FILEDESCRIPTOR_H_
-#define ADIOS2_TRANSPORT_FILE_FILEDESCRIPTOR_H_
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Transport.h"
-
-namespace adios
-{
-namespace transport
-{
-
-/**
- * File descriptor transport using the POSIX library
- */
-class FileDescriptor : public Transport
-{
-
-public:
-    FileDescriptor(MPI_Comm mpiComm, const bool debugMode);
-
-    ~FileDescriptor();
-
-    void Open(const std::string &name, const std::string accessMode);
-
-    void Write(const char *buffer, std::size_t size);
-
-    void Close();
-
-private:
-    int m_FileDescriptor = -1; ///< file descriptor returned by POSIX open
-};
-
-} // end namespace transport
-} // end namespace
-#endif /* ADIOS2_TRANSPORT_FILE_FILEDESCRIPTOR_H_ */
diff --git a/source/adios2/transport/file/FilePointer.h b/source/adios2/transport/file/FilePointer.h
deleted file mode 100644
index 8761127044dc8114bf2fa93d4080226127f41ff7..0000000000000000000000000000000000000000
--- a/source/adios2/transport/file/FilePointer.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * FilePointer.h
- *
- *  Created on: Jan 6, 2017
- *      Author: wfg
- */
-
-#ifndef ADIOS2_TRANSPORT_FILE_FILEPOINTER_H_
-#define ADIOS2_TRANSPORT_FILE_FILEPOINTER_H_
-
-/// \cond EXCLUDE_FROM_DOXYGEN
-#include <stdio.h> // FILE*
-/// \endcond
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Transport.h"
-
-namespace adios
-{
-namespace transport
-{
-
-/**
- * Class that defines a transport method using C file pointer (FP) to streams
- * FILE*
- */
-class FilePointer : public Transport
-{
-
-public:
-    FilePointer(MPI_Comm mpiComm, const bool debugMode);
-
-    ~FilePointer();
-
-    void Open(const std::string &name, const std::string accessMode);
-
-    void SetBuffer(char *buffer, std::size_t size);
-
-    void Write(const char *buffer, std::size_t size);
-
-    void Flush();
-
-    void Close();
-
-private:
-    FILE *m_File = NULL; ///< C file pointer
-};
-
-} // end namespace transport
-} // end namespace
-
-#endif /* ADIOS2_TRANSPORT_FILE_FILEPOINTER_H_ */
diff --git a/source/adios2/transport/file/MPI_File.h b/source/adios2/transport/file/MPI_File.h
deleted file mode 100644
index 255d55983cc75e2ba111d1cc126f9caa3ae02380..0000000000000000000000000000000000000000
--- a/source/adios2/transport/file/MPI_File.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * MPIFile.h
- *
- *  Created on: Jan 5, 2017
- *      Author: wfg
- */
-
-#ifndef ADIOS2_TRANSPORT_FILE_MPI_FILE_H_
-#define ADIOS2_TRANSPORT_FILE_MPI_FILE_H_
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/ADIOSMPICommOnly.h"
-
-namespace adios
-{
-namespace transport
-{
-
-/**
- * Class that defines a transport method using C++ file streams
- */
-class MPI_File : public Transport
-{
-
-public:
-    MPI_File(MPI_Comm mpiComm, const bool debugMode);
-
-    ~MPI_File();
-
-    void Open(const std::string streamName, const std::string accessMode);
-
-    void SetBuffer(char *buffer, std::size_t size);
-
-    void Write(const char *buffer, std::size_t size);
-
-    void Flush();
-
-    void Close();
-
-private:
-    MPI_File m_MPIFile; ///< MPI File
-};
-
-} // end namespace transport
-} // end namespace
-
-#endif /* ADIOS2_TRANSPORT_FILE_MPI_FILE_H_ */
diff --git a/source/adios2/transport/wan/MdtmMan.cpp b/source/adios2/transport/wan/MdtmMan.cpp
deleted file mode 100644
index 2394ed008434404ee309a364a780ffe0239032b2..0000000000000000000000000000000000000000
--- a/source/adios2/transport/wan/MdtmMan.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * MdtmMan.cpp
- *
- *  Created on: Jan 22, 2017
- *      Author: wfg
- */
-
-#include "MdtmMan.h"
-
-namespace adios
-{
-namespace transport
-{
-
-MdtmMan::MdtmMan(const std::string localIP, const std::string remoteIP,
-                 const std::string mode, const std::string prefix,
-                 const int numberOfPipes, const std::vector<int> tolerances,
-                 const std::vector<int> priorities, MPI_Comm mpiComm,
-                 const bool debugMode)
-: Transport("File", mpiComm, debugMode), m_LocalIP{localIP},
-  m_RemoteIP{remoteIP}, m_Mode{mode}, m_Prefix{prefix},
-  m_NumberOfPipes{numberOfPipes}, m_Tolerances{tolerances},
-  m_Priorities{priorities}
-{
-}
-
-void MdtmMan::Open(const std::string name, const std::string accessMode) {}
-
-void MdtmMan::SetBuffer(char *buffer, std::size_t size) {}
-
-void MdtmMan::Write(const char *buffer, std::size_t size) {}
-
-void MdtmMan::Flush() {}
-
-void MdtmMan::Close() { m_NumberOfPipes = -1; }
-
-// PRIVATE Functions
-int MdtmMan::Put(const void *data, const std::string doid,
-                 const std::string variable, const std::string dType,
-                 const std::vector<std::uint64_t> &putShape,
-                 const std::vector<uint64_t> &varShape,
-                 const std::vector<uint64_t> &offset,
-                 const std::uint64_t timestep, const int tolerance,
-                 const int priority)
-{
-
-    return 0;
-}
-
-int MdtmMan::Get(void *data, const std::string doid, const std::string variable,
-                 const std::string dType,
-                 const std::vector<std::uint64_t> &putShape,
-                 const std::vector<uint64_t> &varShape,
-                 const std::vector<uint64_t> &offset,
-                 const std::uint64_t timestep, const int tolerance,
-                 const int priority)
-{
-
-    return 0;
-}
-
-int MdtmMan::Get(void *data, const std::string doid, const std::string variable,
-                 const std::string dType, std::vector<std::uint64_t> &varShape,
-                 const std::uint64_t timestep)
-{
-
-    return 0;
-}
-
-void MdtmMan::OnReceive(nlohmann::json &jData) {}
-
-} // end namespace transport
-} // end namespace
diff --git a/source/adios2/transport/wan/MdtmMan.h b/source/adios2/transport/wan/MdtmMan.h
deleted file mode 100644
index 887ffae35d4e8936a89f8d9dada6e49152bc44a5..0000000000000000000000000000000000000000
--- a/source/adios2/transport/wan/MdtmMan.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * MdtmMan.h
- *
- *  Created on: Jan 18, 2017
- *      Author: wfg
- */
-
-#ifndef ADIOS2_TRANSPORT_WAN_MDTMMAN_H_
-#define ADIOS2_TRANSPORT_WAN_MDTMMAN_H_
-
-#include <json.hpp>
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Transport.h"
-
-namespace adios
-{
-namespace transport
-{
-
-class MdtmMan : public Transport
-{
-
-public:
-    /**
-     *
-     * @param localIP
-     * @param remoteIP
-     * @param mode
-     * @param prefix
-     * @param numberOfPipes
-     * @param tolerances
-     * @param priorities
-     * @param mpiComm
-     * @param debugMode
-     */
-    MdtmMan(const std::string localIP, const std::string remoteIP,
-            const std::string mode, const std::string prefix,
-            const int numberOfPipes, const std::vector<int> tolerances,
-            const std::vector<int> priorities, MPI_Comm mpiComm,
-            const bool debugMode);
-
-    virtual ~MdtmMan() = default;
-
-    void Open(const std::string name, const std::string accessMode);
-
-    void SetBuffer(char *buffer, std::size_t size);
-
-    /**
-     * We can always overload this function in the base class and accept other
-     * types of data pointers, e.g. Write( json* );
-     * I'm sticking with char* as it's more general (only C++ libraries, e.g.
-     * boost understand std::std::vector, MPI, POSIX, Infiniband use pointer*)
-     * @param buffer
-     * @param size
-     */
-    void Write(const char *buffer, std::size_t size);
-
-    void Flush(); ///< not sure if this one is needed...
-
-    void Close();
-
-private:
-    std::string m_LocalIP;    ///< local ip address, can change over time
-    std::string m_RemoteIP;   ///<  remote ip address, can change over time
-    std::string m_Mode;       ///< send/write, receive/read
-    std::string m_Prefix;     ///< prefix given to message
-    int m_NumberOfPipes = -1; ///< should it be unsigned int?
-    std::vector<int> m_Tolerances;
-    std::vector<int> m_Priorities;
-
-    /**
-     * Should we change data to char* ?
-     * @param data
-     * @param doid
-     * @param variable
-     * @param dType
-     * @param putShape
-     * @param varShape
-     * @param offset
-     * @param timestep
-     * @param tolerance
-     * @param priority
-     * @return
-     */
-    int Put(const void *data, const std::string doid,
-            const std::string variable, const std::string dType,
-            const std::vector<std::uint64_t> &putShape,
-            const std::vector<uint64_t> &varShape,
-            const std::vector<uint64_t> &offset, const std::uint64_t timestep,
-            const int tolerance, const int priority);
-
-    /**
-     *
-     * @param data
-     * @param doid
-     * @param variable
-     * @param dType
-     * @param putShape
-     * @param varShape
-     * @param offset
-     * @param timestep
-     * @param tolerance
-     * @param priority
-     * @return
-     */
-    int Get(void *data, const std::string doid, const std::string variable,
-            const std::string dType, const std::vector<std::uint64_t> &putShape,
-            const std::vector<uint64_t> &varShape,
-            const std::vector<uint64_t> &offset, const std::uint64_t timestep,
-            const int tolerance, const int priority);
-
-    /**
-     *
-     * @param data
-     * @param doid
-     * @param variable
-     * @param dType
-     * @param varShape
-     * @param timestep
-     * @return
-     */
-    int Get(void *data, const std::string doid, const std::string variable,
-            const std::string dType, std::vector<std::uint64_t> &varShape,
-            const std::uint64_t timestep);
-
-    /**
-     *
-     * @param jData
-     */
-    void OnReceive(nlohmann::json &jData);
-};
-
-} // end namespace transport
-} // end namespace
-
-#endif /* ADIOS2_TRANSPORT_WAN_MDTMMAN_H_ */
diff --git a/source/adios2/utilities/format/bp1/BP1.h b/source/adios2/utilities/format/bp1/BP1.h
deleted file mode 100644
index bc9ffb84acc7d8e098b7b9f6a65d5a3ed1fd59bd..0000000000000000000000000000000000000000
--- a/source/adios2/utilities/format/bp1/BP1.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * BP1.h
- *
- *  Created on: Apr 4, 2017
- *      Author: wfg
- */
-
-#ifndef ADIOS2_UTILITIES_FORMAT_BP1_BP1_H_
-#define ADIOS2_UTILITIES_FORMAT_BP1_BP1_H_
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/utilities/format/bp1/BP1Aggregator.h"
-#include "adios2/utilities/format/bp1/BP1Structs.h"
-#include "adios2/utilities/format/bp1/BP1Writer.h"
-
-#endif /* ADIOS2_UTILITIES_FORMAT_BP1_BP1_H_ */
diff --git a/source/adios2/utilities/format/bp1/BP1Base.cpp b/source/adios2/utilities/format/bp1/BP1Base.cpp
deleted file mode 100644
index 43b1d293b6bbe94b2e36644a5ddf615ea420f8f8..0000000000000000000000000000000000000000
--- a/source/adios2/utilities/format/bp1/BP1Base.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * BP1.cpp
- *
- *  Created on: Feb 7, 2017
- *      Author: wfg
- */
-
-#include "BP1Base.h"
-
-#include "adios2/core/adiosFunctions.h" //CreateDirectory
-
-namespace adios
-{
-namespace format
-{
-
-BP1Base::BP1Base(MPI_Comm mpiComm, const bool debugMode)
-: m_BP1Aggregator(mpiComm, debugMode)
-{
-}
-
-std::string BP1Base::GetDirectoryName(const std::string name) const noexcept
-{
-    std::string directory;
-
-    if (name.find(".bp") == name.size() - 3)
-    {
-        directory = name;
-    }
-    else
-    {
-        directory = name + ".bp";
-    }
-    return directory;
-}
-
-// this should go outside
-void BP1Base::OpenRankFiles(const std::string name,
-                            const std::string accessMode, Transport &file) const
-{
-    const std::string directory = GetDirectoryName(name);
-    // creates a directory and sub-directories recursively
-    CreateDirectory(directory);
-
-    // opens a file transport under name.bp/name.bp.rank
-    const std::string fileName(directory + "/" + directory + "." +
-                               std::to_string(file.m_RankMPI));
-    file.Open(fileName, accessMode);
-}
-
-std::vector<uint8_t> BP1Base::GetMethodIDs(
-    const std::vector<std::shared_ptr<Transport>> &transports) const noexcept
-{
-    auto lf_GetMethodID = [](const std::string method) -> uint8_t {
-        int id = METHOD_UNKNOWN;
-        if (method == "NULL")
-            id = METHOD_NULL;
-        else if (method == "POSIX")
-            id = METHOD_POSIX;
-        else if (method == "FStream")
-            id = METHOD_FSTREAM;
-        else if (method == "File")
-            id = METHOD_FILE;
-        else if (method == "MPI")
-            id = METHOD_MPI;
-
-        return id;
-    };
-
-    std::vector<uint8_t> methodIDs;
-    methodIDs.reserve(transports.size());
-
-    for (const auto &transport : transports)
-        methodIDs.push_back(lf_GetMethodID(transport->m_Type));
-
-    return methodIDs;
-}
-
-} // end namespace format
-} // end namespace adios
diff --git a/source/dataman/DataMan.cpp b/source/dataman/DataMan.cpp
index d3ba9a83fc147368a1cf0409a54cb2a9970b37d0..2c9ab9d27ac0b0330a3e9b48476ec963670f6526 100644
--- a/source/dataman/DataMan.cpp
+++ b/source/dataman/DataMan.cpp
@@ -72,11 +72,23 @@ void DataMan::add_stream(json a_jmsg)
         a_jmsg["num_channels"] = num_channels;
     }
 
+    int local_port = 12306, remote_port = 12307;
+
+    if (a_jmsg["local_port"].is_number())
+    {
+        local_port = a_jmsg["local_port"].get<int>();
+    }
+
+    if (a_jmsg["remote_port"].is_number())
+    {
+        local_port = a_jmsg["remote_port"].get<int>();
+    }
+
     for (int i = 0; i < num_channels; i++)
     {
         a_jmsg["channel_id"] = i;
-        a_jmsg["local_port"] = a_jmsg["local_port"].get<int>() + 2;
-        a_jmsg["remote_port"] = a_jmsg["remote_port"].get<int>() + 2;
+        a_jmsg["local_port"] = local_port + 2;
+        a_jmsg["remote_port"] = remote_port + 2;
         auto man = get_man(method);
         if (man)
         {
diff --git a/source/dataman/MdtmMan.cpp b/source/dataman/MdtmMan.cpp
index 2f41d40c669d4f07439a31f437d4a112e4132517..6bfa3af8c5d860f8db16cfe8f9b380aca392bc42 100644
--- a/source/dataman/MdtmMan.cpp
+++ b/source/dataman/MdtmMan.cpp
@@ -19,6 +19,7 @@
 int MdtmMan::init(json a_jmsg)
 {
 
+    std::cout << " 1 MdtmMan::init " << m_channel_id << std::endl;
     StreamMan::init(a_jmsg);
 
     if (a_jmsg["pipe_prefix"].is_string())
@@ -68,16 +69,22 @@ int MdtmMan::init(json a_jmsg)
 
     // Make pipes
     mkdir(m_pipepath.c_str(), 0755);
+
+    std::cout << "making " << m_full_pipename << std::endl;
     mkfifo(m_full_pipename.c_str(), 0666);
+    std::cout << "made " << m_full_pipename << std::endl;
 
     if (m_stream_mode == "sender")
     {
+        std::cout << "opening " << m_full_pipename << std::endl;
         m_pipe_handler = open(m_full_pipename.c_str(), O_WRONLY);
+        std::cout << "opened " << m_full_pipename << std::endl;
     }
     if (m_stream_mode == "receiver")
     {
         m_pipe_handler = open(m_full_pipename.c_str(), O_RDONLY | O_NONBLOCK);
     }
+
     return 0;
 }
 
diff --git a/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp b/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp
index fc27d532375e52f95eee61b4960327fa5a0e8dfc..ae7e964f16636dc51ad6321d2d23e8fac8db30ae 100644
--- a/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp
+++ b/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp
@@ -37,47 +37,53 @@ TEST_F(ADIOS1WriteReadTest, ADIOS2ADIOS1WriteADIOS1Read1D8)
     {
         adios_init_noxml(MPI_COMM_WORLD);
 
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{8});
-            auto &var_i16 = adios.DefineVariable<short>("i16", adios::Dims{8});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{8});
-            auto &var_i64 = adios.DefineVariable<long>("i64", adios::Dims{8});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{8});
+            auto &var_i16 =
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{8});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{8});
+            auto &var_i64 =
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{8});
             auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{8});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{8});
+                io.DefineVariable<unsigned char>("u8", {}, {}, adios::Dims{8});
+            auto &var_u16 = io.DefineVariable<unsigned short>("u16", {}, {},
+                                                              adios::Dims{8});
             auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{8});
+                io.DefineVariable<unsigned int>("u32", {}, {}, adios::Dims{8});
             auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{8});
-            auto &var_r32 = adios.DefineVariable<float>("r32", adios::Dims{8});
-            auto &var_r64 = adios.DefineVariable<double>("r64", adios::Dims{8});
+                io.DefineVariable<unsigned long>("u64", {}, {}, adios::Dims{8});
+            auto &var_r32 =
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{8});
+            auto &var_r64 =
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{8});
         }
 
         // Create the ADIOS 1 Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("ADIOS1Writer");
-        method.AddTransport("File");
+        io.SetEngine("ADIOS1Writer");
+        io.AddTransport("File");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
@@ -260,51 +266,53 @@ TEST_F(ADIOS1WriteReadTest, ADIOS2ADIOS1WriteADIOS1Read2D2x4)
     {
         adios_init_noxml(MPI_COMM_WORLD);
 
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{2, 4});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{2, 4});
             auto &var_i16 =
-                adios.DefineVariable<short>("i16", adios::Dims{2, 4});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{2, 4});
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{2, 4});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{2, 4});
             auto &var_i64 =
-                adios.DefineVariable<long>("i64", adios::Dims{2, 4});
-            auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{2, 4});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{2, 4});
-            auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{2, 4});
-            auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{2, 4});
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{2, 4});
+            auto &var_u8 = io.DefineVariable<unsigned char>("u8", {}, {},
+                                                            adios::Dims{2, 4});
+            auto &var_u16 = io.DefineVariable<unsigned short>(
+                "u16", {}, {}, adios::Dims{2, 4});
+            auto &var_u32 = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                            adios::Dims{2, 4});
+            auto &var_u64 = io.DefineVariable<unsigned long>("u64", {}, {},
+                                                             adios::Dims{2, 4});
             auto &var_r32 =
-                adios.DefineVariable<float>("r32", adios::Dims{2, 4});
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{2, 4});
             auto &var_r64 =
-                adios.DefineVariable<double>("r64", adios::Dims{2, 4});
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{2, 4});
         }
 
         // Create the ADIOS 1 Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("ADIOS1Writer");
-        method.AddTransport("File");
+        io.SetEngine("ADIOS1Writer");
+        io.AddTransport("file");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
@@ -497,51 +505,53 @@ TEST_F(ADIOS1WriteReadTest, ADIOS2ADIOS1WriteADIOS1Read2D4x2)
     {
         adios_init_noxml(MPI_COMM_WORLD);
 
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{4, 2});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{4, 2});
             auto &var_i16 =
-                adios.DefineVariable<short>("i16", adios::Dims{4, 2});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{4, 2});
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{4, 2});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{4, 2});
             auto &var_i64 =
-                adios.DefineVariable<long>("i64", adios::Dims{4, 2});
-            auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{4, 2});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{4, 2});
-            auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{4, 2});
-            auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{4, 2});
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{4, 2});
+            auto &var_u8 = io.DefineVariable<unsigned char>("u8", {}, {},
+                                                            adios::Dims{4, 2});
+            auto &var_u16 = io.DefineVariable<unsigned short>(
+                "u16", {}, {}, adios::Dims{4, 2});
+            auto &var_u32 = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                            adios::Dims{4, 2});
+            auto &var_u64 = io.DefineVariable<unsigned long>("u64", {}, {},
+                                                             adios::Dims{4, 2});
             auto &var_r32 =
-                adios.DefineVariable<float>("r32", adios::Dims{4, 2});
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{4, 2});
             auto &var_r64 =
-                adios.DefineVariable<double>("r64", adios::Dims{4, 2});
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{4, 2});
         }
 
         // Create the ADIOS 1 Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("ADIOS1Writer");
-        method.AddTransport("File");
+        io.SetEngine("ADIOS1Writer");
+        io.AddTransport("file");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
diff --git a/testing/adios2/engine/bp/TestBPWriteRead.cpp b/testing/adios2/engine/bp/TestBPWriteRead.cpp
index 2ca330c48172be05cb69aa2a174fcca5b56aaa52..ab6f328ced033d1c79a672356743de735cb704cf 100644
--- a/testing/adios2/engine/bp/TestBPWriteRead.cpp
+++ b/testing/adios2/engine/bp/TestBPWriteRead.cpp
@@ -34,47 +34,53 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read1D8)
 
     // Write test data using ADIOS2
     {
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{8});
-            auto &var_i16 = adios.DefineVariable<short>("i16", adios::Dims{8});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{8});
-            auto &var_i64 = adios.DefineVariable<long>("i64", adios::Dims{8});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{8});
+            auto &var_i16 =
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{8});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{8});
+            auto &var_i64 =
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{8});
             auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{8});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{8});
+                io.DefineVariable<unsigned char>("u8", {}, {}, adios::Dims{8});
+            auto &var_u16 = io.DefineVariable<unsigned short>("u16", {}, {},
+                                                              adios::Dims{8});
             auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{8});
+                io.DefineVariable<unsigned int>("u32", {}, {}, adios::Dims{8});
             auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{8});
-            auto &var_r32 = adios.DefineVariable<float>("r32", adios::Dims{8});
-            auto &var_r64 = adios.DefineVariable<double>("r64", adios::Dims{8});
+                io.DefineVariable<unsigned long>("u64", {}, {}, adios::Dims{8});
+            auto &var_r32 =
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{8});
+            auto &var_r64 =
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{8});
         }
 
         // Create the BP Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("BPFileWriter");
-        method.AddTransport("File");
+        io.SetEngine("BPFileWriter");
+        io.AddTransport("File");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
@@ -244,51 +250,53 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D2x4)
 
     // Write test data using ADIOS2
     {
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{2, 4});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{2, 4});
             auto &var_i16 =
-                adios.DefineVariable<short>("i16", adios::Dims{2, 4});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{2, 4});
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{2, 4});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{2, 4});
             auto &var_i64 =
-                adios.DefineVariable<long>("i64", adios::Dims{2, 4});
-            auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{2, 4});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{2, 4});
-            auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{2, 4});
-            auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{2, 4});
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{2, 4});
+            auto &var_u8 = io.DefineVariable<unsigned char>("u8", {}, {},
+                                                            adios::Dims{2, 4});
+            auto &var_u16 = io.DefineVariable<unsigned short>(
+                "u16", {}, {}, adios::Dims{2, 4});
+            auto &var_u32 = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                            adios::Dims{2, 4});
+            auto &var_u64 = io.DefineVariable<unsigned long>("u64", {}, {},
+                                                             adios::Dims{2, 4});
             auto &var_r32 =
-                adios.DefineVariable<float>("r32", adios::Dims{2, 4});
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{2, 4});
             auto &var_r64 =
-                adios.DefineVariable<double>("r64", adios::Dims{2, 4});
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{2, 4});
         }
 
         // Create the BP Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("BPFileWriter");
-        method.AddTransport("File");
+        io.SetEngine("BPFileWriter");
+        io.AddTransport("file");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
@@ -468,51 +476,53 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D4x2)
 
     // Write test data using ADIOS2
     {
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{4, 2});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{4, 2});
             auto &var_i16 =
-                adios.DefineVariable<short>("i16", adios::Dims{4, 2});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{4, 2});
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{4, 2});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{4, 2});
             auto &var_i64 =
-                adios.DefineVariable<long>("i64", adios::Dims{4, 2});
-            auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{4, 2});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{4, 2});
-            auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{4, 2});
-            auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{4, 2});
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{4, 2});
+            auto &var_u8 = io.DefineVariable<unsigned char>("u8", {}, {},
+                                                            adios::Dims{4, 2});
+            auto &var_u16 = io.DefineVariable<unsigned short>(
+                "u16", {}, {}, adios::Dims{4, 2});
+            auto &var_u32 = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                            adios::Dims{4, 2});
+            auto &var_u64 = io.DefineVariable<unsigned long>("u64", {}, {},
+                                                             adios::Dims{4, 2});
             auto &var_r32 =
-                adios.DefineVariable<float>("r32", adios::Dims{4, 2});
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{4, 2});
             auto &var_r64 =
-                adios.DefineVariable<double>("r64", adios::Dims{4, 2});
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{4, 2});
         }
 
         // Create the BP Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("BPFileWriter");
-        method.AddTransport("File");
+        io.SetEngine("BPFileWriter");
+        io.AddTransport("file");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
diff --git a/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp b/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp
index 3f2b6a69f8ab11257cb14674feb1a174bf23d8ef..8789a0829a109935b18da3cd8227d4034aa7afae 100644
--- a/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp
+++ b/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp
@@ -191,46 +191,51 @@ TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read1D8)
 
     // Write test data using ADIOS2
     {
-        adios::ADIOS adios(adios::Verbose::WARN, true); // moved up
+        adios::ADIOS adios(true); // moved up
+        adios::IO &io = adios.DeclareIO("TestIO");
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{8});
-            auto &var_i16 = adios.DefineVariable<short>("i16", adios::Dims{8});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{8});
-            auto &var_i64 = adios.DefineVariable<long>("i64", adios::Dims{8});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{8});
+            auto &var_i16 =
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{8});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{8});
+            auto &var_i64 =
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{8});
             auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{8});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{8});
+                io.DefineVariable<unsigned char>("u8", {}, {}, adios::Dims{8});
+            auto &var_u16 = io.DefineVariable<unsigned short>("u16", {}, {},
+                                                              adios::Dims{8});
             auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{8});
+                io.DefineVariable<unsigned int>("u32", {}, {}, adios::Dims{8});
             auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{8});
-            auto &var_r32 = adios.DefineVariable<float>("r32", adios::Dims{8});
-            auto &var_r64 = adios.DefineVariable<double>("r64", adios::Dims{8});
+                io.DefineVariable<unsigned long>("u64", {}, {}, adios::Dims{8});
+            auto &var_r32 =
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{8});
+            auto &var_r64 =
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{8});
         }
 
         // Create the HDF5 Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("HDF5Writer");
-        method.AddTransport("File");
+        io.SetEngine("HDF5Writer");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
@@ -391,51 +396,53 @@ TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read2D2x4)
 
     // Write test data using ADIOS2
     {
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{2, 4});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{2, 4});
             auto &var_i16 =
-                adios.DefineVariable<short>("i16", adios::Dims{2, 4});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{2, 4});
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{2, 4});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{2, 4});
             auto &var_i64 =
-                adios.DefineVariable<long>("i64", adios::Dims{2, 4});
-            auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{2, 4});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{2, 4});
-            auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{2, 4});
-            auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{2, 4});
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{2, 4});
+            auto &var_u8 = io.DefineVariable<unsigned char>("u8", {}, {},
+                                                            adios::Dims{2, 4});
+            auto &var_u16 = io.DefineVariable<unsigned short>(
+                "u16", {}, {}, adios::Dims{2, 4});
+            auto &var_u32 = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                            adios::Dims{2, 4});
+            auto &var_u64 = io.DefineVariable<unsigned long>("u64", {}, {},
+                                                             adios::Dims{2, 4});
             auto &var_r32 =
-                adios.DefineVariable<float>("r32", adios::Dims{2, 4});
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{2, 4});
             auto &var_r64 =
-                adios.DefineVariable<double>("r64", adios::Dims{2, 4});
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{2, 4});
         }
 
-        // Create the HDF5 Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("HDF5Writer");
-        method.AddTransport("File");
+        io.SetEngine("HDF5Writer");
+        io.AddTransport("file");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        // Create the HDF5 Engine
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
@@ -604,51 +611,53 @@ TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read2D4x2)
 
     // Write test data using ADIOS2
     {
-        adios::ADIOS adios(adios::Verbose::WARN, true);
+        adios::ADIOS adios(true);
+        adios::IO &io = adios.DeclareIO("TestIO");
 
         // Declare 1D variables
         {
-            auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{4, 2});
+            auto &var_i8 =
+                io.DefineVariable<char>("i8", {}, {}, adios::Dims{4, 2});
             auto &var_i16 =
-                adios.DefineVariable<short>("i16", adios::Dims{4, 2});
-            auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{4, 2});
+                io.DefineVariable<short>("i16", {}, {}, adios::Dims{4, 2});
+            auto &var_i32 =
+                io.DefineVariable<int>("i32", {}, {}, adios::Dims{4, 2});
             auto &var_i64 =
-                adios.DefineVariable<long>("i64", adios::Dims{4, 2});
-            auto &var_u8 =
-                adios.DefineVariable<unsigned char>("u8", adios::Dims{4, 2});
-            auto &var_u16 =
-                adios.DefineVariable<unsigned short>("u16", adios::Dims{4, 2});
-            auto &var_u32 =
-                adios.DefineVariable<unsigned int>("u32", adios::Dims{4, 2});
-            auto &var_u64 =
-                adios.DefineVariable<unsigned long>("u64", adios::Dims{4, 2});
+                io.DefineVariable<long>("i64", {}, {}, adios::Dims{4, 2});
+            auto &var_u8 = io.DefineVariable<unsigned char>("u8", {}, {},
+                                                            adios::Dims{4, 2});
+            auto &var_u16 = io.DefineVariable<unsigned short>(
+                "u16", {}, {}, adios::Dims{4, 2});
+            auto &var_u32 = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                            adios::Dims{4, 2});
+            auto &var_u64 = io.DefineVariable<unsigned long>("u64", {}, {},
+                                                             adios::Dims{4, 2});
             auto &var_r32 =
-                adios.DefineVariable<float>("r32", adios::Dims{4, 2});
+                io.DefineVariable<float>("r32", {}, {}, adios::Dims{4, 2});
             auto &var_r64 =
-                adios.DefineVariable<double>("r64", adios::Dims{4, 2});
+                io.DefineVariable<double>("r64", {}, {}, adios::Dims{4, 2});
         }
 
         // Create the HDF5 Engine
-        auto method = adios.DeclareMethod("TestMethod");
-        method.SetEngine("HDF5Writer");
-        method.AddTransport("File");
+        io.SetEngine("HDF5Writer");
+        io.AddTransport("file");
 
-        auto engine = adios.Open(fname, "w", method);
-        ASSERT_NE(engine, nullptr);
+        auto engine = io.Open(fname, adios::OpenMode::Write);
+        ASSERT_NE(engine.get(), nullptr);
 
         for (size_t step = 0; step < 3; ++step)
         {
             // Retrieve the variables that previously went out of scope
-            auto &var_i8 = adios.GetVariable<char>("i8");
-            auto &var_i16 = adios.GetVariable<short>("i16");
-            auto &var_i32 = adios.GetVariable<int>("i32");
-            auto &var_i64 = adios.GetVariable<long>("i64");
-            auto &var_u8 = adios.GetVariable<unsigned char>("u8");
-            auto &var_u16 = adios.GetVariable<unsigned short>("u16");
-            auto &var_u32 = adios.GetVariable<unsigned int>("u32");
-            auto &var_u64 = adios.GetVariable<unsigned long>("u64");
-            auto &var_r32 = adios.GetVariable<float>("r32");
-            auto &var_r64 = adios.GetVariable<double>("r64");
+            auto &var_i8 = io.GetVariable<char>("i8");
+            auto &var_i16 = io.GetVariable<short>("i16");
+            auto &var_i32 = io.GetVariable<int>("i32");
+            auto &var_i64 = io.GetVariable<long>("i64");
+            auto &var_u8 = io.GetVariable<unsigned char>("u8");
+            auto &var_u16 = io.GetVariable<unsigned short>("u16");
+            auto &var_u32 = io.GetVariable<unsigned int>("u32");
+            auto &var_u64 = io.GetVariable<unsigned long>("u64");
+            auto &var_r32 = io.GetVariable<float>("r32");
+            auto &var_r64 = io.GetVariable<double>("r64");
 
             // Write each one
             engine->Write(var_i8, m_TestData.I8.data() + step);
diff --git a/testing/adios2/interface/TestADIOSInterfaceWrite.cpp b/testing/adios2/interface/TestADIOSInterfaceWrite.cpp
index ece198e126594b365855ce3ba118f8fcc9bbe5fb..c315a166db76cc0633b3d92003b60d700ac546d5 100644
--- a/testing/adios2/interface/TestADIOSInterfaceWrite.cpp
+++ b/testing/adios2/interface/TestADIOSInterfaceWrite.cpp
@@ -10,7 +10,7 @@
 class ADIOSInterfaceWriteTest : public ::testing::Test
 {
 public:
-    ADIOSInterfaceWriteTest() : adios(adios::Verbose::WARN, true) {}
+    ADIOSInterfaceWriteTest() : adios(true), io(adios.DeclareIO("TestIO")) {}
 
 protected:
     // virtual void SetUp() { }
@@ -18,25 +18,27 @@ protected:
     // virtual void TearDown() { }
 
     adios::ADIOS adios;
+    adios::IO &io;
 };
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarChar1x10)
 {
     // Define ADIOS variables for each type
-    auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{10});
+    auto &var_i8 = io.DefineVariable<char>("i8", {}, {}, adios::Dims{10});
 
     // Verify the return type is as expected
     ::testing::StaticAssertTypeEq<decltype(var_i8), adios::Variable<char> &>();
 
     // Verify exceptions are thrown upon duplicate variable names
-    EXPECT_THROW(auto &foo = adios.DefineVariable<char>("i8", adios::Dims{10}),
+    EXPECT_THROW(auto &foo =
+                     io.DefineVariable<char>("i8", {}, {}, adios::Dims{10}),
                  std::invalid_argument);
 
     // Verify the dimensions, name, and type are correct
-    ASSERT_EQ(var_i8.m_Shape.size(), 1);
-    EXPECT_EQ(var_i8.m_Shape[0], 10);
-    EXPECT_EQ(var_i8.m_Count.size(), 0);
+    ASSERT_EQ(var_i8.m_Shape.size(), 0);
     EXPECT_EQ(var_i8.m_Start.size(), 0);
+    EXPECT_EQ(var_i8.m_Count.size(), 1);
+    EXPECT_EQ(var_i8.m_Count[0], 10);
     EXPECT_EQ(var_i8.m_Name, "i8");
     EXPECT_EQ(var_i8.m_Type, "char");
 }
@@ -44,60 +46,63 @@ TEST_F(ADIOSInterfaceWriteTest, DefineVarChar1x10)
 // Rinse  and repeat for remaining types
 TEST_F(ADIOSInterfaceWriteTest, DefineVarShort1x10)
 {
-    auto &var_i16 = adios.DefineVariable<short>("i16", adios::Dims{10});
+    auto &var_i16 = io.DefineVariable<short>("i16", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_i16),
                                   adios::Variable<short> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<short>("i16", adios::Dims{10}),
+                     io.DefineVariable<short>("i16", {}, {}, adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_i16.m_Shape.size(), 1);
-    EXPECT_EQ(var_i16.m_Shape[0], 10);
-    EXPECT_EQ(var_i16.m_Count.size(), 0);
+    ASSERT_EQ(var_i16.m_Shape.size(), 0);
     EXPECT_EQ(var_i16.m_Start.size(), 0);
+    EXPECT_EQ(var_i16.m_Count.size(), 1);
+    EXPECT_EQ(var_i16.m_Count[0], 10);
     EXPECT_EQ(var_i16.m_Name, "i16");
     EXPECT_EQ(var_i16.m_Type, "short");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarInt1x10)
 {
-    auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{10});
+    auto &var_i32 = io.DefineVariable<int>("i32", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_i32), adios::Variable<int> &>();
-    EXPECT_THROW(auto &foo = adios.DefineVariable<int>("i32", adios::Dims{10}),
+    EXPECT_THROW(auto &foo =
+                     io.DefineVariable<int>("i32", {}, {}, adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_i32.m_Shape.size(), 1);
-    EXPECT_EQ(var_i32.m_Shape[0], 10);
-    EXPECT_EQ(var_i32.m_Count.size(), 0);
+    ASSERT_EQ(var_i32.m_Shape.size(), 0);
     EXPECT_EQ(var_i32.m_Start.size(), 0);
+    EXPECT_EQ(var_i32.m_Count.size(), 1);
+    EXPECT_EQ(var_i32.m_Count[0], 10);
     EXPECT_EQ(var_i32.m_Name, "i32");
     EXPECT_EQ(var_i32.m_Type, "int");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarLong1x10)
 {
-    auto &var_i64 = adios.DefineVariable<long>("i64", adios::Dims{10});
-    ::testing::StaticAssertTypeEq<decltype(var_i64), adios::Variable<long> &>();
-    EXPECT_THROW(auto &foo = adios.DefineVariable<long>("i64", adios::Dims{10}),
+    auto &var_u16 = io.DefineVariable<long>("u16", {}, {}, adios::Dims{10});
+    ::testing::StaticAssertTypeEq<decltype(var_u16), adios::Variable<long> &>();
+    EXPECT_THROW(auto &foo =
+                     io.DefineVariable<long>("u16", {}, {}, adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_i64.m_Shape.size(), 1);
-    EXPECT_EQ(var_i64.m_Shape[0], 10);
-    EXPECT_EQ(var_i64.m_Count.size(), 0);
-    EXPECT_EQ(var_i64.m_Start.size(), 0);
-    EXPECT_EQ(var_i64.m_Name, "i64");
-    EXPECT_EQ(var_i64.m_Type, "long int");
+    ASSERT_EQ(var_u16.m_Shape.size(), 0);
+    EXPECT_EQ(var_u16.m_Start.size(), 0);
+    EXPECT_EQ(var_u16.m_Count.size(), 1);
+    EXPECT_EQ(var_u16.m_Count[0], 10);
+    EXPECT_EQ(var_u16.m_Name, "u16");
+    EXPECT_EQ(var_u16.m_Type, "long int");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarUChar1x10)
 {
-    auto &var_u8 = adios.DefineVariable<unsigned char>("u8", adios::Dims{10});
+    auto &var_u8 =
+        io.DefineVariable<unsigned char>("u8", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_u8),
                                   adios::Variable<unsigned char> &>();
-    EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<unsigned char>("u8", adios::Dims{10}),
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned char>("u8", {}, {},
+                                                              adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_u8.m_Shape.size(), 1);
-    EXPECT_EQ(var_u8.m_Shape[0], 10);
-    EXPECT_EQ(var_u8.m_Count.size(), 0);
+    ASSERT_EQ(var_u8.m_Shape.size(), 0);
     EXPECT_EQ(var_u8.m_Start.size(), 0);
+    EXPECT_EQ(var_u8.m_Count.size(), 1);
+    EXPECT_EQ(var_u8.m_Count[0], 10);
     EXPECT_EQ(var_u8.m_Name, "u8");
     EXPECT_EQ(var_u8.m_Type, "unsigned char");
 }
@@ -105,162 +110,165 @@ TEST_F(ADIOSInterfaceWriteTest, DefineVarUChar1x10)
 TEST_F(ADIOSInterfaceWriteTest, DefineVarUShort1x10)
 {
     auto &var_u16 =
-        adios.DefineVariable<unsigned short>("u16", adios::Dims{10});
+        io.DefineVariable<unsigned short>("u16", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_u16),
                                   adios::Variable<unsigned short> &>();
-    EXPECT_THROW(auto &foo = adios.DefineVariable<unsigned short>(
-                     "u16", adios::Dims{10}),
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned short>("u16", {}, {},
+                                                               adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_u16.m_Shape.size(), 1);
-    EXPECT_EQ(var_u16.m_Shape[0], 10);
-    EXPECT_EQ(var_u16.m_Count.size(), 0);
+    ASSERT_EQ(var_u16.m_Shape.size(), 0);
     EXPECT_EQ(var_u16.m_Start.size(), 0);
+    EXPECT_EQ(var_u16.m_Count.size(), 1);
+    EXPECT_EQ(var_u16.m_Count[0], 10);
     EXPECT_EQ(var_u16.m_Name, "u16");
     EXPECT_EQ(var_u16.m_Type, "unsigned short");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarUInt1x10)
 {
-    auto &var_u32 = adios.DefineVariable<unsigned int>("u32", adios::Dims{10});
+    auto &var_u32 =
+        io.DefineVariable<unsigned int>("u32", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_u32),
                                   adios::Variable<unsigned int> &>();
-    EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<unsigned int>("u32", adios::Dims{10}),
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                             adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_u32.m_Shape.size(), 1);
-    EXPECT_EQ(var_u32.m_Shape[0], 10);
-    EXPECT_EQ(var_u32.m_Count.size(), 0);
+    ASSERT_EQ(var_u32.m_Shape.size(), 0);
     EXPECT_EQ(var_u32.m_Start.size(), 0);
+    EXPECT_EQ(var_u32.m_Count.size(), 1);
+    EXPECT_EQ(var_u32.m_Count[0], 10);
     EXPECT_EQ(var_u32.m_Name, "u32");
     EXPECT_EQ(var_u32.m_Type, "unsigned int");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarULong1x10)
 {
-    auto &var_u64 = adios.DefineVariable<unsigned long>("u64", adios::Dims{10});
+    auto &var_u64 =
+        io.DefineVariable<unsigned long>("u64", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_u64),
                                   adios::Variable<unsigned long> &>();
-    EXPECT_THROW(
-        auto &foo = adios.DefineVariable<unsigned long>("u64", adios::Dims{10}),
-        std::invalid_argument);
-    ASSERT_EQ(var_u64.m_Shape.size(), 1);
-    EXPECT_EQ(var_u64.m_Shape[0], 10);
-    EXPECT_EQ(var_u64.m_Count.size(), 0);
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned long>("u64", {}, {},
+                                                              adios::Dims{10}),
+                 std::invalid_argument);
+    ASSERT_EQ(var_u64.m_Shape.size(), 0);
     EXPECT_EQ(var_u64.m_Start.size(), 0);
+    EXPECT_EQ(var_u64.m_Count.size(), 1);
+    EXPECT_EQ(var_u64.m_Count[0], 10);
     EXPECT_EQ(var_u64.m_Name, "u64");
     EXPECT_EQ(var_u64.m_Type, "unsigned long int");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarFloat1x10)
 {
-    auto &var_r32 = adios.DefineVariable<float>("r32", adios::Dims{10});
+    auto &var_r32 = io.DefineVariable<float>("r32", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_r32),
                                   adios::Variable<float> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<float>("r32", adios::Dims{10}),
+                     io.DefineVariable<float>("r32", {}, {}, adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_r32.m_Shape.size(), 1);
-    EXPECT_EQ(var_r32.m_Shape[0], 10);
-    EXPECT_EQ(var_r32.m_Count.size(), 0);
+    ASSERT_EQ(var_r32.m_Shape.size(), 0);
     EXPECT_EQ(var_r32.m_Start.size(), 0);
+    EXPECT_EQ(var_r32.m_Count.size(), 1);
+    EXPECT_EQ(var_r32.m_Count[0], 10);
     EXPECT_EQ(var_r32.m_Name, "r32");
     EXPECT_EQ(var_r32.m_Type, "float");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarDouble1x10)
 {
-    auto &var_r64 = adios.DefineVariable<double>("r64", adios::Dims{10});
+    auto &var_r64 = io.DefineVariable<double>("r64", {}, {}, adios::Dims{10});
     ::testing::StaticAssertTypeEq<decltype(var_r64),
                                   adios::Variable<double> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<double>("r64", adios::Dims{10}),
+                     io.DefineVariable<double>("r64", {}, {}, adios::Dims{10}),
                  std::invalid_argument);
-    ASSERT_EQ(var_r64.m_Shape.size(), 1);
-    EXPECT_EQ(var_r64.m_Shape[0], 10);
-    EXPECT_EQ(var_r64.m_Count.size(), 0);
+    ASSERT_EQ(var_r64.m_Shape.size(), 0);
     EXPECT_EQ(var_r64.m_Start.size(), 0);
+    EXPECT_EQ(var_r64.m_Count.size(), 1);
+    EXPECT_EQ(var_r64.m_Count[0], 10);
     EXPECT_EQ(var_r64.m_Name, "r64");
     EXPECT_EQ(var_r64.m_Type, "double");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarChar2x5)
 {
-    auto &var_i8 = adios.DefineVariable<char>("i8", adios::Dims{2, 5});
+    auto &var_i8 = io.DefineVariable<char>("i8", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_i8), adios::Variable<char> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<char>("i8", adios::Dims{2, 5}),
+                     io.DefineVariable<char>("i8", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_i8.m_Shape.size(), 2);
-    EXPECT_EQ(var_i8.m_Shape[0], 2);
-    EXPECT_EQ(var_i8.m_Shape[1], 5);
-    EXPECT_EQ(var_i8.m_Count.size(), 0);
+    ASSERT_EQ(var_i8.m_Shape.size(), 0);
     EXPECT_EQ(var_i8.m_Start.size(), 0);
+    EXPECT_EQ(var_i8.m_Count.size(), 2);
+    EXPECT_EQ(var_i8.m_Count[0], 2);
+    EXPECT_EQ(var_i8.m_Count[1], 5);
     EXPECT_EQ(var_i8.m_Name, "i8");
     EXPECT_EQ(var_i8.m_Type, "char");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarShort2x5)
 {
-    auto &var_i16 = adios.DefineVariable<short>("i16", adios::Dims{2, 5});
+    auto &var_i16 = io.DefineVariable<short>("i16", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_i16),
                                   adios::Variable<short> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<short>("i16", adios::Dims{2, 5}),
+                     io.DefineVariable<short>("i16", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_i16.m_Shape.size(), 2);
-    EXPECT_EQ(var_i16.m_Shape[0], 2);
-    EXPECT_EQ(var_i16.m_Shape[1], 5);
-    EXPECT_EQ(var_i16.m_Count.size(), 0);
+    ASSERT_EQ(var_i16.m_Shape.size(), 0);
     EXPECT_EQ(var_i16.m_Start.size(), 0);
+    EXPECT_EQ(var_i16.m_Count.size(), 2);
+    EXPECT_EQ(var_i16.m_Count[0], 2);
+    EXPECT_EQ(var_i16.m_Count[1], 5);
     EXPECT_EQ(var_i16.m_Name, "i16");
     EXPECT_EQ(var_i16.m_Type, "short");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarInt2x5)
 {
-    auto &var_i32 = adios.DefineVariable<int>("i32", adios::Dims{2, 5});
+    auto &var_i32 = io.DefineVariable<int>("i32", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_i32), adios::Variable<int> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<int>("i32", adios::Dims{2, 5}),
+                     io.DefineVariable<int>("i32", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_i32.m_Shape.size(), 2);
-    EXPECT_EQ(var_i32.m_Shape[0], 2);
-    EXPECT_EQ(var_i32.m_Shape[1], 5);
-    EXPECT_EQ(var_i32.m_Count.size(), 0);
+    ASSERT_EQ(var_i32.m_Shape.size(), 0);
     EXPECT_EQ(var_i32.m_Start.size(), 0);
+    EXPECT_EQ(var_i32.m_Count.size(), 2);
+    EXPECT_EQ(var_i32.m_Count[0], 2);
+    EXPECT_EQ(var_i32.m_Count[1], 5);
     EXPECT_EQ(var_i32.m_Name, "i32");
     EXPECT_EQ(var_i32.m_Type, "int");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarLong2x5)
 {
-    auto &var_i64 = adios.DefineVariable<long>("i64", adios::Dims{2, 5});
-    ::testing::StaticAssertTypeEq<decltype(var_i64), adios::Variable<long> &>();
+    auto &var_u16 = io.DefineVariable<long>("u16", {}, {}, adios::Dims{2, 5});
+    ::testing::StaticAssertTypeEq<decltype(var_u16), adios::Variable<long> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<long>("i64", adios::Dims{2, 5}),
+                     io.DefineVariable<long>("u16", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_i64.m_Shape.size(), 2);
-    EXPECT_EQ(var_i64.m_Shape[0], 2);
-    EXPECT_EQ(var_i64.m_Shape[1], 5);
-    EXPECT_EQ(var_i64.m_Count.size(), 0);
-    EXPECT_EQ(var_i64.m_Start.size(), 0);
-    EXPECT_EQ(var_i64.m_Name, "i64");
-    EXPECT_EQ(var_i64.m_Type, "long int");
+    ASSERT_EQ(var_u16.m_Shape.size(), 0);
+    EXPECT_EQ(var_u16.m_Start.size(), 0);
+    EXPECT_EQ(var_u16.m_Count.size(), 2);
+    EXPECT_EQ(var_u16.m_Count[0], 2);
+    EXPECT_EQ(var_u16.m_Count[1], 5);
+    EXPECT_EQ(var_u16.m_Name, "u16");
+    EXPECT_EQ(var_u16.m_Type, "long int");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarUChar2x5)
 {
-    auto &var_u8 = adios.DefineVariable<unsigned char>("u8", adios::Dims{2, 5});
+    auto &var_u8 =
+        io.DefineVariable<unsigned char>("u8", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_u8),
                                   adios::Variable<unsigned char> &>();
-    EXPECT_THROW(auto &foo = adios.DefineVariable<unsigned char>(
-                     "u8", adios::Dims{2, 5}),
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned char>(
+                     "u8", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_u8.m_Shape.size(), 2);
-    EXPECT_EQ(var_u8.m_Shape[0], 2);
-    EXPECT_EQ(var_u8.m_Shape[1], 5);
-    EXPECT_EQ(var_u8.m_Count.size(), 0);
+    ASSERT_EQ(var_u8.m_Shape.size(), 0);
     EXPECT_EQ(var_u8.m_Start.size(), 0);
+    EXPECT_EQ(var_u8.m_Count.size(), 2);
+    EXPECT_EQ(var_u8.m_Count[0], 2);
+    EXPECT_EQ(var_u8.m_Count[1], 5);
     EXPECT_EQ(var_u8.m_Name, "u8");
     EXPECT_EQ(var_u8.m_Type, "unsigned char");
 }
@@ -268,17 +276,17 @@ TEST_F(ADIOSInterfaceWriteTest, DefineVarUChar2x5)
 TEST_F(ADIOSInterfaceWriteTest, DefineVarUShort2x5)
 {
     auto &var_u16 =
-        adios.DefineVariable<unsigned short>("u16", adios::Dims{2, 5});
+        io.DefineVariable<unsigned short>("u16", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_u16),
                                   adios::Variable<unsigned short> &>();
-    EXPECT_THROW(auto &foo = adios.DefineVariable<unsigned short>(
-                     "u16", adios::Dims{2, 5}),
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned short>(
+                     "u16", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_u16.m_Shape.size(), 2);
-    EXPECT_EQ(var_u16.m_Shape[0], 2);
-    EXPECT_EQ(var_u16.m_Shape[1], 5);
-    EXPECT_EQ(var_u16.m_Count.size(), 0);
+    ASSERT_EQ(var_u16.m_Shape.size(), 0);
     EXPECT_EQ(var_u16.m_Start.size(), 0);
+    EXPECT_EQ(var_u16.m_Count.size(), 2);
+    EXPECT_EQ(var_u16.m_Count[0], 2);
+    EXPECT_EQ(var_u16.m_Count[1], 5);
     EXPECT_EQ(var_u16.m_Name, "u16");
     EXPECT_EQ(var_u16.m_Type, "unsigned short");
 }
@@ -286,17 +294,17 @@ TEST_F(ADIOSInterfaceWriteTest, DefineVarUShort2x5)
 TEST_F(ADIOSInterfaceWriteTest, DefineVarUInt2x5)
 {
     auto &var_u32 =
-        adios.DefineVariable<unsigned int>("u32", adios::Dims{2, 5});
+        io.DefineVariable<unsigned int>("u32", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_u32),
                                   adios::Variable<unsigned int> &>();
-    EXPECT_THROW(auto &foo = adios.DefineVariable<unsigned int>(
-                     "u32", adios::Dims{2, 5}),
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned int>("u32", {}, {},
+                                                             adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_u32.m_Shape.size(), 2);
-    EXPECT_EQ(var_u32.m_Shape[0], 2);
-    EXPECT_EQ(var_u32.m_Shape[1], 5);
-    EXPECT_EQ(var_u32.m_Count.size(), 0);
+    ASSERT_EQ(var_u32.m_Shape.size(), 0);
     EXPECT_EQ(var_u32.m_Start.size(), 0);
+    EXPECT_EQ(var_u32.m_Count.size(), 2);
+    EXPECT_EQ(var_u32.m_Count[0], 2);
+    EXPECT_EQ(var_u32.m_Count[1], 5);
     EXPECT_EQ(var_u32.m_Name, "u32");
     EXPECT_EQ(var_u32.m_Type, "unsigned int");
 }
@@ -304,51 +312,51 @@ TEST_F(ADIOSInterfaceWriteTest, DefineVarUInt2x5)
 TEST_F(ADIOSInterfaceWriteTest, DefineVarULong2x5)
 {
     auto &var_u64 =
-        adios.DefineVariable<unsigned long>("u64", adios::Dims{2, 5});
+        io.DefineVariable<unsigned long>("u64", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_u64),
                                   adios::Variable<unsigned long> &>();
-    EXPECT_THROW(auto &foo = adios.DefineVariable<unsigned long>(
-                     "u64", adios::Dims{2, 5}),
+    EXPECT_THROW(auto &foo = io.DefineVariable<unsigned long>(
+                     "u64", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_u64.m_Shape.size(), 2);
-    EXPECT_EQ(var_u64.m_Shape[0], 2);
-    EXPECT_EQ(var_u64.m_Shape[1], 5);
-    EXPECT_EQ(var_u64.m_Count.size(), 0);
+    ASSERT_EQ(var_u64.m_Shape.size(), 0);
     EXPECT_EQ(var_u64.m_Start.size(), 0);
+    EXPECT_EQ(var_u64.m_Count.size(), 2);
+    EXPECT_EQ(var_u64.m_Count[0], 2);
+    EXPECT_EQ(var_u64.m_Count[1], 5);
     EXPECT_EQ(var_u64.m_Name, "u64");
     EXPECT_EQ(var_u64.m_Type, "unsigned long int");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarFloat2x5)
 {
-    auto &var_r32 = adios.DefineVariable<float>("r32", adios::Dims{2, 5});
+    auto &var_r32 = io.DefineVariable<float>("r32", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_r32),
                                   adios::Variable<float> &>();
     EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<float>("r32", adios::Dims{2, 5}),
+                     io.DefineVariable<float>("r32", {}, {}, adios::Dims{2, 5}),
                  std::invalid_argument);
-    ASSERT_EQ(var_r32.m_Shape.size(), 2);
-    EXPECT_EQ(var_r32.m_Shape[0], 2);
-    EXPECT_EQ(var_r32.m_Shape[1], 5);
-    EXPECT_EQ(var_r32.m_Count.size(), 0);
+    ASSERT_EQ(var_r32.m_Shape.size(), 0);
     EXPECT_EQ(var_r32.m_Start.size(), 0);
+    EXPECT_EQ(var_r32.m_Count.size(), 2);
+    EXPECT_EQ(var_r32.m_Count[0], 2);
+    EXPECT_EQ(var_r32.m_Count[1], 5);
     EXPECT_EQ(var_r32.m_Name, "r32");
     EXPECT_EQ(var_r32.m_Type, "float");
 }
 
 TEST_F(ADIOSInterfaceWriteTest, DefineVarDouble2x5)
 {
-    auto &var_r64 = adios.DefineVariable<double>("r64", adios::Dims{2, 5});
+    auto &var_r64 = io.DefineVariable<double>("r64", {}, {}, adios::Dims{2, 5});
     ::testing::StaticAssertTypeEq<decltype(var_r64),
                                   adios::Variable<double> &>();
-    EXPECT_THROW(auto &foo =
-                     adios.DefineVariable<double>("r64", adios::Dims{2, 5}),
-                 std::invalid_argument);
-    ASSERT_EQ(var_r64.m_Shape.size(), 2);
-    EXPECT_EQ(var_r64.m_Shape[0], 2);
-    EXPECT_EQ(var_r64.m_Shape[1], 5);
-    EXPECT_EQ(var_r64.m_Count.size(), 0);
+    EXPECT_THROW(
+        auto &foo = io.DefineVariable<double>("r64", {}, {}, adios::Dims{2, 5}),
+        std::invalid_argument);
+    ASSERT_EQ(var_r64.m_Shape.size(), 0);
     EXPECT_EQ(var_r64.m_Start.size(), 0);
+    EXPECT_EQ(var_r64.m_Count.size(), 2);
+    EXPECT_EQ(var_r64.m_Count[0], 2);
+    EXPECT_EQ(var_r64.m_Count[1], 5);
     EXPECT_EQ(var_r64.m_Name, "r64");
     EXPECT_EQ(var_r64.m_Type, "double");
 }