diff --git a/CMakeLists.txt b/CMakeLists.txt
index 65c892099bf1f43c6fad87f03bba814321af9ecb..e31f749bf9acf63d09836b41d882dec7323219db 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,31 +55,40 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
 
 include(CMakeDependentOption)
 
-# Setup shared library / -fPIC stuff
+# Setup shared library defaults.  If explicitly specified somehow, then default 
+# to that.  Otherwise base the default on whether or not shared libs are even
+# supported.
 get_property(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
-if(DEFINED BUILD_SHARED_LIBS)
-  set(ADIOS2_BUILD_SHARED_LIBS_DEFAULT ${BUILD_SHARED_LIBS})
-elseif(DEFINED ADIOS2_BUILD_SHARED_LIBS)
+if(DEFINED ADIOS2_BUILD_SHARED_LIBS)
   set(ADIOS2_BUILD_SHARED_LIBS_DEFAULT ${ADIOS2_BUILD_SHARED_LIBS})
+elseif(DEFINED BUILD_SHARED_LIBS)
+  set(ADIOS2_BUILD_SHARED_LIBS_DEFAULT ${BUILD_SHARED_LIBS})
 else()
   set(ADIOS2_BUILD_SHARED_LIBS_DEFAULT ${SHARED_LIBS_SUPPORTED})
 endif()
-unset(BUILD_SHARED_LIBS)
-option(ADIOS2_BUILD_SHARED_LIBS "Build shared libraries (so/dylib/dll)." ${ADIOS2_BUILD_SHARED_LIBS})
+cmake_dependent_option(ADIOS2_BUILD_SHARED_LIBS
+  "Build shared libraries (so/dylib/dll)." ${ADIOS2_BUILD_SHARED_LIBS_DEFAULT}
+  "SHARED_LIBS_SUPPORTED" OFF
+)
 set(BUILD_SHARED_LIBS ${ADIOS2_BUILD_SHARED_LIBS})
-if(NOT SHARED_LIBS_SUPPORTED)
-  if(BUILD_SHARED_LIBS)
-    message(WARNING "A shared library build was requested but is not supported on this platform / compiler.  Unexpected build results will likely occur")
-  endif()
-  set(BUILD_SHARED_LIBS OFF)
+mark_as_advanced(BUILD_SHARED_LIBS)
+
+# Setup PIC defaults.  If explicitly specified somehow, then default 
+# to that.  Otherwise base the default on whether or not shared libs are even
+# supported.
+if(DEFINED ADIOS2_ENABLE_PIC)
+  set(ADIOS2_ENABLE_PIC_DEFAULT ${ADIOS2_ENABLE_PIC})
+elseif(DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
+  set(ADIOS2_ENABLE_PIC_DEFAULT ${CMAKE_POSITION_INDEPENDENT_CODE})
+else()
+  set(ADIOS2_ENABLE_PIC_DEFAULT ${SHARED_LIBS_SUPPORTED})
 endif()
-
 cmake_dependent_option(ADIOS2_ENABLE_PIC
-  "Build with Position Independent Code" ON
-  "SHARED_LIBS_SUPPORTED" OFF)
-if(ADIOS2_ENABLE_PIC)
-  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-endif()
+  "Build with Position Independent Code" ${ADIOS2_ENABLE_PIC_DEFAULT}
+  "SHARED_LIBS_SUPPORTED" OFF
+)
+set(CMAKE_POSITION_INDEPENDENT_CODE ${ADIOS2_ENABLE_PIC})
+mark_as_advanced(CMAKE_POSITION_INDEPENDENT_CODE)
 
 adios_option(BZip2     "Enable support for BZip2 transforms" AUTO)
 adios_option(ZFP       "Enable support for ZFP transforms" AUTO)
@@ -162,10 +171,13 @@ message("")
 message("  Installation prefix: ${CMAKE_INSTALL_PREFIX}")
 message("  Features:")
 if(BUILD_SHARED_LIBS)
-  message("    Library Type: shared")
+  set(msg_lib_type "shared")
+elseif(CMAKE_POSITION_INDEPENDENT_CODE)
+  set(msg_lib_type "static (with PIC)")
 else()
-  message("    Library Type: static")
+  set(msg_lib_type "static (without PIC)")
 endif()
+message("    Library Type: ${msg_lib_type}")
 message("    Build Type:   ${CMAKE_BUILD_TYPE}")
 message("    Testing: ${BUILD_TESTING}")
 message("    Build Options:")
diff --git a/bindings/python/ADIOSPy.cpp b/bindings/python/ADIOSPy.cpp
index 96c8033a80176655e44130dc7dd5c956671b6163..7f196f40a1d4806fd28bcad89c3b1fa7041b7a4f 100644
--- a/bindings/python/ADIOSPy.cpp
+++ b/bindings/python/ADIOSPy.cpp
@@ -19,7 +19,8 @@ namespace adios2
 
 ADIOSPy::ADIOSPy(const std::string configFile, MPI_Comm mpiComm,
                  const bool debugMode)
-: m_DebugMode(debugMode), m_ADIOS(configFile, mpiComm, debugMode)
+: m_DebugMode(debugMode),
+  m_ADIOS(std::make_shared<adios2::ADIOS>(configFile, mpiComm, debugMode))
 {
 }
 
@@ -29,7 +30,7 @@ ADIOSPy::ADIOSPy(MPI_Comm mpiComm, const bool debugMode)
 }
 
 ADIOSPy::ADIOSPy(const std::string configFile, const bool debugMode)
-: ADIOSPy("", MPI_COMM_SELF, debugMode)
+: ADIOSPy(configFile, MPI_COMM_SELF, debugMode)
 {
 }
 
@@ -39,7 +40,7 @@ ADIOSPy::ADIOSPy(const bool debugMode) : ADIOSPy("", MPI_COMM_SELF, debugMode)
 
 IOPy ADIOSPy::DeclareIO(const std::string name)
 {
-    return IOPy(m_ADIOS.DeclareIO(name), m_DebugMode);
+    return IOPy(m_ADIOS->DeclareIO(name), m_DebugMode);
 }
 
 } // end namespace adios
diff --git a/bindings/python/ADIOSPy.h b/bindings/python/ADIOSPy.h
index 64cd3fbbe0c2ef6b1f1e6d6a27ecf7e92f66a7d4..d3c9f5e85ddf7fbad16e24f326a46baba5e50640 100644
--- a/bindings/python/ADIOSPy.h
+++ b/bindings/python/ADIOSPy.h
@@ -12,6 +12,7 @@
 #define ADIOS2_BINDINGS_PYTHON_SOURCE_ADIOSPY_H_
 
 /// \cond EXCLUDE_FROM_DOXYGEN
+#include <memory> //std::shared_ptr
 #include <string>
 /// \endcond
 
@@ -32,13 +33,14 @@ public:
     ADIOSPy(MPI_Comm mpiComm, const bool debugMode);
     ADIOSPy(const std::string configFile, const bool debugMode);
     ADIOSPy(const bool debugMode);
+
     ~ADIOSPy() = default;
 
     IOPy DeclareIO(const std::string name);
 
 private:
     const bool m_DebugMode;
-    adios2::ADIOS m_ADIOS;
+    std::shared_ptr<adios2::ADIOS> m_ADIOS;
 };
 
 } // end namespace adios
diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt
index 8403e7306894667f7b63a93f844a4562d938d0d3..90d030a55245ad5ee4e0d691a093d6e160567fa7 100644
--- a/bindings/python/CMakeLists.txt
+++ b/bindings/python/CMakeLists.txt
@@ -1,7 +1,3 @@
-if(NOT BUILD_SHARED_LIBS)
-  message(ERROR "Python bindings are only supported for shared libraries")
-endif()
-
 set(Python_ADDITIONAL_VERSIONS 3 2.7)
 find_package(PythonInterp REQUIRED)
 find_package(PythonLibsNew REQUIRED)
diff --git a/bindings/python/gluePyBind11.cpp b/bindings/python/gluePyBind11.cpp
index 86eab2cb14aad75939642f69d9147b7e377bb8b5..85f5ec219461a07de5c4a89ce690b5f426f100dd 100644
--- a/bindings/python/gluePyBind11.cpp
+++ b/bindings/python/gluePyBind11.cpp
@@ -68,7 +68,7 @@ adios2::ADIOSPy ADIOSPyInit(adios2::pyObject &object, const bool debugMode)
 adios2::ADIOSPy ADIOSPyInitConfig(const std::string configFile,
                                   const bool debugMode)
 {
-    return adios2::ADIOSPy(debugMode);
+    return adios2::ADIOSPy(configFile, debugMode);
 }
 
 adios2::ADIOSPy ADIOSPyInit(const bool debugMode)
diff --git a/cmake/DetectOptions.cmake b/cmake/DetectOptions.cmake
index a484a5957f7c862b724cd102639b6339e7460c98..5022c676d3c31fe1dbaa82907f0ec9b72417a614 100644
--- a/cmake/DetectOptions.cmake
+++ b/cmake/DetectOptions.cmake
@@ -94,7 +94,7 @@ list(INSERT CMAKE_MODULE_PATH 0
   "${ADIOS2_SOURCE_DIR}/thirdparty/pybind11/pybind11/tools"
 )
 if(ADIOS2_USE_Python STREQUAL AUTO)
-  if(BUILD_SHARED_LIBS)
+  if(SHARED_LIBS_SUPPORTED AND ADIOS2_ENABLE_PIC)
     set(Python_ADDITIONAL_VERSIONS 3 2.7)
     find_package(PythonInterp)
     find_package(PythonLibsNew)
diff --git a/examples/basics/joinedArray/joinedArray_write.cpp b/examples/basics/joinedArray/joinedArray_write.cpp
index 73aa4fc6b251665d8c1f4f205a127c58755dc77f..d22438dda7dfe985b869d9abc8c9911efc186ad0 100644
--- a/examples/basics/joinedArray/joinedArray_write.cpp
+++ b/examples/basics/joinedArray/joinedArray_write.cpp
@@ -70,6 +70,8 @@ int main(int argc, char *argv[])
         // Get io settings from the config file or
         // create one with default settings here
         adios2::IO &io = adios.DeclareIO("Output");
+        // io.SetEngine("ADIOS1Writer");
+        // io.AddTransport("File", {{"library", "MPI"}});
 
         /*
          * Define joinable local array: type, name, global and local size
diff --git a/examples/heatTransfer/read/PrintData.cpp b/examples/heatTransfer/read/PrintData.cpp
index ef84e6a40a69e1ad1c37514c69a0843093055e06..edbc6688fba93569b4d3eb9b74190735d9b21be7 100644
--- a/examples/heatTransfer/read/PrintData.cpp
+++ b/examples/heatTransfer/read/PrintData.cpp
@@ -15,6 +15,44 @@
 
 #include "PrintData.h"
 
+void printData(double *xy, size_t *size, size_t *offset, int rank, int steps)
+{
+    std::ofstream myfile;
+    std::string filename = "data." + std::to_string(rank);
+    myfile.open(filename);
+    double *data = xy;
+    uint64_t nelems = size[0] * size[1];
+    for (int step = 0; step < steps; step++)
+    {
+        myfile << "rank=" << rank << " size=" << size[0] << "x" << size[1]
+               << " offsets=" << offset[0] << ":" << offset[1]
+               << " step=" << step << std::endl;
+
+        myfile << " time   row   columns " << offset[1] << "..."
+               << offset[1] + size[1] - 1 << std::endl;
+        myfile << "        ";
+        for (int j = 0; j < size[1]; j++)
+        {
+            myfile << std::setw(9) << offset[1] + j;
+        }
+        myfile << std::endl;
+        myfile << "------------------------------------------------------------"
+                  "--\n";
+        for (int i = 0; i < size[0]; i++)
+        {
+            myfile << std::setw(5) << step << std::setw(5) << offset[0] + i;
+            for (int j = 0; j < size[1]; j++)
+            {
+                myfile << std::setw(9) << std::setprecision(2)
+                       << data[i * size[1] + j];
+            }
+            myfile << std::endl;
+        }
+        data += nelems;
+    }
+    myfile.close();
+}
+
 void printData(double *xy, uint64_t *size, uint64_t *offset, int rank,
                int steps)
 {
diff --git a/examples/heatTransfer/read/PrintData.h b/examples/heatTransfer/read/PrintData.h
index 308ace34007f88c15498464b1555b5cca3ed1f6b..13e1e527ce1a27036d0f65c540be48a459b3b3eb 100644
--- a/examples/heatTransfer/read/PrintData.h
+++ b/examples/heatTransfer/read/PrintData.h
@@ -13,6 +13,7 @@
 
 #include <cstdint>
 
+void printData(double *xy, size_t *size, size_t *offset, int rank, int steps);
 void printData(double *xy, uint64_t *size, uint64_t *offset, int rank,
                int steps);
 
diff --git a/examples/heatTransfer/read/heatRead_adios2.cpp b/examples/heatTransfer/read/heatRead_adios2.cpp
index dd8ef0cf0e7038a99eae8e3d7a90c71ced2d9f15..35ec668372a3c950002659d1487cac773a4515c7 100644
--- a/examples/heatTransfer/read/heatRead_adios2.cpp
+++ b/examples/heatTransfer/read/heatRead_adios2.cpp
@@ -93,8 +93,8 @@ int main(int argc, char *argv[])
     }
 
     // 1D decomposition of the columns, which is inefficient for reading!
-    std::vector<uint64_t> readsize({gndx, gndy / nproc});
-    std::vector<uint64_t> offset({0LL, rank * readsize[1]});
+    adios2::Dims readsize({gndx, gndy / nproc});
+    adios2::Dims offset({0LL, rank * readsize[1]});
     if (rank == nproc - 1)
     {
         // last process should read all the rest of columns
diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt
index 43b9e6a4bc0f6d23aef3571dc119cb7a67579a1e..2850407da804fce34afa2c23bdfce603865e4795 100644
--- a/examples/hello/CMakeLists.txt
+++ b/examples/hello/CMakeLists.txt
@@ -19,3 +19,12 @@ endif()
 if(ADIOS2_HAVE_HDF5)
   add_subdirectory(hdf5Writer)
 endif()
+
+if(ADIOS2_HAVE_BZip2)
+  add_subdirectory(bpBZip2Wrapper)
+endif()
+
+if(ADIOS2_HAVE_ZFP)
+  add_subdirectory(bpZfpWrapper)
+endif()
+
diff --git a/examples/hello/bpBZip2Wrapper/CMakeLists.txt b/examples/hello/bpBZip2Wrapper/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3803a998a7103673cdee602633c71a03a049da24
--- /dev/null
+++ b/examples/hello/bpBZip2Wrapper/CMakeLists.txt
@@ -0,0 +1,18 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+if(ADIOS2_HAVE_MPI)
+  find_package(MPI COMPONENTS C REQUIRED)
+
+  add_executable(hello_bpBZip2Wrapper helloBPBZip2Wrapper.cpp)
+  target_include_directories(hello_bpBZip2Wrapper PRIVATE ${MPI_C_INCLUDE_PATH})
+  target_link_libraries(hello_bpBZip2Wrapper ${MPI_C_LIBRARIES})
+  
+else()
+  add_executable(hello_bpBZip2Wrapper helloBPBZip2Wrapper_nompi.cpp)
+  
+endif()
+
+target_link_libraries(hello_bpBZip2Wrapper adios2)
diff --git a/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper.cpp b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bb425051ccd39c7bfdbb56f1925f1d014476be42
--- /dev/null
+++ b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper.cpp
@@ -0,0 +1,120 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloBPBZip2Wrapper.cpp: Simple self-descriptive example of how to write a
+ * variable to a BP File that lives in several MPI processes and is compressed
+ * with BZip2 http://www.bzip.org/
+ *
+ *  Created on: Jul 26, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+#include <mpi.h>
+
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <numeric>   //std::iota
+#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 uints from 0 to 1000 */
+    std::vector<unsigned int> myUInts(1000);
+    std::iota(myUInts.begin(), myUInts.end(), 0.f);
+    const std::size_t Nx = myUInts.size();
+    const std::size_t inputBytes = Nx * sizeof(unsigned int);
+
+    try
+    {
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON);
+
+        // Get a Transform of type BZip2
+        adios2::Transform &adiosBZip2 = adios.GetTransform("bzip2");
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_BZip2");
+
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios2::Variable<unsigned int> &bpUInts =
+            bpIO.DefineVariable<unsigned int>("bpUInts", {size * Nx},
+                                              {rank * Nx}, {Nx},
+                                              adios2::ConstantDims);
+
+        // 1st way: adding transform metadata to variable to Engine can decide:
+        // &adiosBZip2 gets mapped to bpUInts.TransformInfo[bzip2ID].Operator
+        const unsigned int bzip2ID =
+            bpUInts.AddTransform(adiosBZip2, {{"BlockSize100K", "9"}});
+
+        // 2nd way: treat Transforms as wrappers to underlying library.
+        // you can redefine parameters
+        const std::size_t estimatedSize =
+            adiosBZip2.BufferMaxSize(Nx * bpUInts.m_ElementSize);
+        std::vector<char> compressedBuffer(estimatedSize);
+        size_t compressedSize = adiosBZip2.Compress(
+            myUInts.data(), bpUInts.m_Count, bpUInts.m_ElementSize,
+            bpUInts.m_Type, compressedBuffer.data(), {{"BlockSize100K", "1"}});
+
+        compressedBuffer.resize(compressedSize);
+
+        std::cout << "Rank " << rank << "\n";
+        std::cout << "Compression summary:\n";
+        std::cout << "Input data size: " << inputBytes << " bytes\n";
+        std::cout << "BZip2 estimated output size: " << estimatedSize
+                  << " bytes\n";
+        std::cout << "BZip2 final output size: " << compressedSize
+                  << " bytes\n\n";
+
+        // Allocate original data size
+        std::vector<unsigned int> decompressedBuffer(Nx);
+        size_t decompressedSize = adiosBZip2.Decompress(
+            compressedBuffer.data(), compressedSize, decompressedBuffer.data(),
+            decompressedBuffer.size() * sizeof(unsigned int));
+
+        std::cout << "Decompression summary:\n";
+        std::cout << "Decompressed size: " << decompressedSize << " bytes\n";
+        std::cout << "Data:\n";
+
+        for (const auto number : decompressedBuffer)
+        {
+            if (number % 25 == 0)
+            {
+                std::cout << "\n";
+            }
+            std::cout << number << " ";
+        }
+        std::cout << "\n";
+    }
+    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/bpBZip2Wrapper/helloBPBZip2Wrapper_nompi.cpp b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper_nompi.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe7e2b7b027a031f5b63c3d61f94b2788763c6d9
--- /dev/null
+++ b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper_nompi.cpp
@@ -0,0 +1,103 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloBPBZip2Writer_nompi.cpp sequential non-mpi version of helloBPBZip2Writer
+ * using BZip2 http://www.bzip.org/
+ *
+ *  Created on: Jul 26, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <numeric>   //std::iota
+#include <stdexcept> //std::invalid_argument std::exception
+#include <vector>
+
+#include <adios2.h>
+
+int main(int argc, char *argv[])
+{
+    /** Application variable uints from 0 to 1000 */
+    std::vector<unsigned int> myUInts(1000);
+    std::iota(myUInts.begin(), myUInts.end(), 0.f);
+    const std::size_t Nx = myUInts.size();
+    const std::size_t inputBytes = Nx * sizeof(unsigned int);
+
+    try
+    {
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios2::ADIOS adios(adios2::DebugON);
+
+        // Get a Transform of type BZip2
+        adios2::Transform &adiosBZip2 = adios.GetTransform("bzip2");
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_BZip2");
+
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios2::Variable<unsigned int> &bpUInts =
+            bpIO.DefineVariable<unsigned int>("bpUInts", {}, {}, {Nx},
+                                              adios2::ConstantDims);
+
+        // 1st way: adding transform metadata to variable to Engine can decide:
+        bpUInts.AddTransform(adiosBZip2, {{"BlockSize100K", "10"}});
+
+        // 2nd way: treat Transforms as wrappers to underlying library:
+        const std::size_t estimatedSize =
+            adiosBZip2.BufferMaxSize(Nx * bpUInts.m_ElementSize);
+        std::vector<char> compressedBuffer(estimatedSize);
+        size_t compressedSize = adiosBZip2.Compress(
+            myUInts.data(), bpUInts.m_Count, bpUInts.m_ElementSize,
+            bpUInts.m_Type, compressedBuffer.data(), {{"BlockSize100K", "9"}});
+
+        compressedBuffer.resize(compressedSize);
+
+        std::cout << "Compression summary:\n";
+        std::cout << "Input data size: " << inputBytes << " bytes\n";
+        std::cout << "BZip2 estimated output size: " << estimatedSize
+                  << " bytes\n";
+        std::cout << "BZip2 final output size: " << compressedSize
+                  << " bytes\n\n";
+
+        // Allocate original data size
+        std::vector<unsigned int> decompressedBuffer(Nx);
+        size_t decompressedSize = adiosBZip2.Decompress(
+            compressedBuffer.data(), compressedSize, decompressedBuffer.data(),
+            decompressedBuffer.size() * sizeof(unsigned int));
+
+        std::cout << "Decompression summary:\n";
+        std::cout << "Decompressed size: " << decompressedSize << " bytes\n";
+        std::cout << "Data:\n";
+
+        for (const auto number : decompressedBuffer)
+        {
+            if (number % 25 == 0)
+            {
+                std::cout << "\n";
+            }
+            std::cout << number << " ";
+        }
+        std::cout << "\n";
+    }
+    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\n";
+        std::cout << e.what() << "\n";
+    }
+
+    return 0;
+}
diff --git a/examples/hello/bpWriter/helloBPWriter_nompi.cpp b/examples/hello/bpWriter/helloBPWriter_nompi.cpp
index 7217e12b6ac48e8dafa6062593bb5d4f41c3ca8d..0a08af072a9e949079e48b2172e46c266368a1c1 100644
--- a/examples/hello/bpWriter/helloBPWriter_nompi.cpp
+++ b/examples/hello/bpWriter/helloBPWriter_nompi.cpp
@@ -29,7 +29,6 @@ int main(int argc, char *argv[])
         /*** IO class object: settings and factory of Settings: Variables,
          * Parameters, Transports, and Execution: Engines */
         adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N");
-        bpIO.AddTransport("File", {{"Library", "stdio"}});
 
         /** global array: name, { shape (total dimensions) }, { start (local) },
          * { count (local) }, all are constant dimensions */
diff --git a/examples/hello/bpZfpWrapper/CMakeLists.txt b/examples/hello/bpZfpWrapper/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c5cb52b74f20dc3bdced1ea0e63a5a5373a33329
--- /dev/null
+++ b/examples/hello/bpZfpWrapper/CMakeLists.txt
@@ -0,0 +1,18 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+if(ADIOS2_HAVE_MPI)
+  find_package(MPI COMPONENTS C REQUIRED)
+
+  add_executable(hello_bpZfpWrapper helloBPZfpWrapper.cpp)
+  target_include_directories(hello_bpZfpWrapper PRIVATE ${MPI_C_INCLUDE_PATH})
+  target_link_libraries(hello_bpZfpWrapper ${MPI_C_LIBRARIES})
+  
+else()
+  add_executable(hello_bpZfpWrapper helloBPZfpWrapper_nompi.cpp)
+  
+endif()
+
+target_link_libraries(hello_bpZfpWrapper adios2)
diff --git a/examples/hello/bpZfpWrapper/helloBPZfpWrapper.cpp b/examples/hello/bpZfpWrapper/helloBPZfpWrapper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9227e20c7c266d94f61e64eb71bbac290e48476
--- /dev/null
+++ b/examples/hello/bpZfpWrapper/helloBPZfpWrapper.cpp
@@ -0,0 +1,122 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloBPZfpWrapper.cpp: Simple self-descriptive example of how to write a
+ * variable to a BP File that lives in several MPI processes and is compressed
+ * with Zfp https://computation.llnl.gov/projects/floating-point-compression
+ *
+ *  Created on: Jul 26, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+#include <mpi.h>
+
+#include <cstdint>   //std::int32_t
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <numeric>   //std::iota
+#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 uints from 0 to 100 */
+    std::vector<float> myFloats(100);
+    std::iota(myFloats.begin(), myFloats.end(), 0.f);
+    const std::size_t Nx = myFloats.size();
+    const std::size_t inputBytes = Nx * sizeof(float);
+
+    try
+    {
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON);
+
+        // Get a Transform of type BZip2
+        adios2::Transform &adiosZfp = adios.GetTransform("zfp");
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_Zfp");
+
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>(
+            "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims);
+
+        // 1st way: adding transform metadata to variable to Engine can decide:
+        const unsigned int zfpID =
+            bpFloats.AddTransform(adiosZfp, {{"Rate", "8"}});
+
+        // 2nd way: treat Transforms as wrappers to underlying library:
+        const std::size_t estimatedSize =
+            adiosZfp.BufferMaxSize(myFloats.data(), bpFloats.m_Count,
+                                   bpFloats.m_TransformsInfo[zfpID].Parameters);
+
+        // Compress
+        std::vector<char> compressedBuffer(estimatedSize);
+
+        size_t compressedSize = adiosZfp.Compress(
+            myFloats.data(), bpFloats.m_Count, bpFloats.m_ElementSize,
+            bpFloats.m_Type, compressedBuffer.data(),
+            bpFloats.m_TransformsInfo[zfpID].Parameters);
+
+        compressedBuffer.resize(compressedSize);
+
+        std::cout << "Compression summary:\n";
+        std::cout << "Input data size: " << inputBytes << " bytes\n";
+        std::cout << "Zfp estimated output size: " << estimatedSize
+                  << " bytes\n";
+        std::cout << "Zfp final output size: " << compressedSize
+                  << " bytes\n\n";
+
+        // Allocate original data size
+        std::vector<float> decompressedBuffer(Nx);
+        size_t decompressedSize = adiosZfp.Decompress(
+            compressedBuffer.data(), compressedBuffer.size(),
+            decompressedBuffer.data(), bpFloats.m_Count, bpFloats.m_Type,
+            bpFloats.m_TransformsInfo[zfpID].Parameters);
+
+        std::cout << "Decompression summary:\n";
+        std::cout << "Decompressed size: " << decompressedSize << " bytes\n ";
+        std::cout << "Data:\n";
+
+        for (const auto number : decompressedBuffer)
+        {
+            if (static_cast<int>(number) % 25 == 0 && number != 0)
+            {
+                std::cout << "\n";
+            }
+            std::cout << number << " ";
+        }
+        std::cout << "\n";
+    }
+    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/bpZfpWrapper/helloBPZfpWrapper_nompi.cpp b/examples/hello/bpZfpWrapper/helloBPZfpWrapper_nompi.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e84feee7b8c75401da3ee360ac22b29a291ce70f
--- /dev/null
+++ b/examples/hello/bpZfpWrapper/helloBPZfpWrapper_nompi.cpp
@@ -0,0 +1,114 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * helloBPZfpWriter_nompi.cpp sequential non-mpi version of helloBPZfpWrapper
+ * using  Zfp https://computation.llnl.gov/projects/floating-point-compression
+ *
+ *  Created on: Jul 26, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include <cstdint>   //std::int32_t
+#include <ios>       //std::ios_base::failure
+#include <iostream>  //std::cout
+#include <numeric>   //std::iota
+#include <stdexcept> //std::invalid_argument std::exception
+#include <vector>
+
+#include <adios2.h>
+
+int main(int argc, char *argv[])
+{
+    /** Application variable uints from 0 to 100 */
+    std::vector<float> myFloats(100);
+    std::iota(myFloats.begin(), myFloats.end(), 0.f);
+    const std::size_t Nx = myFloats.size();
+    const std::size_t inputBytes = Nx * sizeof(float);
+
+    try
+    {
+        /** ADIOS class factory of IO class objects, DebugON is recommended */
+        adios2::ADIOS adios(adios2::DebugON);
+
+        // Get a Transform of type BZip2
+        adios2::Transform &adiosZfp = adios.GetTransform("zfp");
+
+        /*** IO class object: settings and factory of Settings: Variables,
+         * Parameters, Transports, and Execution: Engines */
+        adios2::IO &bpIO = adios.DeclareIO("BPVariable_Zfp");
+
+        /** global array : name, { shape (total) }, { start (local) }, { count
+         * (local) }, all are constant dimensions */
+        adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>(
+            "bpUInts", {}, {}, {Nx}, adios2::ConstantDims);
+
+        // Adding transform metadata to variable:
+        // Options:
+        // Rate double
+        // Tolerance
+        // Precision
+        const unsigned int zfpID =
+            bpFloats.AddTransform(adiosZfp, {{"Rate", "8"}});
+
+        // Treat Transforms as wrappers to underlying library (zfp):
+        const std::size_t estimatedSize =
+            adiosZfp.BufferMaxSize(myFloats.data(), bpFloats.m_Count,
+                                   bpFloats.m_TransformsInfo[zfpID].Parameters);
+
+        // Compress
+        std::vector<char> compressedBuffer(estimatedSize);
+
+        size_t compressedSize = adiosZfp.Compress(
+            myFloats.data(), bpFloats.m_Count, bpFloats.m_ElementSize,
+            bpFloats.m_Type, compressedBuffer.data(),
+            bpFloats.m_TransformsInfo[zfpID].Parameters);
+
+        compressedBuffer.resize(compressedSize);
+
+        std::cout << "Compression summary:\n";
+        std::cout << "Input data size: " << inputBytes << " bytes\n";
+        std::cout << "Zfp estimated output size: " << estimatedSize
+                  << " bytes\n";
+        std::cout << "Zfp final output size: " << compressedSize
+                  << " bytes\n\n";
+
+        // Decompress, allocate original data size
+        std::vector<float> decompressedBuffer(Nx);
+        size_t decompressedSize = adiosZfp.Decompress(
+            compressedBuffer.data(), compressedBuffer.size(),
+            decompressedBuffer.data(), bpFloats.m_Count, bpFloats.m_Type,
+            bpFloats.m_TransformsInfo[zfpID].Parameters);
+
+        std::cout << "Decompression summary:\n";
+        std::cout << "Decompressed size: " << decompressedSize << " bytes\n ";
+        std::cout << "Data:\n";
+
+        for (const auto number : decompressedBuffer)
+        {
+            if (static_cast<int>(number) % 25 == 0 && number != 0)
+            {
+                std::cout << "\n";
+            }
+            std::cout << number << " ";
+        }
+        std::cout << "\n";
+    }
+    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\n";
+        std::cout << e.what() << "\n";
+    }
+
+    return 0;
+}
diff --git a/source/adios2/ADIOSConfig.h.in b/source/adios2/ADIOSConfig.h.in
index 7bfbd537dec1992ed8b55ba1f4fdfe954d64218b..44b9128c1f50b81c4d0458fe163833c1138aecdb 100644
--- a/source/adios2/ADIOSConfig.h.in
+++ b/source/adios2/ADIOSConfig.h.in
@@ -27,10 +27,10 @@
 /* CMake Option: ADIOS_USE_MPI=OFF */
 #cmakedefine ADIOS2_HAVE_MPI
 
-/* CMake Option: ADIOS_USE_ZFP=OFF */
+/* CMake Option: ADIOS_USE_ZFP=ON */
 #cmakedefine ADIOS2_HAVE_ZFP
 
-/* CMake Option: ADIOS_USE_BZip2=OFF */
+/* CMake Option: ADIOS_USE_BZip2=ON */
 #cmakedefine ADIOS2_HAVE_BZIP2
 
 /* CMake Option: ADIOS_USE_ADIOS1=ON */
diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h
index 8f1471a4a7067ea274f5620ba439320856679df0..f3043732b588cbde469d3b5f9e06adcc85afa03b 100644
--- a/source/adios2/ADIOSMacros.h
+++ b/source/adios2/ADIOSMacros.h
@@ -56,4 +56,10 @@
     MACRO(float)                                                               \
     MACRO(double)
 
+#define ADIOS2_FOREACH_ZFP_TYPE_1ARG(MACRO)                                    \
+    MACRO(int32_t)                                                             \
+    MACRO(int64_t)                                                             \
+    MACRO(float)                                                               \
+    MACRO(double)
+
 #endif /* ADIOS2_ADIOSMACROS_H */
diff --git a/source/adios2/ADIOSTypes.h b/source/adios2/ADIOSTypes.h
index 352d62ef2c0ade4981f629e0c65c8252639de082..bb806e56960f57681c2edd4ff500a94fc67103d5 100644
--- a/source/adios2/ADIOSTypes.h
+++ b/source/adios2/ADIOSTypes.h
@@ -144,7 +144,7 @@ enum class SelectionType
 
 // adios defaults
 #ifdef _WIN32
-const std::string DefaultFileLibrary("stdio");
+const std::string DefaultFileLibrary("fstream");
 #else
 const std::string DefaultFileLibrary("POSIX");
 #endif
@@ -160,7 +160,7 @@ constexpr size_t DefaultMaxBufferSize(std::numeric_limits<size_t>::max() - 1);
 
 /** default buffer growth factor. Needs to be studied
  * for optimizing applications*/
-constexpr float DefaultBufferGrowthFactor(1.05);
+constexpr float DefaultBufferGrowthFactor(1.05f);
 
 /** default size for writing/reading files using POSIX/fstream/stdio write
  *  2Gb - 100Kb (tolerance)*/
diff --git a/source/adios2/CMakeLists.txt b/source/adios2/CMakeLists.txt
index da981d4b4e66e8c6e7f946f00e88c47ea076fbf9..f0891b33b70a60ff70f7a3d075c4ba6404c76f28 100644
--- a/source/adios2/CMakeLists.txt
+++ b/source/adios2/CMakeLists.txt
@@ -10,13 +10,14 @@ add_library(adios2
   core/Selection.cpp
   core/SelectionBoundingBox.cpp
   core/SelectionPoints.cpp
-  core/Transform.cpp
+  core/Transform.cpp core/Transform.tcc
   core/Variable.cpp core/Variable.tcc
   core/VariableBase.cpp
   core/VariableCompound.cpp core/VariableCompound.tcc
   
 #helper
   helper/adiosMath.cpp
+  helper/adiosMPIFunctions.cpp
   helper/adiosString.cpp
   helper/adiosSystem.cpp
   helper/adiosType.cpp
@@ -79,15 +80,14 @@ endif()
 
 if(ADIOS2_HAVE_BZip2)
   find_package(BZip2 REQUIRED)
-  target_sources(adios2 PRIVATE transform/compression/BZip2.cpp)
+  target_sources(adios2 PRIVATE transform/compress/CompressBZip2.cpp)
   target_link_libraries(adios2 PRIVATE BZip2::BZip2)
 endif()
 
 if(ADIOS2_HAVE_ZFP)
   find_package(ZFP REQUIRED)
-  message("ADIOS ZFP support not yet implemented")
-#  target_sources(adios2 PRIVATE transform/compression/ZFP.cpp)
-#  target_link_libraries(adios2 PRIVATE zfp::zfp)
+  target_sources(adios2 PRIVATE transform/compress/CompressZfp.cpp)
+  target_link_libraries(adios2 PRIVATE zfp::zfp)
 endif()
 
 if(ADIOS2_HAVE_MPI)
diff --git a/source/adios2/core/ADIOS.cpp b/source/adios2/core/ADIOS.cpp
index af7020254e84fd396c9e4c8be71c984deef9b8f0..d4853c603d064962abc543a8caa94dfc36a01643 100644
--- a/source/adios2/core/ADIOS.cpp
+++ b/source/adios2/core/ADIOS.cpp
@@ -21,6 +21,15 @@
 #include "adios2/ADIOSMPI.h"
 #include "adios2/helper/adiosFunctions.h"
 
+// transforms
+#ifdef ADIOS2_HAVE_BZIP2
+#include "adios2/transform/compress/CompressBZip2.h"
+#endif
+
+#ifdef ADIOS2_HAVE_ZFP
+#include "adios2/transform/compress/CompressZfp.h"
+#endif
+
 namespace adios2
 {
 
@@ -86,11 +95,59 @@ IO &ADIOS::GetIO(const std::string name)
     {
         throw std::invalid_argument(
             "ERROR: Unable to find previously defined IO object with name \"" +
-            name + "\" in call to GetIO.");
+            name + "\", in call to GetIO.");
     }
     return itIO->second;
 }
 
+Transform &ADIOS::GetTransform(const std::string transform)
+{
+    auto itTransform = m_Transforms.find(transform);
+
+    if (itTransform != m_Transforms.end())
+    {
+        return *itTransform->second.get();
+    }
+
+    if (transform == "bzip2" || transform == "BZip2")
+    {
+#ifdef ADIOS2_HAVE_BZIP2
+        auto itPair = m_Transforms.emplace(
+            "bzip2",
+            std::make_shared<adios2::transform::CompressBZip2>(m_DebugMode));
+        return *itPair.first->second;
+#else
+        throw std::invalid_argument(
+            "ERROR: this version of ADIOS2 didn't compile with "
+            "bzip2 library, in call to GetTransport\n");
+#endif
+    }
+    else if (transform == "zfp" || transform == "Zfp")
+    {
+#ifdef ADIOS2_HAVE_ZFP
+        auto itPair = m_Transforms.emplace(
+            "zfp",
+            std::make_shared<adios2::transform::CompressZfp>(m_DebugMode));
+        return *itPair.first->second;
+#else
+        throw std::invalid_argument(
+            "ERROR: this version of ADIOS2 didn't compile with "
+            "zfp library, in call to GetTransport\n");
+#endif
+    }
+    else
+    {
+        if (m_DebugMode)
+        {
+            throw std::invalid_argument(
+                "ERROR: transform " + transform +
+                " not supported by ADIOS2, in call to GetTransport\n");
+        }
+    }
+
+    return *itTransform->second.get();
+}
+
 // PRIVATE FUNCTIONS
 void ADIOS::CheckMPI() const
 {
diff --git a/source/adios2/core/ADIOS.h b/source/adios2/core/ADIOS.h
index c9e9937076f33f3d15f06c0d4cc02f304f38a2ef..eba4e72430fa5b313253fb1fc8793c0f0adeef29 100644
--- a/source/adios2/core/ADIOS.h
+++ b/source/adios2/core/ADIOS.h
@@ -33,7 +33,9 @@ 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
+
+    /** Changed by language bindings */
+    std::string m_HostLanguage = "C++";
 
     /**
      * @brief Constructor for MPI applications WITH a XML config file
@@ -43,7 +45,7 @@ public:
      * @param debugMode true: extra exception checks (recommended)
      */
     ADIOS(const std::string configFile, MPI_Comm mpiComm,
-          const bool debugMode = false);
+          const bool debugMode = true);
 
     /**
      * @brief Constructor for non-MPI applications WITH a XML config file
@@ -51,20 +53,27 @@ public:
      * future?)
      * @param debugMode true: extra exception checks (recommended)
      */
-    ADIOS(const std::string configFile, const bool debugMode = false);
+    ADIOS(const std::string configFile, const bool debugMode = true);
 
     /**
      * @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);
+    ADIOS(MPI_Comm mpiComm, const bool debugMode = true);
 
     /**
      *  @brief ADIOS no-MPI default empty constructor
      *  @param debugMode true: extra exception checks (recommended)
      */
-    ADIOS(const bool debugMode = false);
+    ADIOS(const bool debugMode = true);
+
+    /**
+     * Delete copy constructor explicitly. Objects shouldn't be allowed to be
+     * redefined. Use smart pointers if this is absolutely necessary.
+     * @param adios reference to another adios object
+     */
+    ADIOS(const ADIOS &adios) = delete;
 
     ~ADIOS() = default;
 
@@ -81,19 +90,23 @@ public:
     IO &DeclareIO(const std::string ioName);
 
     /**
-     * Retrieve an already defined IO object
+     * Retrieve an already defined IO object. Make sure IO was previously
+     * created with DeclareIO. Otherwise, throws an exception in debug mode.
+     * @return reference to existing IO object inside ADIOS
      */
     IO &GetIO(const std::string name);
 
-protected: // no const member to allow default empty and copy constructors
+    Transform &GetTransform(const std::string transform);
+
+private:
     /** XML File to be read containing configuration information */
-    std::string m_ConfigFile;
+    const std::string m_ConfigFile;
 
     /** if true will do more checks, exceptions, warnings, expect slower code */
-    bool m_DebugMode = false;
+    const bool m_DebugMode = true;
 
     /** transforms associated with ADIOS run */
-    std::vector<std::shared_ptr<Transform>> m_Transforms;
+    std::map<std::string, std::shared_ptr<Transform>> m_Transforms;
 
     /**
      * @brief List of IO class objects defined from either ADIOS
diff --git a/source/adios2/core/Engine.inl b/source/adios2/core/Engine.inl
index 1dde7f3c449f7dbb862113200883e84193ec4324..dccf770fd98215718fb83fdf6c0ba771827d1b8f 100644
--- a/source/adios2/core/Engine.inl
+++ b/source/adios2/core/Engine.inl
@@ -29,7 +29,7 @@ void Engine::Write(Variable<T> &variable, const T *values)
 {
     if (m_DebugMode)
     {
-        variable.CheckDims("in call to Write");
+        variable.CheckDimsBeforeWrite("Write(" + variable.m_Name + ")");
     }
 
     DoWrite(variable, values);
diff --git a/source/adios2/core/Transform.cpp b/source/adios2/core/Transform.cpp
index dc4079aed7aa725493c67f6eab8cda3c1f4617de..02973f2460c664fc9f214a9b6692728ed4c91229 100644
--- a/source/adios2/core/Transform.cpp
+++ b/source/adios2/core/Transform.cpp
@@ -9,20 +9,90 @@
  */
 
 #include "Transform.h"
+#include "Transform.tcc"
 
 namespace adios2
 {
 
-Transform::Transform(const std::string method) : m_Method(method) {}
+Transform::Transform(const std::string library, const bool debugMode)
+: m_Library(library), m_DebugMode(debugMode)
+{
+}
+
+size_t Transform::BufferMaxSize(const size_t sizeIn) const
+{
+    if (m_DebugMode)
+    {
+        throw std::invalid_argument(
+            "ERROR: signature (const size_t) not supported "
+            "by derived class implemented with " +
+            m_Library + ", in call to BufferMaxSize\n");
+    }
+    return 0;
+}
+
+size_t Transform::Compress(const void * /*dataIn*/, const Dims & /*dimensions*/,
+                           const size_t /*elementSize*/,
+                           const std::string /*type*/, void * /*bufferOut*/,
+                           const Params & /*params*/) const
+{
+    if (m_DebugMode)
+    {
+        throw std::invalid_argument("ERROR: signature (const void*, const "
+                                    "Dims, const size_t, const std::string, "
+                                    "void*, const Params&) not supported "
+                                    "by derived class implemented with " +
+                                    m_Library + ", in call to Compress\n");
+    }
+    return 0;
+}
 
-void Transform::Compress(const std::vector<char> & /*bufferIn*/,
-                         std::vector<char> & /*bufferOut*/)
+size_t Transform::Decompress(const void *bufferIn, const size_t sizeIn,
+                             void *dataOut, const size_t sizeOut) const
 {
+    if (m_DebugMode)
+    {
+        throw std::invalid_argument(
+            "ERROR: signature (const void*, const size_t, void) not supported "
+            "by derived class implemented with " +
+            m_Library + ", in call to Decompress\n");
+    }
+
+    return 0;
 }
 
-void Transform::Decompress(const std::vector<char> & /*bufferIn*/,
-                           std::vector<char> & /*bufferOut*/)
+size_t Transform::Decompress(const void * /*bufferIn*/, const size_t /*sizeIn*/,
+                             void * /*dataOut*/, const Dims & /*dimensions*/,
+                             const std::string /*type*/,
+                             const Params & /*parameters*/) const
 {
+    if (m_DebugMode)
+    {
+        throw std::invalid_argument("ERROR: signature (const void*, const "
+                                    "size_t, void*, const Dims&, const "
+                                    "std::string ) not supported "
+                                    "by derived class implemented with " +
+                                    m_Library + ", in call to Decompress\n");
+    }
+
+    return 0;
+}
+
+// PROTECTED
+size_t Transform::DoBufferMaxSize(const void *dataIn, const Dims &dimensions,
+                                  const std::string type,
+                                  const Params &parameters) const
+{
+    if (m_DebugMode)
+    {
+        throw std::invalid_argument(
+            "ERROR: signature (const void*, const Dims& "
+            "std::string ) not supported "
+            "by derived class implemented with " +
+            m_Library + ", in call to BufferMaxSize\n");
+    }
+
+    return 0;
 }
 
-} // end namespace adios
+} // end namespace adios2
diff --git a/source/adios2/core/Transform.h b/source/adios2/core/Transform.h
index 32c857293ef9d7ee29ecb02abda652c81d9d261b..19d617432da299dfd62ac0e2f279946c1b8e31ff 100644
--- a/source/adios2/core/Transform.h
+++ b/source/adios2/core/Transform.h
@@ -16,33 +16,96 @@
 #include <vector>
 /// \endcond
 
-#include "adios2/ADIOSConfig.h"
+#include "adios2/ADIOSTypes.h"
 
 namespace adios2
 {
 
-/** Base class that defines data variable transformations */
+/** Base class that defines data variable transformations implemented under
+ * adios2/transform */
 class Transform
 {
 
 public:
-    /** From derived class to identify the transform */
-    const std::string m_Method;
+    /** From derived class */
+    const std::string m_Library;
 
     /**
-     * Initialize parent method
-     * @param method zlib, bzip2, szip
+     * Unique base class constructor
+     * @param method bzip2, zfp
+     * @param debugMode true: extra exceptions checks
      */
-    Transform(const std::string method);
+    Transform(const std::string library, const bool debugMode);
 
     virtual ~Transform() = default;
 
-    virtual void Compress(const std::vector<char> &bufferIn,
-                          std::vector<char> &bufferOut);
+    /**
+     * Returns a conservative buffer size to hold input data for classes
+     * @param sizeIn size of input data to be compressed in bytes
+     * @return recommended allocation for output buffer
+     */
+    virtual size_t BufferMaxSize(const size_t sizeIn) const;
+
+    /**
+     * Used by Zfp
+     * Returns a conservative buffer size to hold input data for classes
+     * @param dataIn
+     * @param dimensions
+     * @return recommended allocation for output buffer in bytes
+     */
+    template <class T>
+    size_t BufferMaxSize(const T *dataIn, const Dims &dimensions,
+                         const Params &params) const;
+
+    /**
+     * BZip2 and Zfp common call
+     * @param dataIn
+     * @param dimensions
+     * @param elementSize
+     * @param type
+     * @param bufferOut
+     * @param parameters
+     * @return size of compressed buffer
+     */
+    virtual size_t Compress(const void *dataIn, const Dims &dimensions,
+                            const size_t elementSize, const std::string type,
+                            void *bufferOut,
+                            const Params &parameters = Params()) const;
 
-    virtual void Decompress(const std::vector<char> &bufferIn,
-                            std::vector<char> &bufferOut);
+    virtual size_t Decompress(const void *bufferIn, const size_t sizeIn,
+                              void *dataOut, const size_t sizeOut) const;
+
+    /**
+     * Zfp signature
+     * @param bufferIn
+     * @param sizeIn
+     * @param dataOut
+     * @param dimensions
+     * @param type
+     * @return
+     */
+    virtual size_t Decompress(const void *bufferIn, const size_t sizeIn,
+                              void *dataOut, const Dims &dimensions,
+                              const std::string type,
+                              const Params &parameters) const;
+
+protected:
+    /** true: extra exception checks, false: skip exception checks */
+    const bool m_DebugMode = false;
+
+    /**
+     * Used by CompressZfp
+     * Returns a conservative buffer size to hold input data for classes
+     * @param dataIn
+     * @param dimensions
+     * @param type
+     * @return conservative buffer size for allocation
+     */
+    virtual size_t DoBufferMaxSize(const void *dataIn, const Dims &dimensions,
+                                   const std::string type,
+                                   const Params &parameters) const;
 };
 
-} // end namespace adios
+} // end namespace adios2
+
 #endif /* ADIOS2_CORE_TRANSFORM_H_ */
diff --git a/source/adios2/core/Transform.tcc b/source/adios2/core/Transform.tcc
new file mode 100644
index 0000000000000000000000000000000000000000..3fac195fda0603970a939ab6f817c9c553c5079f
--- /dev/null
+++ b/source/adios2/core/Transform.tcc
@@ -0,0 +1,35 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Transform.tcc : specialization of template functions
+ *
+ *  Created on: Jul 25, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_CORE_TRANSFORM_TCC_
+#define ADIOS2_CORE_TRANSFORM_TCC_
+
+#include "Transform.h"
+
+#include "adios2/ADIOSMacros.h"
+#include "adios2/helper/adiosFunctions.h"
+
+namespace adios2
+{
+
+#define declare_type(T)                                                        \
+    template <>                                                                \
+    size_t Transform::BufferMaxSize<T>(                                        \
+        const T *dataIn, const Dims &dimensions, const Params &parameters)     \
+        const                                                                  \
+    {                                                                          \
+        return DoBufferMaxSize(dataIn, dimensions, GetType<T>(), parameters);  \
+    }
+ADIOS2_FOREACH_ZFP_TYPE_1ARG(declare_type)
+#undef declare_type
+
+} // end namespace adios2
+
+#endif // ADIOS2_CORE_TRANSFORM_TCC_
diff --git a/source/adios2/core/VariableBase.cpp b/source/adios2/core/VariableBase.cpp
index 3a13c739ad5ea212d8f00815c85d6170f01e95ed..d98f572d15db6b399d008e6d5c4364cbbd29f91c 100644
--- a/source/adios2/core/VariableBase.cpp
+++ b/source/adios2/core/VariableBase.cpp
@@ -60,8 +60,7 @@ void VariableBase::SetSelection(const Dims start, const Dims count)
         }
 
         if (m_ShapeID == ShapeID::GlobalArray &&
-            (m_Shape.size() != m_Count.size() ||
-             m_Shape.size() != m_Start.size()))
+            (m_Shape.size() != count.size() || m_Shape.size() != start.size()))
         {
             throw std::invalid_argument("ERROR: count and start must be the "
                                         "same size as shape for variable " +
@@ -125,105 +124,176 @@ void VariableBase::SetStepSelection(const unsigned int startStep,
     m_ReadNSteps = countStep;
 }
 
-void VariableBase::AddTransform(
-    Transform &transform, const std::vector<std::string> &parametersVector)
+// transforms related functions
+unsigned int VariableBase::AddTransform(Transform &transform,
+                                        const Params &parameters) noexcept
 {
+    m_TransformsInfo.push_back(TransformInfo{transform, parameters});
+    return static_cast<unsigned int>(m_TransformsInfo.size() - 1);
 }
 
-void VariableBase::AddTransform(Transform &transform,
-                                const Params &parametersVector)
+void VariableBase::ResetTransformParameters(const unsigned int transformIndex,
+                                            const Params &parameters)
 {
+    if (m_DebugMode)
+    {
+        if (transformIndex < m_TransformsInfo.size())
+        {
+            m_TransformsInfo[transformIndex].Parameters = parameters;
+        }
+    }
+    else
+    {
+        m_TransformsInfo[transformIndex].Parameters = parameters;
+    }
 }
 
-// transforms related functions
-void VariableBase::ClearTransforms() { m_TransformsInfo.clear(); }
+void VariableBase::ClearTransforms() noexcept { m_TransformsInfo.clear(); }
 
 // PRIVATE
 void VariableBase::InitShapeType()
 {
-    if (!m_Shape.empty() && m_Start.empty() && m_Count.empty())
+    if (!m_Shape.empty())
     {
-        if (m_DebugMode)
+        if (std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) == 1)
         {
-            if (m_ConstantDims)
+            if (!m_Start.empty() &&
+                std::count(m_Start.begin(), m_Start.end(), 0) != m_Start.size())
             {
-                throw std::invalid_argument(
-                    "ERROR: isConstantShape (true) argument is invalid "
-                    "with empty start and count "
-                    "arguments\n");
+                throw std::invalid_argument("ERROR: The Start array must be "
+                                            "empty or full-zero when defining "
+                                            "a Joined Array in call to "
+                                            "DefineVariable " +
+                                            m_Name + "\n");
             }
+            m_ShapeID = ShapeID::JoinedArray;
         }
-
-        m_ShapeID = ShapeID::GlobalArray;
-    }
-    else if (!m_Shape.empty() && m_Shape.size() == m_Start.size() &&
-             m_Shape.size() == m_Count.size())
-    {
-        if (m_DebugMode)
+        else if (m_Start.empty() && m_Count.empty())
         {
-            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_Shape.size() == 1 && m_Shape.front() == LocalValueDim)
+            {
+                m_ShapeID = ShapeID::LocalValue;
+                m_SingleValue = true;
+            }
+            else
             {
-                if (m_Count[i] > m_Shape[i])
+                if (m_DebugMode)
                 {
-                    lf_LargerThanError(i, "count", "shape");
+                    if (m_ConstantDims)
+                    {
+                        throw std::invalid_argument(
+                            "ERROR: isConstantShape (true) argument is invalid "
+                            "with empty start and count "
+                            "arguments in call to "
+                            "DefineVariable " +
+                            m_Name + "\n");
+                    }
                 }
-                if (m_Start[i] > m_Shape[i])
+
+                m_ShapeID = ShapeID::GlobalArray;
+            }
+        }
+        else if (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)
                 {
-                    lf_LargerThanError(i, "start", "shape");
+                    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
+        {
+            throw std::invalid_argument("ERROR: the "
+                                        "combination of shape, start and count "
+                                        "arguments is inconsistent, in call to "
+                                        "DefineVariable " +
+                                        m_Name + "\n");
         }
-
-        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)
+    else //(m_Shape.empty())
     {
-        m_ShapeID = ShapeID::JoinedArray;
+        if (m_Start.empty())
+        {
+            if (m_Count.empty())
+            {
+                m_ShapeID = ShapeID::GlobalValue;
+                m_SingleValue = true;
+            }
+            else if (m_Start.empty() && !m_Count.empty())
+            {
+                m_ShapeID = ShapeID::LocalArray;
+            }
+        }
+        else
+        {
+            throw std::invalid_argument(
+                "ERROR: if the "
+                "shape is empty, start must be empty as well, in call to "
+                "DefineVariable " +
+                m_Name + "\n");
+        }
     }
-    else if (!m_Shape.empty() &&
-             std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) > 1)
+
+    /* Extra checks for invalid settings */
+    if (m_DebugMode)
+        CheckDimsCommon("DefineVariable(" + m_Name + ")");
+}
+
+void VariableBase::CheckDimsCommon(const std::string hint) const
+{
+    if (m_ShapeID != ShapeID::LocalValue)
     {
-        throw std::invalid_argument("ERROR: variable can't have more than one "
-                                    "JoinedDim in shape argument, in call to "
-                                    "DefineVariable " +
-                                    m_Name + "\n");
+        if ((!m_Shape.empty() &&
+             std::count(m_Shape.begin(), m_Shape.end(), LocalValueDim) > 0) ||
+            (!m_Start.empty() &&
+             std::count(m_Start.begin(), m_Start.end(), LocalValueDim) > 0) ||
+            (!m_Count.empty() &&
+             std::count(m_Count.begin(), m_Count.end(), LocalValueDim) > 0))
+        {
+            throw std::invalid_argument("ERROR: LocalValueDim is only "
+                                        "allowed in a {LocalValueDim} "
+                                        "shape in call to " +
+                                        hint + "\n");
+        }
     }
-    else
+
+    if ((!m_Shape.empty() &&
+         std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) > 1) ||
+        (!m_Start.empty() &&
+         std::count(m_Start.begin(), m_Start.end(), JoinedDim) > 0) ||
+        (!m_Count.empty() &&
+         std::count(m_Count.begin(), m_Count.end(), JoinedDim) > 0))
     {
-        throw std::invalid_argument("ERROR: the "
-                                    "combination of shape, start and count "
-                                    "arguments is inconsistent, in call to "
-                                    "DefineVariable " +
-                                    m_Name + "\n");
+        throw std::invalid_argument("ERROR: JoinedDim is only allowed once in "
+                                    "Shape and cannot appear in Start/Count in "
+                                    "call to " +
+                                    hint + "\n");
     }
 }
 
-void VariableBase::CheckDims(const std::string hint) const
+void VariableBase::CheckDimsBeforeWrite(const std::string hint) const
 {
     if (m_ShapeID == ShapeID::GlobalArray)
     {
@@ -232,10 +302,12 @@ void VariableBase::CheckDims(const std::string hint) const
             throw std::invalid_argument(
                 "ERROR: GlobalArray variable " + m_Name +
                 " start and count dimensions must be defined by either "
-                "DefineVariable or a Selection " +
+                "DefineVariable or a Selection in call to " +
                 hint + "\n");
         }
     }
+
+    CheckDimsCommon(hint);
     // TODO need to think more exceptions here
 }
 
diff --git a/source/adios2/core/VariableBase.h b/source/adios2/core/VariableBase.h
index 424a93892bd4142e1db38622909afc7c99a1f5c6..61fc093dfd72f5860565edc4eb5da69d5ec72611 100644
--- a/source/adios2/core/VariableBase.h
+++ b/source/adios2/core/VariableBase.h
@@ -105,44 +105,51 @@ public:
     void SetStepSelection(const unsigned int startStep,
                           const unsigned int countStep);
 
-    void AddTransform(Transform &transform,
-                      const std::vector<std::string> &parametersVector);
+    /**
+     * Pushed a new transform to a sequence of transports
+     * @param transform reference to an object derived from the Transform class
+     * @param parameters transform specific parameters
+     * @return transformID handler
+     */
+    unsigned int AddTransform(Transform &transform,
+                              const Params &parameters = Params()) noexcept;
 
-    void AddTransform(Transform &transform,
-                      const Params &parametersVector = Params());
-
-    /** Apply current sequence of transforms defined by AddTransform */
-    virtual void ApplyTransforms() = 0;
+    void ResetTransformParameters(const unsigned int transformIndex,
+                                  const Params &parameters = Params());
 
     /** Clears out the transform sequence defined by AddTransform */
-    void ClearTransforms();
+    void ClearTransforms() noexcept;
 
-    /** 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:
-    const bool m_DebugMode = false;
-
-    void InitShapeType();
+    /** Apply current sequence of transforms defined by AddTransform */
+    virtual void ApplyTransforms() = 0;
 
     /** Transforms metadata info */
     struct TransformInfo
     {
         /** reference to object derived from Transform class */
-        Transform &Object;
+        Transform &Operator;
         /** parameters from AddTransform */
         Params Parameters;
         /** resulting sizes from transformation */
         Dims Sizes;
     };
 
-    /**
-     * Sequence determines application order, e.g.
-     * first Transforms[0] then Transforms[1]. Pointer used as
-     * reference (no memory management).
-     */
+    /** Registered transforms */
     std::vector<TransformInfo> m_TransformsInfo;
+
+    /** Self-check dims according to type, called right after DefineVariable and
+     * SetSelection.
+     * @param hint extra debugging info for the exception */
+    void CheckDimsCommon(const std::string hint) const;
+
+    /** Self-check dims according to type, called from Engine before Write
+     * @param hint extra debugging info for the exception */
+    void CheckDimsBeforeWrite(const std::string hint) const;
+
+private:
+    const bool m_DebugMode = false;
+
+    void InitShapeType();
 };
 
 } // end namespace
diff --git a/source/adios2/engine/dataman/DataManReader.cpp b/source/adios2/engine/dataman/DataManReader.cpp
index 54dde23fc04fa1dc657926d4152570caba84a6d2..a4d661fd3ace86496c321cf1ef1977bacc9b14ee 100644
--- a/source/adios2/engine/dataman/DataManReader.cpp
+++ b/source/adios2/engine/dataman/DataManReader.cpp
@@ -17,20 +17,19 @@ namespace adios2
 
 DataManReader::DataManReader(IO &io, const std::string &name,
                              const OpenMode openMode, MPI_Comm mpiComm)
-: Engine("DataManReader", io, name, openMode, mpiComm),
-    m_Man(mpiComm, true)
+: Engine("DataManReader", io, name, openMode, mpiComm), m_Man(mpiComm, true)
 {
     m_EndMessage = " in call to IO Open DataManReader " + m_Name + "\n";
     Init();
 }
 
-void DataManReader::SetCallBack(
+void DataManReader::SetCallback(
     std::function<void(const void *, std::string, std::string, std::string,
                        Dims)>
         callback)
 {
     m_CallBack = callback;
-//    m_Man.reg_callback(callback);
+    m_Man.SetCallback(callback);
 }
 
 void DataManReader::Close(const int transportIndex) {}
@@ -81,6 +80,7 @@ void DataManReader::Init()
                                  }) == s.end();
         };
 
+        /*
         json jmsg;
         for (auto &i : m_IO.m_Parameters)
         {
@@ -94,7 +94,19 @@ void DataManReader::Init()
             }
         }
         jmsg["stream_mode"] = "receiver";
-//        m_Man.add_stream(jmsg);
+        */
+
+        int n_Transports = 1;
+        std::vector<Params> para(n_Transports);
+
+        for (unsigned int i = 0; i < para.size(); i++)
+        {
+            para[i]["type"] = "wan";
+            para[i]["transport"] = "zmq";
+            para[i]["name"] = "stream";
+            para[i]["ipaddress"] = "127.0.0.1";
+        }
+        m_Man.OpenWANTransports("zmq", adios2::OpenMode::Read, para, true);
 
         std::string method_type;
         int num_channels = 0;
diff --git a/source/adios2/engine/dataman/DataManReader.h b/source/adios2/engine/dataman/DataManReader.h
index 1e8ef433fb9fdbbcf3f85a7b99877056df6acb71..c1c2c42d1403213e1530e1a14fac856f2d983a66 100644
--- a/source/adios2/engine/dataman/DataManReader.h
+++ b/source/adios2/engine/dataman/DataManReader.h
@@ -13,9 +13,9 @@
 
 #include <iostream> //std::cout << Needs to go
 
-#include "adios2/toolkit/transportman/DataMan/DataMan.h"
 #include "adios2/ADIOSConfig.h"
 #include "adios2/core/Engine.h"
+#include "adios2/toolkit/transportman/dataman/DataMan.h"
 
 namespace adios2
 {
@@ -45,7 +45,7 @@ public:
      * @param callback function (get) provided by the user to be applied in
      * DataMan
      */
-    void SetCallBack(std::function<void(const void *, std::string, std::string,
+    void SetCallback(std::function<void(const void *, std::string, std::string,
                                         std::string, Dims)>
                          callback);
 
diff --git a/source/adios2/engine/dataman/DataManWriter.cpp b/source/adios2/engine/dataman/DataManWriter.cpp
index 6e7357a44d92d48270dd398e0fca5b723be414c3..95132cc67110cfcbba2791ce6e4bbc4b1b9df5b6 100644
--- a/source/adios2/engine/dataman/DataManWriter.cpp
+++ b/source/adios2/engine/dataman/DataManWriter.cpp
@@ -20,8 +20,7 @@ namespace adios2
 
 DataManWriter::DataManWriter(IO &io, const std::string &name,
                              const OpenMode openMode, MPI_Comm mpiComm)
-: Engine("DataManWriter", io, name, openMode, mpiComm),
-    m_Man(mpiComm, true)
+: Engine("DataManWriter", io, name, openMode, mpiComm), m_Man(mpiComm, true)
 {
     m_EndMessage = ", in call to Open DataManWriter\n";
     Init();
@@ -33,15 +32,17 @@ void DataManWriter::SetCallBack(
         callback)
 {
     m_CallBack = callback;
-//    m_Man.reg_callback(callback);
+    //    m_Man.reg_callback(callback);
 }
 
-void DataManWriter::Advance(const float timeoutSeconds) {
-//    m_Man.flush();
+void DataManWriter::Advance(const float timeoutSeconds)
+{
+    //    m_Man.flush();
 }
 
-void DataManWriter::Close(const int transportIndex) {
-//    m_Man.flush();
+void DataManWriter::Close(const int transportIndex)
+{
+    //    m_Man.flush();
 }
 
 // PRIVATE functions below
@@ -102,39 +103,32 @@ void DataManWriter::Init()
                                  }) == s.end();
         };
 
-//        json jmsg;
-//        for (const auto &i : m_IO.m_Parameters)
-//        {
-//            if (lf_IsNumber(i.second))
-//            {
-//                jmsg[i.first] = std::stoi(i.second);
-//            }
-//            else
-//            {
-//                jmsg[i.first] = i.second;
-//            }
-//        }
-//        jmsg["stream_mode"] = "sender";
-//        m_Man.add_stream(jmsg);
+        //        json jmsg;
+        //        for (const auto &i : m_IO.m_Parameters)
+        //        {
+        //            if (lf_IsNumber(i.second))
+        //            {
+        //                jmsg[i.first] = std::stoi(i.second);
+        //            }
+        //            else
+        //            {
+        //                jmsg[i.first] = i.second;
+        //            }
+        //        }
+        //        jmsg["stream_mode"] = "sender";
+        //        m_Man.add_stream(jmsg);
 
         int n_Transports = 1;
         std::vector<Params> para(n_Transports);
 
-        std::cout << para.size() << std::endl;
-
-        for(unsigned int i=0; i<para.size(); i++){
+        for (unsigned int i = 0; i < para.size(); i++)
+        {
             para[i]["type"] = "wan";
             para[i]["transport"] = "zmq";
             para[i]["name"] = "stream";
             para[i]["ipaddress"] = "127.0.0.1";
         }
 
-        for(auto &i :para){
-            for(auto &j :i){
-                std::cout << j.first << " " << j.second << std::endl;
-            }
-        }
-
         m_Man.OpenWANTransports("zmq", adios2::OpenMode::Write, para, true);
 
         std::string method_type;
diff --git a/source/adios2/engine/dataman/DataManWriter.h b/source/adios2/engine/dataman/DataManWriter.h
index f087a7b74f52f5dc61449f9a988071b5176cd757..d1a840ab60a03bdf857c5b7033875f2329fedf78 100644
--- a/source/adios2/engine/dataman/DataManWriter.h
+++ b/source/adios2/engine/dataman/DataManWriter.h
@@ -14,9 +14,9 @@
 #include <iostream> //std::cout must be removed, only used for hello example
 #include <unistd.h> //sleep must be removed
 
-#include "adios2/toolkit/transportman/DataMan/DataMan.h"
 #include "adios2/ADIOSConfig.h"
 #include "adios2/core/Engine.h"
+#include "adios2/toolkit/transportman/dataman/DataMan.h"
 
 namespace adios2
 {
@@ -25,8 +25,6 @@ class DataManWriter : public Engine
 {
 
 public:
-    using json = nlohmann::json;
-
     DataManWriter(IO &io, const std::string &name, const OpenMode openMode,
                   MPI_Comm mpiComm);
 
diff --git a/source/adios2/engine/dataman/DataManWriter.tcc b/source/adios2/engine/dataman/DataManWriter.tcc
index e86cf3a53a537763f9937de4ad03f6161685acbe..05e1b816b64ef91e11bef9a6f0430febac6aa3f6 100644
--- a/source/adios2/engine/dataman/DataManWriter.tcc
+++ b/source/adios2/engine/dataman/DataManWriter.tcc
@@ -40,7 +40,8 @@ void DataManWriter::DoWriteCommon(Variable<T> &variable, const T *values)
         variable.m_Start.assign(variable.m_Count.size(), 0);
     }
 
-    json jmsg;
+    std::cout << "DoWriteCommon begin" << std::endl;
+    nlohmann::json jmsg;
     jmsg["doid"] = m_Name;
     jmsg["var"] = variable.m_Name;
     jmsg["dtype"] = GetType<T>();
@@ -48,7 +49,12 @@ void DataManWriter::DoWriteCommon(Variable<T> &variable, const T *values)
     jmsg["varshape"] = variable.m_Shape;
     jmsg["offset"] = variable.m_Start;
     jmsg["timestep"] = 0;
-//    m_Man.put(values, jmsg);
+    jmsg["bytes"] =
+        std::accumulate(variable.m_Shape.begin(), variable.m_Shape.end(),
+                        sizeof(T), std::multiplies<size_t>());
+
+    std::cout << "DoWriteCommon end" << std::endl;
+    m_Man.WriteWAN(values, jmsg);
 
     if (m_DoMonitor)
     {
diff --git a/source/adios2/helper/adiosFunctions.h b/source/adios2/helper/adiosFunctions.h
index af3e98f18f93c75e745c2903ce5f7ab4e98c662f..e088875c7a4ec65bdbbed370a710b71dc834c71f 100644
--- a/source/adios2/helper/adiosFunctions.h
+++ b/source/adios2/helper/adiosFunctions.h
@@ -12,9 +12,10 @@
 #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/adiosMPIFunctions.h" //MPI functions (Bcast, send/recv)
+#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
diff --git a/source/adios2/helper/adiosMPIFunctions.cpp b/source/adios2/helper/adiosMPIFunctions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bd550b00ef5c2e1fb0f4baaa9f83a3a8da49cbd3
--- /dev/null
+++ b/source/adios2/helper/adiosMPIFunctions.cpp
@@ -0,0 +1,46 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMPIFunctions.cpp
+ *
+ *  Created on: Jul 20, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+#include "adiosMPIFunctions.h"
+
+#include "adios2/ADIOSMPI.h"
+#include "adios2/ADIOSTypes.h"
+
+namespace adios2
+{
+
+std::string BroadcastString(const std::string &input, MPI_Comm mpiComm,
+                            const int rankSource)
+{
+    int rank;
+    MPI_Comm_rank(mpiComm, &rank);
+    size_t length = 0;
+    std::string output;
+
+    if (rank == rankSource)
+    {
+        length = input.size();
+        MPI_Bcast(&length, 1, ADIOS2_MPI_SIZE_T, rankSource, mpiComm);
+
+        MPI_Bcast(const_cast<char *>(input.data()), length, MPI_CHAR,
+                  rankSource, mpiComm);
+
+        return input;
+    }
+    else
+    {
+        MPI_Bcast(&length, 1, ADIOS2_MPI_SIZE_T, rankSource, mpiComm);
+        output.resize(length);
+        MPI_Bcast(const_cast<char *>(output.data()), length, MPI_CHAR,
+                  rankSource, mpiComm);
+    }
+    return output;
+}
+
+} // end namespace adios2
diff --git a/source/adios2/helper/adiosMPIFunctions.h b/source/adios2/helper/adiosMPIFunctions.h
new file mode 100644
index 0000000000000000000000000000000000000000..a79345d6af4b735a57f718887c6d21f38b8878bb
--- /dev/null
+++ b/source/adios2/helper/adiosMPIFunctions.h
@@ -0,0 +1,36 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * adiosMPIFunctions.h : collection of MPI functions used across adios2
+ *
+ *  Created on: Jul 20, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_HELPER_ADIOMPIFUNCTIONS_H_
+#define ADIOS2_HELPER_ADIOMPIFUNCTIONS_H_
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <string>
+/// \endcond
+
+#include "adios2/ADIOSMPICommOnly.h"
+
+namespace adios2
+{
+
+/**
+ * rankSource: owns a string and broadcast to all other ranks
+ * Others: receive std::vector<char> and copy to a string
+ * @param mpiComm MPI communicator defining all ranks and size domain
+ * @param input string input from rankSource
+ * @param rankSource rank that broadcast the string, (default = 0)
+ * @return input contents for each rank
+ */
+std::string BroadcastString(const std::string &input, MPI_Comm mpiComm,
+                            const int rankSource = 0);
+
+} // end namespace adios2
+
+#endif /* ADIOS2_HELPER_ADIOMPIFUNCTIONS_H_ */
diff --git a/source/adios2/helper/adiosMemory.h b/source/adios2/helper/adiosMemory.h
index 20ab7739562cd8cb7650ae0f136020f35f1ffe72..ad5dd0116d123da9a885c99ca940efa1e825b969 100644
--- a/source/adios2/helper/adiosMemory.h
+++ b/source/adios2/helper/adiosMemory.h
@@ -83,6 +83,14 @@ void MemcpyToBufferThreads(std::vector<char> &buffer, size_t &position,
                            const T *source, size_t size,
                            const unsigned int threads = 1);
 
+/**
+ * Cast an element to uint64 and insert to a buffer
+ * @param buffer data destination
+ * @param element to be added to buffer
+ */
+template <class T>
+void InsertU64(std::vector<char> &buffer, const T element) noexcept;
+
 } // end namespace adios
 
 #include "adiosMemory.inl"
diff --git a/source/adios2/helper/adiosMemory.inl b/source/adios2/helper/adiosMemory.inl
index ee50425e2b1083eb2e076d8579b631de49b406eb..0eaa2662a765b1e8e5523c624d5ce853b3194a10 100644
--- a/source/adios2/helper/adiosMemory.inl
+++ b/source/adios2/helper/adiosMemory.inl
@@ -25,7 +25,7 @@ namespace adios2
 
 template <class T>
 void InsertToBuffer(std::vector<char> &buffer, const T *source,
-                    const std::size_t elements) noexcept
+                    const size_t elements) noexcept
 {
     const char *src = reinterpret_cast<const char *>(source);
     buffer.insert(buffer.end(), src, src + elements * sizeof(T));
@@ -159,6 +159,13 @@ void MemcpyToBufferThreads(std::vector<char> &buffer, size_t &position,
     }
 }
 
+template <class T>
+void InsertU64(std::vector<char> &buffer, const T element) noexcept
+{
+    const uint64_t element64 = static_cast<const uint64_t>(element);
+    InsertToBuffer(buffer, &element64);
+}
+
 } // end namespace
 
 #endif /* ADIOS2_HELPER_ADIOSMEMORY_INL_ */
diff --git a/source/adios2/helper/adiosString.cpp b/source/adios2/helper/adiosString.cpp
index 21e4bb138c253a69b78788955df28a04ef7166b1..f294951ab6021ba1e1bd7cda44859bbea5617caa 100644
--- a/source/adios2/helper/adiosString.cpp
+++ b/source/adios2/helper/adiosString.cpp
@@ -130,25 +130,103 @@ void SetParameterValue(const std::string key, const Params &parameters,
 }
 
 std::string GetParameter(const std::string key, const Params &params,
-                              const bool isMandatory,
-                              const bool debugMode, const std::string hint){
-        std::string value;
-        auto itParameter = params.find(key);
-        if (itParameter == params.end())
+                         const bool isMandatory, const bool debugMode,
+                         const std::string hint)
+{
+    std::string value;
+    auto itParameter = params.find(key);
+    if (itParameter == params.end())
+    {
+        if (debugMode && isMandatory)
         {
-            if (debugMode && isMandatory)
-            {
-                throw std::invalid_argument(
-                    "ERROR: mandatory parameter " + key +
-					" not found, " + hint );
-            }
+            throw std::invalid_argument("ERROR: mandatory parameter " + key +
+                                        " not found, " + hint);
+        }
+    }
+    else
+    {
+        value = itParameter->second;
+    }
+    return value;
+}
+
+void SetParameterValueInt(const std::string key, const Params &parameters,
+                          int &value, const bool debugMode,
+                          const std::string hint)
+{
+    auto itKey = parameters.find(key);
+
+    if (itKey == parameters.end())
+    {
+        return;
+    }
+
+    if (debugMode)
+    {
+        try
+        {
+            value = std::stoi(itKey->second);
+        }
+        catch (...)
+        {
+            std::throw_with_nested(std::invalid_argument(
+                "ERROR: could not cast " + itKey->second +
+                " to int from key parameter: " + itKey->first + ", " + hint));
+        }
+    }
+    else
+    {
+        value = std::stoi(itKey->second);
+    }
+}
+
+double StringToDouble(const std::string value, const bool debugMode,
+                      const std::string hint)
+{
+    double valueDouble = -1.;
+
+    if (debugMode)
+    {
+        try
+        {
+            valueDouble = std::stod(value);
         }
-        else
+        catch (...)
         {
-            value = itParameter->second;
+            std::throw_with_nested(std::invalid_argument(
+                "ERROR: could not cast " + value + " to double, " + hint));
         }
-        return value;
     }
+    else
+    {
+        valueDouble = std::stod(value);
+    }
+    return valueDouble;
+}
 
+unsigned int StringToUInt(const std::string value, const bool debugMode,
+                          const std::string hint)
+{
+    unsigned int valueUInt = 0;
+
+    if (debugMode)
+    {
+        try
+        {
+            valueUInt = static_cast<unsigned int>(std::stoul(value));
+        }
+        catch (...)
+        {
+            std::throw_with_nested(
+                std::invalid_argument("ERROR: could not cast " + value +
+                                      " to unsigned int, " + hint));
+        }
+    }
+    else
+    {
+        valueUInt = static_cast<unsigned int>(std::stoul(value));
+    }
+    return valueUInt;
+}
 
 } // end namespace adios
diff --git a/source/adios2/helper/adiosString.h b/source/adios2/helper/adiosString.h
index 45952bb6cd789c8b6aab7277787f7f83b87540d4..e323797e8a18ebaa7ae3bcec78875288a1e10476 100644
--- a/source/adios2/helper/adiosString.h
+++ b/source/adios2/helper/adiosString.h
@@ -69,10 +69,41 @@ void SetParameterValue(const std::string key, const Params &parameters,
                        std::string &value) noexcept;
 
 std::string GetParameter(const std::string key, const adios2::Params &params,
-                              const bool isMandatory,
-                              const bool debugMode, const std::string hint);
-}
+                         const bool isMandatory, const bool debugMode,
+                         const std::string hint);
+/**
+ * Sets int value if found in parameters for input key
+ * @param key input
+ * @param parameters map with key: field, value: value
+ * @param value to be modified if key is found in parameters
+ * @param debugMode check for string conversion
+ * @param hint passed for extra debugging info if exception is thrown
+ */
+void SetParameterValueInt(const std::string key, const Params &parameters,
+                          int &value, const bool debugMode,
+                          const std::string hint);
 
+/**
+ * function that cast a string to a double verifying validity of the cast with
+ * exceptions in debugMode
+ * @param value string to be casted
+ * @param debugMode check for string conversion
+ * @param hint passed for extra debugging info if exception is thrown
+ * @return value as a double
+ */
+double StringToDouble(const std::string value, const bool debugMode,
+                      const std::string hint);
 
+/**
+ * function that cast a string to unsigned int verifying validity of the cast
+ * with exceptions in debugMode
+ * @param value string to be casted
+ * @param debugMode check for string conversion
+ * @param hint passed for extra debugging info if exception is thrown
+ * @return value as unsigned int
+ */
+unsigned int StringToUInt(const std::string value, const bool debugMode,
+                          const std::string hint);
+}
 
 #endif /* ADIOS2_HELPER_ADIOSSTRING_H_ */
diff --git a/source/adios2/helper/adiosSystem.cpp b/source/adios2/helper/adiosSystem.cpp
index 8e0b967c5e0d07b8620c29dce7beadaf8693a2f6..233f2d096cffde6bb1b482c75bcdcbbc5a36ee72 100644
--- a/source/adios2/helper/adiosSystem.cpp
+++ b/source/adios2/helper/adiosSystem.cpp
@@ -9,7 +9,7 @@
  */
 #include "adiosSystem.h"
 
-#include <ctime> //std::ctime
+#include <ctime>
 
 #include <chrono> //system_clock, now
 
@@ -19,6 +19,11 @@
 #include "adios2/ADIOSTypes.h"
 #include "adios2/helper/adiosString.h"
 
+// remove ctime warning on Windows
+#ifdef _WIN32
+#pragma warning(disable : 4996)
+#endif
+
 namespace adios2
 {
 
@@ -38,44 +43,7 @@ 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));
-}
-
-std::string BroadcastString(const std::string &input, MPI_Comm mpiComm)
-{
-    std::string receivedInput;
-    size_t characterCount = 0;
-
-    int rank;
-    MPI_Comm_rank(mpiComm, &rank);
-
-    if (rank == 0) // sender
-    {
-        characterCount = input.size();
-
-        // broadcast size for allocation
-        MPI_Bcast(&characterCount, 1, ADIOS2_MPI_SIZE_T, 0, mpiComm);
-
-        // broadcast contents
-        MPI_Bcast(const_cast<char *>(input.c_str()),
-                  static_cast<int>(characterCount), MPI_CHAR, 0, mpiComm);
-
-        return input;
-    }
-    else // receivers
-    {
-        // receive size
-        MPI_Bcast(&characterCount, 1, ADIOS2_MPI_SIZE_T, 0, mpiComm);
-
-        // allocate receiver
-        std::vector<char> stringReceiver(characterCount);
-        MPI_Bcast(stringReceiver.data(), static_cast<int>(characterCount),
-                  MPI_CHAR, 0, mpiComm);
-
-        receivedInput.assign(stringReceiver.begin(), stringReceiver.end());
-    }
-
-    return receivedInput;
+    return std::string(ctime(&now));
 }
 
 } // end namespace adios
diff --git a/source/adios2/helper/adiosSystem.h b/source/adios2/helper/adiosSystem.h
index 844e73e47fbb4fbaed5772f28abb9a2569d1634f..650cba40987401a9452304de0a7e9d7b574307fd 100644
--- a/source/adios2/helper/adiosSystem.h
+++ b/source/adios2/helper/adiosSystem.h
@@ -17,8 +17,6 @@
 #include <vector>
 /// \endcond
 
-#include "adios2/ADIOSMPICommOnly.h"
-
 namespace adios2
 {
 
@@ -43,15 +41,6 @@ bool IsLittleEndian() noexcept;
  */
 std::string LocalTimeDate() noexcept;
 
-/**
- * Rank 0: opens file, dumps contents string and broadcast.
- * Others: receive std::vector<char> and copy to a string
- * @param fileName
- * @param mpiComm
- * @return fileContents as a single string
- */
-std::string BroadcastString(const std::string &input, MPI_Comm mpiComm);
-
 } // end namespace adios
 
 #endif /* ADIOS2_HELPER_ADIOSSYSTEM_H_ */
diff --git a/source/adios2/helper/adiosXML.cpp b/source/adios2/helper/adiosXML.cpp
index 0045c4de336d3ec8b71fb5c85dbd1b5729ad7ec5..25bae1343c05e09b5776f9ca7af4ecf07f3ae6ae 100644
--- a/source/adios2/helper/adiosXML.cpp
+++ b/source/adios2/helper/adiosXML.cpp
@@ -6,6 +6,7 @@
  *
  *  Created on: May 17, 2017
  *      Author: William F Godoy godoywf@ornl.gov
+ *              Chuck Atkins chuck.atkins@kitware.com
  */
 
 #include "adiosXML.h"
@@ -16,6 +17,7 @@
 
 #include "adios2/ADIOSMPI.h"
 #include "adios2/ADIOSTypes.h"
+#include "adios2/helper/adiosMPIFunctions.h"
 #include "adios2/helper/adiosString.h"
 
 #include <pugixml.hpp>
@@ -23,148 +25,173 @@
 namespace adios2
 {
 
-Params InitParametersXML(pugi::xml_node node, bool debugMode)
+Params InitParametersXML(const pugi::xml_node &node, const bool debugMode)
 {
     Params params;
-    for (pugi::xml_node paramNode : node.children("parameter"))
+    for (const pugi::xml_node paramNode : node.children("parameter"))
     {
-        pugi::xml_attribute attrKey = paramNode.attribute("key");
-        if (!attrKey)
+        const pugi::xml_attribute key = paramNode.attribute("key");
+        if (debugMode)
         {
-            if (debugMode)
+            if (!key)
             {
                 throw std::invalid_argument("ERROR: XML: No \"key\" attribute "
-                                            "found on <parameter> element.");
+                                            "found on <parameter> element, in "
+                                            "call to ADIOS constructor\n");
             }
-            continue;
         }
 
-        pugi::xml_attribute attrValue = paramNode.attribute("value");
-        if (!attrValue)
+        const pugi::xml_attribute value = paramNode.attribute("value");
+
+        if (debugMode)
         {
-            if (debugMode)
+            if (!value)
             {
+
                 throw std::invalid_argument("ERROR: XML: No \"value\" "
                                             "attribute found on <parameter> "
-                                            "element.");
+                                            "element,  for key " +
+                                            std::string(key.value()) +
+                                            ", in call to ADIOS constructor\n");
+                continue;
             }
-            continue;
         }
 
-        params.emplace(attrKey.value(), attrValue.value());
+        params.emplace(key.value(), value.value());
     }
     return params;
 }
 
-void InitIOXML(const pugi::xml_node ioNode, const MPI_Comm mpiComm,
+void InitIOXML(const pugi::xml_node &ioNode, MPI_Comm mpiComm,
                const bool debugMode,
-               std::vector<std::shared_ptr<Transform>> &transforms,
+               std::map<std::string, std::shared_ptr<Transform>> &transforms,
                std::map<std::string, IO> &ios)
 {
     // Extract <io name=""> attribute
-    pugi::xml_attribute nameAttr = ioNode.attribute("name");
+    const pugi::xml_attribute nameAttr = ioNode.attribute("name");
     if (!nameAttr)
     {
         if (debugMode)
         {
-            throw std::invalid_argument(
-                "ERROR: XML: No \"name\" attribute found on <io> element.");
+            throw std::invalid_argument("ERROR: XML: No \"name\" attribute "
+                                        "found on <io> element, in call to "
+                                        "ADIOS constructor.\n");
         }
         return;
     }
-    std::string ioName = nameAttr.value();
+    const std::string ioName = nameAttr.value();
 
     // Build the IO object
     auto ioIt = ios.emplace(ioName, IO(ioName, mpiComm, true, debugMode));
     IO &io = ioIt.first->second;
 
     // Extract <engine> element
-    pugi::xml_node engineNode = ioNode.child("engine");
-    if (!engineNode)
+    if (debugMode)
     {
-        throw std::invalid_argument(
-            "ERROR: XML: No <engine> element found in <io> element.");
+        unsigned int count = 0;
+
+        for (const pugi::xml_node engineNode : ioNode.children("engine"))
+        {
+            ++count;
+            if (count == 2)
+            {
+                throw std::invalid_argument(
+                    "ERROR: XML only one <engine> element "
+                    "can exist inside an <io> element from io " +
+                    ioName + ", in call to ADIOS constructor\n");
+            }
+        }
     }
-    pugi::xml_attribute engineTypeAttr = engineNode.attribute("type");
-    if (!engineTypeAttr)
+
+    const pugi::xml_node engineNode = ioNode.child("engine");
+    if (engineNode)
     {
-        throw std::invalid_argument(
-            "ERROR: XML: No \"type\" attribute found on <engine> element.");
+        const pugi::xml_attribute engineTypeAttr = engineNode.attribute("type");
+
+        if (debugMode)
+        {
+            if (!engineTypeAttr)
+            {
+                throw std::invalid_argument(
+                    "ERROR: XML: No \"type\" attribute "
+                    "found on <engine> element, in call to "
+                    "ADIOS constructor");
+            }
+        }
+
+        io.SetEngine(engineTypeAttr.value());
     }
-    io.SetEngine(engineTypeAttr.value());
 
     // Process <engine> parameters
     io.SetParameters(InitParametersXML(engineNode, debugMode));
 
     // Extract and process <transport> elements
-    for (pugi::xml_node transportNode : ioNode.children("transport"))
+    for (const pugi::xml_node transportNode : ioNode.children("transport"))
     {
-        pugi::xml_attribute typeAttr = transportNode.attribute("type");
-        if (!typeAttr)
+        const pugi::xml_attribute typeXMLAttribute =
+            transportNode.attribute("type");
+
+        if (debugMode)
         {
-            if (debugMode)
+            if (!typeXMLAttribute)
             {
+
                 throw std::invalid_argument("ERROR: XML: No \"type\" attribute "
-                                            "found on <transport> element.");
+                                            "found on <transport> element, in "
+                                            "call to ADIOS constructor\n");
             }
-            continue;
         }
-        io.AddTransport(typeAttr.value(),
+
+        io.AddTransport(typeXMLAttribute.value(),
                         InitParametersXML(transportNode, debugMode));
     }
 }
 
-void InitXML(const std::string configXML, const MPI_Comm mpiComm,
+void InitXML(const std::string configXML, MPI_Comm mpiComm,
              const bool debugMode,
-             std::vector<std::shared_ptr<Transform>> &transforms,
+             std::map<std::string, std::shared_ptr<Transform>> &transforms,
              std::map<std::string, IO> &ios)
 {
     int mpiRank;
     MPI_Comm_rank(mpiComm, &mpiRank);
     std::string fileContents;
-    unsigned long long len;
 
     // Read the file on rank 0 and broadcast it to everybody else
     if (mpiRank == 0)
     {
         fileContents = FileToString(configXML);
-        len = static_cast<unsigned long long>(fileContents.size());
-    }
-    MPI_Bcast(&len, 1, MPI_UNSIGNED_LONG, 0, mpiComm);
-    if (mpiRank != 0)
-    {
-        fileContents.resize(len);
     }
-    MPI_Bcast(const_cast<char *>(fileContents.data()), len, MPI_CHAR, 0,
-              mpiComm);
+
+    fileContents = BroadcastString(fileContents, mpiComm);
 
     pugi::xml_document doc;
     auto parse_result = doc.load_buffer_inplace(
         const_cast<char *>(fileContents.data()), fileContents.size());
-    if (!parse_result)
+
+    if (debugMode)
     {
-        if (debugMode)
+        if (!parse_result)
         {
             throw std::invalid_argument(
-                std::string("ERROR: XML: Parse error: ") +
-                parse_result.description());
+                "ERROR: XML: parse error in file " + configXML +
+                " description: " + std::string(parse_result.description()) +
+                ", in call to ADIOS constructor\n");
         }
-        return;
     }
 
-    pugi::xml_node configNode = doc.child("adios-config");
-    if (!configNode)
+    const pugi::xml_node configNode = doc.child("adios-config");
+
+    if (debugMode)
     {
-        if (debugMode)
+        if (!configNode)
         {
             throw std::invalid_argument(
-                "ERROR: XML: No <adios-config> element found");
+                "ERROR: XML: No <adios-config> element found in file " +
+                configXML + ", in call to ADIOS constructor\n");
         }
-        return;
     }
 
-    ios.clear();
-    for (pugi::xml_node ioNode : configNode.children("io"))
+    for (const pugi::xml_node ioNode : configNode.children("io"))
     {
         InitIOXML(ioNode, mpiComm, debugMode, transforms, ios);
     }
diff --git a/source/adios2/helper/adiosXML.h b/source/adios2/helper/adiosXML.h
index 055c14605f43259a71783c4727c015ea4a34d476..0746eb47708041c3b19aef93a1aa3ee3c11b98fd 100644
--- a/source/adios2/helper/adiosXML.h
+++ b/source/adios2/helper/adiosXML.h
@@ -16,7 +16,6 @@
 #include <memory> //std::shared_ptr
 #include <string>
 #include <utility> //std::pair
-#include <vector>
 /// \endcond
 
 #include "adios2/core/IO.h"
@@ -34,9 +33,9 @@ namespace adios2
  * @param transforms
  * @param ios
  */
-void InitXML(const std::string configXML, const MPI_Comm mpiComm,
+void InitXML(const std::string configXML, MPI_Comm mpiComm,
              const bool debugMode,
-             std::vector<std::shared_ptr<Transform>> &transforms,
+             std::map<std::string, std::shared_ptr<Transform>> &transforms,
              std::map<std::string, IO> &ios);
 }
 
diff --git a/source/adios2/mpidummy.cpp b/source/adios2/mpidummy.cpp
index 75f76646a12d8c80e149ca11e2cf5be46d94c7d2..c97938e95d78063c73195ac0cacd2275335f516c 100644
--- a/source/adios2/mpidummy.cpp
+++ b/source/adios2/mpidummy.cpp
@@ -26,7 +26,6 @@
 #define open64 open
 #endif
 */
-
 #include <cinttypes>
 #include <cstdio>
 #include <cstring>
@@ -34,6 +33,12 @@
 #include <chrono>
 #include <string>
 
+// remove warnings on Windows
+#ifdef _WIN32
+#pragma warning(disable : 4996) // fopen
+#pragma warning(disable : 4477) // strcpy, sprintf
+#endif
+
 namespace adios2
 {
 
@@ -296,7 +301,7 @@ int MPI_File_open(MPI_Comm /*comm*/, const char *filename, int amode,
     }
     mode += "b";
 
-    *fh = fopen(filename, mode.c_str());
+    *fh = std::fopen(filename, mode.c_str());
     if (!*fh)
     {
         std::snprintf(mpierrmsg, MPI_MAX_ERROR_STRING, "File not found: %s",
@@ -310,10 +315,10 @@ int MPI_File_close(MPI_File *fh) { return fclose(*fh); }
 
 int MPI_File_get_size(MPI_File fh, MPI_Offset *size)
 {
-    long curpos = ftell(fh);
+    long curpos = std::ftell(fh);
     fseek(fh, 0, SEEK_END); // go to end, returned is the size in bytes
-    long endpos = ftell(fh);
-    fseek(fh, curpos, SEEK_SET); // go back where we were
+    long endpos = std::ftell(fh);
+    std::fseek(fh, curpos, SEEK_SET); // go back where we were
     *size = static_cast<MPI_Offset>(endpos);
     // printf("MPI_File_get_size: fh=%d, size=%lld\n", fh, *size);
     return MPI_SUCCESS;
@@ -325,13 +330,14 @@ int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype,
     // FIXME: int count can read only 2GB (*datatype size) array at max
     size_t bytes_to_read = static_cast<size_t>(count) * datatype;
     size_t bytes_read;
-    bytes_read = fread(buf, 1, bytes_to_read, fh);
+    bytes_read = std::fread(buf, 1, bytes_to_read, fh);
     if (bytes_read != bytes_to_read)
     {
         std::snprintf(mpierrmsg, MPI_MAX_ERROR_STRING,
-                      "could not read %" PRId64 " bytes. read only: %" PRId64
+                      "could not read %llu bytes. read only: %llu"
                       "\n",
-                      bytes_to_read, bytes_read);
+                      (unsigned long long)bytes_to_read,
+                      (unsigned long long)bytes_read);
         return -2;
     }
     *status = bytes_read;
@@ -342,7 +348,7 @@ int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype,
 
 int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence)
 {
-    return fseek(fh, offset, whence) == MPI_SUCCESS;
+    return std::fseek(fh, offset, whence) == MPI_SUCCESS;
 }
 
 int MPI_Get_count(const MPI_Status *status, MPI_Datatype, int *count)
diff --git a/source/adios2/mpidummy.h b/source/adios2/mpidummy.h
index f4607ea204c313de54f37a1a8b0a2f484fc50ade..5457f0dd7788c55653787571271a4294878d9079 100644
--- a/source/adios2/mpidummy.h
+++ b/source/adios2/mpidummy.h
@@ -14,9 +14,6 @@
 #include <cstdint>
 #include <cstdio>
 
-/// \cond EXCLUDE_FROM_DOXYGEN
-/// \endcond
-
 namespace adios2
 {
 
diff --git a/source/adios2/toolkit/capsule/Capsule.h b/source/adios2/toolkit/capsule/Capsule.h
index 09ba7fd4c3daf7b992decd735c9a68a37442d142..0534e75ec69912a4b012befb0249048c9fad2a12 100644
--- a/source/adios2/toolkit/capsule/Capsule.h
+++ b/source/adios2/toolkit/capsule/Capsule.h
@@ -61,8 +61,8 @@ public:
 
     size_t GetAvailableDataSize() const;
 
-    virtual void ResizeData(size_t size);     ///< resize data buffer
-    virtual void ResizeMetadata(size_t size); ///< resize metadata buffer
+    virtual void ResizeData(const size_t size);     ///< resize data buffer
+    virtual void ResizeMetadata(const size_t size); ///< resize metadata buffer
 
 protected:
     const bool m_DebugMode = false; ///< true: extra exception checks
diff --git a/source/adios2/toolkit/capsule/heap/STLVector.cpp b/source/adios2/toolkit/capsule/heap/STLVector.cpp
index 57daca380aa539c9f7b765617bee9fb71132717e..5221f00faa3245c66a14d3dd44708d34a40b1f81 100644
--- a/source/adios2/toolkit/capsule/heap/STLVector.cpp
+++ b/source/adios2/toolkit/capsule/heap/STLVector.cpp
@@ -41,11 +41,12 @@ void STLVector::ResizeData(const size_t size)
         {
             m_Data.resize(size);
         }
-        catch (std::bad_alloc &e)
+        catch (...)
         {
-            throw std::runtime_error("ERROR: bad_alloc detected when resizing "
-                                     "data buffer with size " +
-                                     std::to_string(size) + "\n");
+            std::throw_with_nested(
+                std::runtime_error("ERROR: possible overflow when resizing "
+                                   "data buffer with size " +
+                                   std::to_string(size) + "\n"));
         }
     }
     else
@@ -62,11 +63,12 @@ void STLVector::ResizeMetadata(const size_t size)
         {
             m_Metadata.resize(size);
         }
-        catch (std::bad_alloc &e)
+        catch (...)
         {
-            throw std::runtime_error("ERROR: bad_alloc detected when resizing "
-                                     "metadata buffer with size " +
-                                     std::to_string(size) + "\n");
+            std::throw_with_nested(
+                std::runtime_error("ERROR: possible overflow when resizing "
+                                   "metadata buffer with size " +
+                                   std::to_string(size) + "\n"));
         }
     }
     else
diff --git a/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp b/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp
index 62486da1d39580ba1e211928cf9a1bbb5ca9cf60..21ba4efcd636c739cfa8a3517d03f4d7db9e14c5 100644
--- a/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp
+++ b/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp
@@ -2,10 +2,10 @@
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
  *
- * ShmSystemV.cpp
+ * ShmSystemV.cpp : implementation of ShmSystemV class
  *
  *  Created on: Dec 22, 2016
- *      Author: wfg
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #include "ShmSystemV.h"
diff --git a/source/adios2/toolkit/capsule/shmem/ShmSystemV.h b/source/adios2/toolkit/capsule/shmem/ShmSystemV.h
index df997af7bf10a2a6cd46939c3fc544ffe15e89e6..b1bf0f48ea2c28a77c9571137c7e66d803b7eb09 100644
--- a/source/adios2/toolkit/capsule/shmem/ShmSystemV.h
+++ b/source/adios2/toolkit/capsule/shmem/ShmSystemV.h
@@ -1,6 +1,12 @@
 /*
  * Distributed under the OSI-approved Apache License, Version 2.0.  See
  * accompanying file Copyright.txt for details.
+ *
+ * ShmSystemV.h : ShmSystem class as a thin wrapper to a shared memory capsule
+ *                using POSIX SystemV
+ *
+ * Created on: Dec 22, 2016
+ *      Author: William F Godoy godoywf@ornl.gov
  */
 
 #ifndef ADIOS2_TOOLKIT_CAPSULE_SHMEM_SHMSYSTEMV_H_
diff --git a/source/adios2/toolkit/format/bp1/BP1Base.cpp b/source/adios2/toolkit/format/bp1/BP1Base.cpp
index 387366b43fffc86c6736aa54d8799d3255dfd288..ecc990f38bef44f499eb417f0e9e609845ae5a6c 100644
--- a/source/adios2/toolkit/format/bp1/BP1Base.cpp
+++ b/source/adios2/toolkit/format/bp1/BP1Base.cpp
@@ -170,6 +170,8 @@ void BP1Base::InitParameterBufferGrowth(const std::string value)
     if (m_DebugMode)
     {
         bool success = true;
+        std::string description;
+
         try
         {
             m_GrowthFactor = std::stof(value);
@@ -177,6 +179,7 @@ void BP1Base::InitParameterBufferGrowth(const std::string value)
         catch (std::exception &e)
         {
             success = false;
+            description = std::string(e.what());
         }
 
         if (!success || m_GrowthFactor <= 1.f)
@@ -184,7 +187,8 @@ void BP1Base::InitParameterBufferGrowth(const std::string value)
             throw std::invalid_argument(
                 "ERROR: BufferGrowthFactor value "
                 "can't be less or equal than 1 (default = 1.5), or couldn't "
-                "convert number, in call to Open\n");
+                "convert number,\n additional description:" +
+                description + "\n, in call to Open\n");
         }
     }
     else
@@ -195,15 +199,14 @@ void BP1Base::InitParameterBufferGrowth(const std::string value)
 
 void BP1Base::InitParameterInitBufferSize(const std::string value)
 {
-    const std::string errorMessage(
-        "ERROR: wrong value for InitialBufferSize, it must be larger than "
-        "16Kb (minimum default), in call to Open\n");
-
     if (m_DebugMode)
     {
         if (value.size() < 2)
         {
-            throw std::invalid_argument(errorMessage);
+            throw std::invalid_argument(
+                "ERROR: wrong value for InitialBufferSize, it must be larger "
+                "than "
+                "16Kb (minimum default), in call to Open\n");
         }
     }
 
@@ -215,6 +218,8 @@ void BP1Base::InitParameterInitBufferSize(const std::string value)
     if (m_DebugMode)
     {
         bool success = true;
+        std::string description;
+
         try
         {
             bufferSize = static_cast<size_t>(std::stoul(number) * factor);
@@ -222,11 +227,16 @@ void BP1Base::InitParameterInitBufferSize(const std::string value)
         catch (std::exception &e)
         {
             success = false;
+            description = std::string(e.what());
         }
 
         if (!success || bufferSize < DefaultInitialBufferSize) // 16384b
         {
-            throw std::invalid_argument(errorMessage);
+            throw std::invalid_argument(
+                "ERROR: wrong value for InitialBufferSize, it must be larger "
+                "than "
+                "16Kb (minimum default), additional description: " +
+                description + " in call to Open\n");
         }
     }
     else
@@ -239,17 +249,15 @@ void BP1Base::InitParameterInitBufferSize(const std::string value)
 
 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);
+            throw std::invalid_argument(
+                "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");
         }
     }
 
@@ -260,6 +268,8 @@ void BP1Base::InitParameterMaxBufferSize(const std::string value)
     if (m_DebugMode)
     {
         bool success = true;
+        std::string description;
+
         try
         {
             m_MaxBufferSize = static_cast<size_t>(std::stoul(number) * factor);
@@ -267,11 +277,17 @@ void BP1Base::InitParameterMaxBufferSize(const std::string value)
         catch (std::exception &e)
         {
             success = false;
+            description = std::string(e.what());
         }
 
         if (!success || m_MaxBufferSize < 16 * 1024) // 16384b
         {
-            throw std::invalid_argument(errorMessage);
+            throw std::invalid_argument(
+                "ERROR: couldn't convert value of max_buffer_size IO "
+                "SetParameter, valid syntax: MaxBufferSize=10Gb, "
+                "MaxBufferSize=1000Mb, MaxBufferSize=16Kb (minimum default), "
+                "\nadditional description: " +
+                description + " in call to Open");
         }
     }
     else
@@ -287,6 +303,7 @@ void BP1Base::InitParameterThreads(const std::string value)
     if (m_DebugMode)
     {
         bool success = true;
+        std::string description;
 
         try
         {
@@ -295,13 +312,15 @@ void BP1Base::InitParameterThreads(const std::string value)
         catch (std::exception &e)
         {
             success = false;
+            description = std::string(e.what());
         }
 
         if (!success || threads < 1)
         {
             throw std::invalid_argument(
                 "ERROR: value in Threads=value in IO SetParameters must be "
-                "an integer >= 1 (default), in call to Open\n");
+                "an integer >= 1 (default) \nadditional description: " +
+                description + "\n, in call to Open\n");
         }
     }
     else
@@ -319,6 +338,7 @@ void BP1Base::InitParameterVerbose(const std::string value)
     if (m_DebugMode)
     {
         bool success = true;
+        std::string description;
 
         try
         {
@@ -327,13 +347,15 @@ void BP1Base::InitParameterVerbose(const std::string value)
         catch (std::exception &e)
         {
             success = false;
+            description = std::string(e.what());
         }
 
         if (!success || verbosity < 0 || 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");
+                "an integer in the range [0,5], \nadditional description: " +
+                description + "\n, in call to Open\n");
         }
     }
     else
diff --git a/source/adios2/toolkit/format/bp1/BP1Writer.cpp b/source/adios2/toolkit/format/bp1/BP1Writer.cpp
index c7b9210b3e63d6ab65eb7d2590da3cc3439ac624..7bc9f34b18e379806764b3c36808272b03d67e76 100644
--- a/source/adios2/toolkit/format/bp1/BP1Writer.cpp
+++ b/source/adios2/toolkit/format/bp1/BP1Writer.cpp
@@ -42,7 +42,7 @@ void BP1Writer::WriteProcessGroupIndex(
     dataPosition += 8; // skip pg length (8)
 
     const std::size_t metadataPGLengthPosition = metadataBuffer.size();
-    metadataBuffer.insert(metadataBuffer.end(), 2, 0); // skip pg length (2)
+    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));
@@ -56,7 +56,8 @@ void BP1Writer::WriteProcessGroupIndex(
     WriteNameRecord(name, dataBuffer, dataPosition);
 
     // processID in metadata,
-    const uint32_t processID = static_cast<uint32_t>(m_BP1Aggregator.m_RankMPI);
+    const uint32_t processID =
+        static_cast<const uint32_t>(m_BP1Aggregator.m_RankMPI);
     InsertToBuffer(metadataBuffer, &processID);
     // skip coordination var in data ....what is coordination var?
     dataPosition += 4;
@@ -71,22 +72,23 @@ void BP1Writer::WriteProcessGroupIndex(
     CopyToBuffer(dataBuffer, dataPosition, &m_MetadataSet.TimeStep);
 
     // offset to pg in data in metadata which is the current absolute position
-    InsertToBuffer(metadataBuffer, reinterpret_cast<uint64_t *>(
-                                       &m_HeapBuffer.m_DataAbsolutePosition));
+    InsertU64(metadataBuffer, m_HeapBuffer.m_DataAbsolutePosition);
 
     // Back to writing metadata pg index length (length of group)
-    const uint16_t metadataPGIndexLength =
-        metadataBuffer.size() - metadataPGLengthPosition - 2;
+    const uint16_t metadataPGIndexLength = static_cast<const uint16_t>(
+        metadataBuffer.size() - metadataPGLengthPosition - 2);
+
     size_t backPosition = metadataPGLengthPosition;
     CopyToBuffer(metadataBuffer, backPosition, &metadataPGIndexLength);
     // DONE With metadataBuffer
 
     // here write method in data
     const std::vector<uint8_t> methodIDs = GetTransportIDs(transportsTypes);
-    const uint8_t methodsCount = methodIDs.size();
+    const uint8_t methodsCount = static_cast<const uint8_t>(methodIDs.size());
     CopyToBuffer(dataBuffer, dataPosition, &methodsCount); // count
     // methodID (1) + method params length(2), no parameters for now
-    const uint16_t methodsLength = methodIDs.size() * 3;
+    const uint16_t methodsLength =
+        static_cast<const uint16_t>(methodsCount * 3);
 
     CopyToBuffer(dataBuffer, dataPosition, &methodsLength); // length
 
@@ -253,23 +255,19 @@ void BP1Writer::WriteDimensionsRecord(const Dims localDimensions,
 {
     if (offsets.empty())
     {
-        for (const auto &localDimension : localDimensions)
+        for (const auto localDimension : localDimensions)
         {
-            InsertToBuffer(buffer,
-                           reinterpret_cast<const uint64_t *>(&localDimension));
-            buffer.insert(buffer.end(), 2 * sizeof(uint64_t), 0);
+            InsertU64(buffer, localDimension);
+            buffer.insert(buffer.end(), 2 * sizeof(uint64_t), '\0');
         }
     }
     else
     {
         for (unsigned int d = 0; d < localDimensions.size(); ++d)
         {
-            InsertToBuffer(buffer, reinterpret_cast<const uint64_t *>(
-                                       &localDimensions[d]));
-            InsertToBuffer(buffer, reinterpret_cast<const uint64_t *>(
-                                       &globalDimensions[d]));
-            InsertToBuffer(buffer,
-                           reinterpret_cast<const uint64_t *>(&offsets[d]));
+            InsertU64(buffer, localDimensions[d]);
+            InsertU64(buffer, globalDimensions[d]);
+            InsertU64(buffer, offsets[d]);
         }
     }
 }
@@ -290,8 +288,9 @@ void BP1Writer::WriteDimensionsRecord(const Dims localDimensions,
             CopyToBuffer(buffer, position, &no);
         }
 
-        CopyToBuffer(buffer, position,
-                     reinterpret_cast<const uint64_t *>(&dimension));
+        const uint64_t dimension64 = static_cast<const uint64_t>(dimension);
+
+        CopyToBuffer(buffer, position, &dimension64);
     };
 
     // BODY Starts here
@@ -326,7 +325,7 @@ void BP1Writer::WriteDimensionsRecord(const Dims localDimensions,
 void BP1Writer::WriteNameRecord(const std::string name,
                                 std::vector<char> &buffer) noexcept
 {
-    const uint16_t length = name.length();
+    const uint16_t length = static_cast<const uint16_t>(name.length());
     InsertToBuffer(buffer, &length);
     InsertToBuffer(buffer, name.c_str(), length);
 }
@@ -335,7 +334,7 @@ void BP1Writer::WriteNameRecord(const std::string name,
                                 std::vector<char> &buffer,
                                 size_t &position) noexcept
 {
-    const uint16_t length = name.length();
+    const uint16_t length = static_cast<const uint16_t>(name.length());
     CopyToBuffer(buffer, position, &length);
     CopyToBuffer(buffer, position, name.c_str(), length);
 }
@@ -434,23 +433,22 @@ void BP1Writer::FlattenMetadata() noexcept
     lf_IndexCountLength(m_MetadataSet.AttributesIndices, attributesCount,
                         attributesLength);
 
-    const size_t footerSize = (pgLength + 16) + (varsLength + 12) +
-                              (attributesLength + 12) +
-                              m_MetadataSet.MiniFooterSize;
+    const size_t footerSize = static_cast<const size_t>(
+        (pgLength + 16) + (varsLength + 12) + (attributesLength + 12) +
+        m_MetadataSet.MiniFooterSize);
 
     auto &buffer = m_HeapBuffer.m_Data;
     auto &position = m_HeapBuffer.m_DataPosition;
 
     // reserve data to fit metadata,
-    // 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);
     CopyToBuffer(buffer, position, &pgLength);
     CopyToBuffer(buffer, position, m_MetadataSet.PGIndex.Buffer.data(),
-                 pgLength);
+                 static_cast<const size_t>(pgLength));
 
     // Vars indices
     lf_FlattenIndices(varsCount, varsLength, m_MetadataSet.VarsIndices, buffer,
@@ -460,9 +458,12 @@ void BP1Writer::FlattenMetadata() noexcept
                       m_MetadataSet.AttributesIndices, buffer, position);
 
     // getting absolute offsets, minifooter is 28 bytes for now
-    const uint64_t offsetPGIndex = m_HeapBuffer.m_DataAbsolutePosition;
-    const uint64_t offsetVarsIndex = offsetPGIndex + (pgLength + 16);
-    const uint64_t offsetAttributeIndex = offsetVarsIndex + (varsLength + 12);
+    const uint64_t offsetPGIndex =
+        static_cast<const uint64_t>(m_HeapBuffer.m_DataAbsolutePosition);
+    const uint64_t offsetVarsIndex =
+        static_cast<const uint64_t>(offsetPGIndex + (pgLength + 16));
+    const uint64_t offsetAttributeIndex =
+        static_cast<const uint64_t>(offsetVarsIndex + (varsLength + 12));
 
     CopyToBuffer(buffer, position, &offsetPGIndex);
     CopyToBuffer(buffer, position, &offsetVarsIndex);
diff --git a/source/adios2/toolkit/format/bp1/BP1Writer.h b/source/adios2/toolkit/format/bp1/BP1Writer.h
index 44d306c3f2500cf61a216f58be108026ab0f58df..7f65b749e2730dece386db1e273a4f77cf7208cf 100644
--- a/source/adios2/toolkit/format/bp1/BP1Writer.h
+++ b/source/adios2/toolkit/format/bp1/BP1Writer.h
@@ -72,7 +72,7 @@ public:
     void Advance();
 
     /** Flattens data buffer and close current process group, doesn't
-     * advance time index */
+     *  advance time index */
     void Flush();
 
     /**
diff --git a/source/adios2/toolkit/format/bp1/BP1Writer.tcc b/source/adios2/toolkit/format/bp1/BP1Writer.tcc
index 733f43195b2e8f85d864e0d78896e1bc28400c11..c1aa88ca6643d8e98fe48c3c4145b137b7ec7ff4 100644
--- a/source/adios2/toolkit/format/bp1/BP1Writer.tcc
+++ b/source/adios2/toolkit/format/bp1/BP1Writer.tcc
@@ -37,7 +37,7 @@ void BP1Writer::WriteVariableMetadata(const Variable<T> &variable) noexcept
     stats.MemberID = variableIndex.MemberID;
 
     // write metadata header in data and extract offsets
-    stats.Offset = m_HeapBuffer.m_DataAbsolutePosition;
+    stats.Offset = static_cast<uint64_t>(m_HeapBuffer.m_DataAbsolutePosition);
     WriteVariableMetadataInData(variable, stats);
     stats.PayloadOffset = m_HeapBuffer.m_DataAbsolutePosition;
 
@@ -109,7 +109,8 @@ void BP1Writer::WriteVariableMetadataInData(
     constexpr char no = 'n'; // isDimension
     CopyToBuffer(buffer, position, &no);
 
-    const uint8_t dimensions = variable.m_Count.size();
+    const uint8_t dimensions =
+        static_cast<const uint8_t>(variable.m_Count.size());
     CopyToBuffer(buffer, position, &dimensions); // count
 
     // 27 is from 9 bytes for each: var y/n + local, var y/n + global dimension,
@@ -145,11 +146,11 @@ void BP1Writer::WriteVariableMetadataInIndex(
     if (isNew) // write variable header (might be shared with
                // attributes index)
     {
-        buffer.insert(buffer.end(), 4, 0); // skip var length (4)
+        buffer.insert(buffer.end(), 4, '\0'); // skip var length (4)
         InsertToBuffer(buffer, &stats.MemberID);
-        buffer.insert(buffer.end(), 2, 0); // skip group name
+        buffer.insert(buffer.end(), 2, '\0'); // skip group name
         WriteNameRecord(variable.m_Name, buffer);
-        buffer.insert(buffer.end(), 2, 0); // skip path
+        buffer.insert(buffer.end(), 2, '\0'); // skip path
 
         const std::uint8_t dataType = GetDataType<T>();
         InsertToBuffer(buffer, &dataType);
@@ -256,15 +257,17 @@ void BP1Writer::WriteVariableCharacteristics(
     // going back at the end
     const size_t characteristicsCountPosition = buffer.size();
     // skip characteristics count(1) + length (4)
-    buffer.insert(buffer.end(), 5, 0);
+    buffer.insert(buffer.end(), 5, '\0');
     uint8_t characteristicsCounter = 0;
 
     // DIMENSIONS
     uint8_t characteristicID = characteristic_dimensions;
     InsertToBuffer(buffer, &characteristicID);
-    const uint8_t dimensions = variable.m_Count.size();
+    const uint8_t dimensions =
+        static_cast<const uint8_t>(variable.m_Count.size());
     InsertToBuffer(buffer, &dimensions); // count
-    const uint16_t dimensionsLength = 24 * dimensions;
+    const uint16_t dimensionsLength =
+        static_cast<const uint16_t>(24 * dimensions);
     InsertToBuffer(buffer, &dimensionsLength); // length
     WriteDimensionsRecord(variable.m_Count, variable.m_Shape, variable.m_Start,
                           buffer);
@@ -276,9 +279,10 @@ void BP1Writer::WriteVariableCharacteristics(
     WriteCharacteristicRecord(characteristic_time_index, characteristicsCounter,
                               stats.TimeIndex, buffer);
 
+    const uint32_t rankU32 =
+        static_cast<const uint32_t>(m_BP1Aggregator.m_RankMPI);
     WriteCharacteristicRecord(characteristic_file_index, characteristicsCounter,
-                              static_cast<uint32_t>(m_BP1Aggregator.m_RankMPI),
-                              buffer);
+                              rankU32, buffer);
 
     WriteCharacteristicRecord(characteristic_offset, characteristicsCounter,
                               stats.Offset, buffer);
@@ -293,8 +297,8 @@ void BP1Writer::WriteVariableCharacteristics(
     CopyToBuffer(buffer, backPosition, &characteristicsCounter); // count (1)
 
     // remove its own length (4) + characteristic counter (1)
-    const uint32_t characteristicsLength =
-        buffer.size() - characteristicsCountPosition - 4 - 1;
+    const uint32_t characteristicsLength = static_cast<const uint32_t>(
+        buffer.size() - characteristicsCountPosition - 4 - 1);
 
     CopyToBuffer(buffer, backPosition, &characteristicsLength); // length
 }
@@ -315,9 +319,11 @@ void BP1Writer::WriteVariableCharacteristics(
     uint8_t characteristicID = characteristic_dimensions;
     CopyToBuffer(buffer, position, &characteristicID);
 
-    const uint8_t dimensions = variable.m_Count.size();
+    const uint8_t dimensions =
+        static_cast<const uint8_t>(variable.m_Count.size());
     CopyToBuffer(buffer, position, &dimensions); // count
-    const uint16_t dimensionsLength = 24 * dimensions;
+    const uint16_t dimensionsLength =
+        static_cast<const uint16_t>(24 * dimensions);
     CopyToBuffer(buffer, position, &dimensionsLength); // length
     WriteDimensionsRecord(variable.m_Count, variable.m_Shape, variable.m_Start,
                           buffer, position, true); // isCharacteristic = true
@@ -333,8 +339,8 @@ void BP1Writer::WriteVariableCharacteristics(
     CopyToBuffer(buffer, backPosition, &characteristicsCounter);
 
     // remove its own length (4) + characteristic counter (1)
-    const uint32_t characteristicsLength =
-        position - characteristicsCountPosition - 4 - 1;
+    const uint32_t characteristicsLength = static_cast<const uint32_t>(
+        position - characteristicsCountPosition - 4 - 1);
     CopyToBuffer(buffer, backPosition, &characteristicsLength);
 }
 
diff --git a/source/adios2/toolkit/transport/file/FilePointer.cpp b/source/adios2/toolkit/transport/file/FilePointer.cpp
index 82b764bd58548119564bf60f8fda0416d2967a46..e11c4f9fb9dc17a6118f4cec5d8fc6f933061eb8 100644
--- a/source/adios2/toolkit/transport/file/FilePointer.cpp
+++ b/source/adios2/toolkit/transport/file/FilePointer.cpp
@@ -14,6 +14,11 @@
 #include <ios> //std::ios_base::failure
 /// \endcond
 
+// removes fopen warning on Windows
+#ifdef _WIN32
+#pragma warning(disable : 4996) // fopen
+#endif
+
 namespace adios2
 {
 namespace transport
@@ -28,7 +33,7 @@ FilePointer::~FilePointer()
 {
     if (m_IsOpen)
     {
-        fclose(m_File);
+        std::fclose(m_File);
     }
 }
 
@@ -48,19 +53,19 @@ void FilePointer::Open(const std::string &name, const OpenMode openMode)
 
     if (m_OpenMode == OpenMode::Write)
     {
-        m_File = std::fopen(name.c_str(), "w");
+        m_File = std::fopen(name.c_str(), "wb");
     }
     else if (m_OpenMode == OpenMode::Append)
     {
         // need to change when implemented
-        m_File = std::fopen(name.c_str(), "a");
+        m_File = std::fopen(name.c_str(), "ab");
     }
     else if (m_OpenMode == OpenMode::Read)
     {
-        m_File = std::fopen(name.c_str(), "r");
+        m_File = std::fopen(name.c_str(), "rb");
     }
 
-    if (std::ferror(m_File))
+    if (ferror(m_File))
     {
         throw std::ios_base::failure("ERROR: couldn't open file " + name +
                                      ", "
diff --git a/source/adios2/toolkit/transport/file/FilePointer.h b/source/adios2/toolkit/transport/file/FilePointer.h
index 7c14b48066d1291790411adac6ffef5194bb6cb1..6d1521a3d5d99fff26f00806871194f9461fa5a8 100644
--- a/source/adios2/toolkit/transport/file/FilePointer.h
+++ b/source/adios2/toolkit/transport/file/FilePointer.h
@@ -45,7 +45,7 @@ public:
 
 private:
     /** C File pointer */
-    std::FILE *m_File = nullptr; // NULL or nullptr?
+    FILE *m_File = nullptr; // NULL or nullptr?
 };
 
 } // end namespace transport
diff --git a/source/adios2/toolkit/transport/file/FileStream.cpp b/source/adios2/toolkit/transport/file/FileStream.cpp
index 50c05e0e22443b37be4721c0e60eb5568bdae081..3609394539420b2a3c3333bc31506f45b05b76a7 100644
--- a/source/adios2/toolkit/transport/file/FileStream.cpp
+++ b/source/adios2/toolkit/transport/file/FileStream.cpp
@@ -40,16 +40,17 @@ void FileStream::Open(const std::string &name, const OpenMode openMode)
 
     if (m_OpenMode == OpenMode::Write)
     {
-        m_FileStream.open(name, std::fstream::out);
+        m_FileStream.open(name, std::fstream::out | std::fstream::binary);
     }
     else if (m_OpenMode == OpenMode::Append)
     {
         // to be changed to rw?
-        m_FileStream.open(name, std::fstream::out | std::fstream::app);
+        m_FileStream.open(name, std::fstream::out | std::fstream::app |
+                                    std::fstream::binary);
     }
     else if (m_OpenMode == OpenMode::Read)
     {
-        m_FileStream.open(name, std::fstream::in);
+        m_FileStream.open(name, std::fstream::in | std::fstream::binary);
     }
 
     if (!m_FileStream)
diff --git a/source/adios2/toolkit/transport/wan/WANZmq.cpp b/source/adios2/toolkit/transport/wan/WANZmq.cpp
index 6627a6372c42ddebaab36572825787cabbfa29e2..7760f4bf7f00ab3e8f95c4bf3eea6294b1f8b286 100644
--- a/source/adios2/toolkit/transport/wan/WANZmq.cpp
+++ b/source/adios2/toolkit/transport/wan/WANZmq.cpp
@@ -10,6 +10,7 @@
 
 #include "WANZmq.h"
 
+#include <iostream>
 #include <zmq.h>
 
 namespace adios2
@@ -22,7 +23,7 @@ WANZmq::WANZmq(const std::string ipAddress, const std::string port,
 : Transport("wan", "zmq", mpiComm, debugMode), m_IPAddress(ipAddress),
   m_Port(port)
 {
-
+    m_Context = zmq_ctx_new();
     if (m_DebugMode)
     {
         // TODO verify port is unsigned int
@@ -35,6 +36,10 @@ WANZmq::~WANZmq()
     {
         zmq_close(m_Socket);
     }
+    if (m_Context)
+    {
+        zmq_ctx_destroy(m_Context);
+    }
 }
 
 void WANZmq::Open(const std::string &name, const OpenMode openMode)
@@ -51,7 +56,8 @@ void WANZmq::Open(const std::string &name, const OpenMode openMode)
 
         m_Socket = zmq_socket(m_Context, ZMQ_REQ);
         const std::string fullIP("tcp://" + m_IPAddress + ":" + m_Port);
-        zmq_connect(m_Socket, fullIP.c_str());
+        std::cout << "full IP = " << fullIP << std::endl;
+        int err = zmq_connect(m_Socket, fullIP.c_str());
 
         if (m_Profiler.IsActive)
         {
@@ -78,6 +84,7 @@ void WANZmq::Open(const std::string &name, const OpenMode openMode)
 
         m_Socket = zmq_socket(m_Context, ZMQ_REP);
         const std::string fullIP("tcp://" + m_IPAddress + ":" + m_Port);
+        std::cout << "full IP = " << fullIP << std::endl;
         zmq_bind(m_Socket, fullIP.c_str());
 
         if (m_Profiler.IsActive)
@@ -108,10 +115,13 @@ void WANZmq::Write(const char *buffer, size_t size)
         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();
@@ -128,6 +138,7 @@ void WANZmq::Write(const char *buffer, size_t size)
                                          ", in call to WANZmq write\n");
         }
     }
+    */
 }
 
 void WANZmq::Flush() {}
diff --git a/source/adios2/toolkit/transport/wan/WANZmq.h b/source/adios2/toolkit/transport/wan/WANZmq.h
index 7249f963cc31d0fd464c4c9d92c594c2ee600408..c24b3e70b02841f2e0d67710eec0875ea2dffd63 100644
--- a/source/adios2/toolkit/transport/wan/WANZmq.h
+++ b/source/adios2/toolkit/transport/wan/WANZmq.h
@@ -50,10 +50,10 @@ private:
     const std::string m_IPAddress;
     std::string m_Port;
 
-    /** TODO: find out if is provided externally */
+    /** context handler created by zmq, thread safe */
     void *m_Context = NULL;
 
-    /** handler created by zmq */
+    /** socket handler created by zmq */
     void *m_Socket = NULL;
 };
 
diff --git a/source/adios2/toolkit/transportman/dataman/DataMan.cpp b/source/adios2/toolkit/transportman/dataman/DataMan.cpp
index 651337954c14bce8b25990f74ddf7a446f6b5837..95abf19ee8c735b42293c6084383dcb5a4005fd1 100644
--- a/source/adios2/toolkit/transportman/dataman/DataMan.cpp
+++ b/source/adios2/toolkit/transportman/dataman/DataMan.cpp
@@ -8,7 +8,7 @@
  *      Author: Jason Wang wangr1@ornl.gov
  */
 
-#include "adios2/toolkit/transportman/DataMan/DataMan.h"
+#include "adios2/toolkit/transportman/dataman/DataMan.h"
 #include "adios2/helper/adiosString.h"
 
 #ifdef ADIOS2_HAVE_ZEROMQ
@@ -32,16 +32,16 @@ void DataMan::OpenWANTransports(const std::string &name,
 
     for (const auto &parameters : parametersVector)
     {
-        std::shared_ptr<Transport> wanTransport;
-
-        for(auto &i :parameters){
+        std::shared_ptr<Transport> wanTransport, controlTransport;
 
+        // to be removed
+        for (auto &i : parameters)
+        {
             std::cout << i.first << " " << i.second << std::endl;
-
         }
 
         const std::string type(
-                GetParameter("type", parameters, true, m_DebugMode, ""));
+            GetParameter("type", parameters, true, m_DebugMode, ""));
 
         const std::string trans(
             GetParameter("transport", parameters, true, m_DebugMode, ""));
@@ -49,14 +49,16 @@ void DataMan::OpenWANTransports(const std::string &name,
         const std::string ipAddress(
             GetParameter("ipaddress", parameters, true, m_DebugMode, ""));
 
-        std::string port(
+        std::string port_control(
             GetParameter("port", parameters, false, m_DebugMode, ""));
 
-        if (port.empty())
+        if (port_control.empty())
         {
-            port = m_DefaultPort;
+            port_control = std::to_string(m_DefaultPort);
         }
 
+        const std::string port_data(std::to_string(stoi(port_control) + 1));
+
         std::string messageName(
             GetParameter("name", parameters, false, m_DebugMode, ""));
 
@@ -71,7 +73,9 @@ void DataMan::OpenWANTransports(const std::string &name,
             {
 #ifdef ADIOS2_HAVE_ZEROMQ
                 wanTransport = std::make_shared<transport::WANZmq>(
-                    ipAddress, port, m_MPIComm, m_DebugMode);
+                    ipAddress, port_data, m_MPIComm, m_DebugMode);
+                controlTransport = std::make_shared<transport::WANZmq>(
+                    ipAddress, port_control, m_MPIComm, m_DebugMode);
 #else
                 throw std::invalid_argument(
                     "ERROR: this version of ADIOS2 didn't compile with "
@@ -89,8 +93,46 @@ void DataMan::OpenWANTransports(const std::string &name,
                 }
             }
         }
+
         wanTransport->Open(messageName, openMode);
         m_Transports.push_back(std::move(wanTransport));
+        controlTransport->Open(messageName, openMode);
+        m_ControlTransports.push_back(std::move(controlTransport));
+    }
+}
+
+void DataMan::WriteWAN(const void *buffer, nlohmann::json jmsg)
+{
+    m_ControlTransports[m_CurrentTransport]->Write(jmsg.dump().c_str(),
+                                                   jmsg.dump().size());
+    m_Transports[m_CurrentTransport]->Write(static_cast<const char *>(buffer),
+                                            jmsg["bytes"].get<size_t>());
+}
+
+void DataMan::SetCallback(std::function<void(const void *, std::string,
+                                             std::string, std::string, Dims)>
+                              callback)
+{
+    m_CallBack = callback;
+}
+
+void DataMan::ReadThread(std::shared_ptr<Transport> trans,
+                         std::shared_ptr<Transport> ctl_trans)
+{
+    while (m_Listening)
+    {
+        // Wait for Read API to be implemented
+        /*
+        if (ctl_trans->Read() >= 0)
+        {
+            std::string smsg;
+            nlohmann::json jmsg = json::parse(smsg);
+        }
+        else
+        {
+            usleep(1);
+        }
+        */
     }
 }
 
diff --git a/source/adios2/toolkit/transportman/dataman/DataMan.h b/source/adios2/toolkit/transportman/dataman/DataMan.h
index 0e7dacd258b5431a5994a1ce1b357dea6ce03303..8466068fa98c96ac2b1fc97a88970ff505efa53e 100644
--- a/source/adios2/toolkit/transportman/dataman/DataMan.h
+++ b/source/adios2/toolkit/transportman/dataman/DataMan.h
@@ -13,6 +13,7 @@
 
 #include "adios2/toolkit/transportman/TransportMan.h"
 #include <json.hpp>
+#include <thread>
 
 namespace adios2
 {
@@ -31,11 +32,29 @@ public:
                            const std::vector<Params> &parametersVector,
                            const bool profile);
 
+    void WriteWAN(const void *buffer, nlohmann::json jmsg);
+
+    void SetCallback(std::function<void(const void *, std::string, std::string,
+                                        std::string, Dims)>
+                         callback);
+
 private:
+    void ReadThread(std::shared_ptr<Transport> trans,
+                    std::shared_ptr<Transport> ctl_trans);
+
+    std::vector<std::shared_ptr<Transport>> m_ControlTransports;
+    std::vector<std::thread> m_ControlThreads;
+    size_t m_CurrentTransport = 0;
+    bool m_Listening = false;
+
+    std::function<void(const void *, std::string, std::string, std::string,
+                       Dims)>
+        m_CallBack;
+
     nlohmann::json m_JMessage;
 
     /** Pick the appropriate default */
-    const std::string m_DefaultPort = "22";
+    const int m_DefaultPort = 12306;
 };
 
 } // end namespace transportman
diff --git a/source/adios2/transform/compress/CompressBZip2.cpp b/source/adios2/transform/compress/CompressBZip2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..59c378422c42f25edf77e0dd4d99f30da3c180b0
--- /dev/null
+++ b/source/adios2/transform/compress/CompressBZip2.cpp
@@ -0,0 +1,170 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * CompressBZip2.cpp
+ *
+ *  Created on: Jul 24, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "CompressBZip2.h"
+
+/// \cond EXCLUDE_FROM_DOXYGEN
+#include <cmath>     //std::ceil
+#include <ios>       //std::ios_base::failure
+#include <stdexcept> //std::invalid_argument
+/// \endcond
+
+#include <bzlib.h>
+
+#include "adios2/helper/adiosFunctions.h"
+
+namespace adios2
+{
+namespace transform
+{
+
+CompressBZip2::CompressBZip2(const bool debugMode)
+: Transform("bzip2", debugMode)
+{
+}
+
+size_t CompressBZip2::BufferMaxSize(const size_t sizeIn) const
+{
+    return static_cast<size_t>(std::ceil(1.1 * sizeIn) + 600);
+}
+
+size_t CompressBZip2::Compress(const void *dataIn, const Dims &dimensions,
+                               const size_t elementSize, const std::string type,
+                               void *bufferOut, const Params &parameters) const
+{
+    // defaults
+    int blockSize100k = 1;
+    int verbosity = 0;
+    int workFactor = 0;
+
+    if (!parameters.empty())
+    {
+        const std::string hint(" in call to CompressBZip2 Compress " + type +
+                               "\n");
+        SetParameterValueInt("BlockSize100K", parameters, blockSize100k,
+                             m_DebugMode, hint);
+        SetParameterValueInt("Verbosity", parameters, verbosity, m_DebugMode,
+                             hint);
+        SetParameterValueInt("WorkFactor", parameters, workFactor, m_DebugMode,
+                             hint);
+        if (m_DebugMode == true)
+        {
+
+            if (blockSize100k < 1 || blockSize100k > 9)
+            {
+                throw std::invalid_argument(
+                    "ERROR: BlockSize100K must be an "
+                    "integer between 1 (less "
+                    "compression, less memory) and 9 "
+                    "(more compression, more memory) inclusive, " +
+                    hint);
+            }
+        }
+    }
+
+    const size_t sizeIn =
+        static_cast<const size_t>(GetTotalSize(dimensions) * elementSize);
+    // Build inputs to BZip2 compression function
+    char *dest = const_cast<char *>(reinterpret_cast<const char *>(bufferOut));
+    unsigned int destLen = static_cast<unsigned int>(BufferMaxSize(sizeIn));
+
+    char *source = const_cast<char *>(reinterpret_cast<const char *>(dataIn));
+    unsigned int sourceLen = static_cast<unsigned int>(sizeIn);
+
+    int status = BZ2_bzBuffToBuffCompress(dest, &destLen, source, sourceLen,
+                                          blockSize100k, verbosity, workFactor);
+
+    if (m_DebugMode)
+    {
+        CheckStatus(status, "in call to CompressBZip2 Compress\n");
+    }
+
+    return static_cast<size_t>(destLen);
+}
+
+size_t CompressBZip2::Decompress(const void *bufferIn, const size_t sizeIn,
+                                 void *dataOut, const size_t sizeOut) const
+{
+    // TODO: leave defaults at zero?
+    int small = 0;
+    int verbosity = 0;
+
+    char *dest = reinterpret_cast<char *>(dataOut);
+    unsigned int destLen = static_cast<unsigned int>(sizeOut);
+
+    char *source = const_cast<char *>(reinterpret_cast<const char *>(bufferIn));
+    unsigned int sourceLen = static_cast<unsigned int>(sizeIn);
+
+    int status = BZ2_bzBuffToBuffDecompress(dest, &destLen, source, sourceLen,
+                                            small, verbosity);
+
+    if (m_DebugMode)
+    {
+        CheckStatus(status, "in call to CompressBZip2 Decompress\n");
+    }
+
+    return static_cast<size_t>(destLen);
+}
+
+void CompressBZip2::CheckStatus(const int status, const std::string hint) const
+{
+    switch (status)
+    {
+
+    case (BZ_CONFIG_ERROR):
+        throw std::invalid_argument(
+            "ERROR: BZ_CONFIG_ERROR, bzip2 library is not configured "
+            "correctly" +
+            hint);
+        break;
+
+    case (BZ_PARAM_ERROR):
+        throw std::invalid_argument(
+            "ERROR: BZ_PARAM_ERROR bufferOut stream might be null" + hint);
+        break;
+
+    case (BZ_MEM_ERROR):
+        throw std::ios_base::failure(
+            "ERROR: BZ_MEM_ERROR bzip2 detected insufficient memory " + hint);
+        break;
+
+    case (BZ_OUTBUFF_FULL):
+        throw std::ios_base::failure("ERROR: BZ_OUTBUFF_FULL bzip2 detected "
+                                     "size of compressed data is larger than "
+                                     "destination length " +
+                                     hint);
+        break;
+
+    // decompression
+    case (BZ_DATA_ERROR):
+        throw std::invalid_argument("ERROR: BZ_DATA_ERROR, bzip2 library "
+                                    "detected integrity errors in compressed "
+                                    "data " +
+                                    hint);
+        break;
+
+    case (BZ_DATA_ERROR_MAGIC):
+        throw std::invalid_argument("ERROR: BZ_DATA_ERROR_MAGIC, bzip2 library "
+                                    "detected wrong magic numbers in "
+                                    "compressed data " +
+                                    hint);
+        break;
+
+    case (BZ_UNEXPECTED_EOF):
+        throw std::invalid_argument("ERROR: BZ_UNEXPECTED_EOF, bzip2 library "
+                                    "detected unexpected end of "
+                                    "compressed data " +
+                                    hint);
+        break;
+    }
+}
+
+} // end namespace transform
+} // end namespace adios2
diff --git a/source/adios2/transform/compress/CompressBZip2.h b/source/adios2/transform/compress/CompressBZip2.h
new file mode 100644
index 0000000000000000000000000000000000000000..81cd28759a041a0feca1408c80a2e1ab784cb194
--- /dev/null
+++ b/source/adios2/transform/compress/CompressBZip2.h
@@ -0,0 +1,74 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * CompressBZip2.h : wrapper to BZip2 compression library
+ *
+ *  Created on: Jul 24, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TRANSFORM_COMPRESSION_COMPRESSBZIP2_H_
+#define ADIOS2_TRANSFORM_COMPRESSION_COMPRESSBZIP2_H_
+
+#include "adios2/core/Transform.h"
+
+namespace adios2
+{
+namespace transform
+{
+
+class CompressBZip2 : public Transform
+{
+
+public:
+    /**
+     * Unique constructor
+     * @param debugMode
+     */
+    CompressBZip2(const bool debugMode);
+
+    ~CompressBZip2() = default;
+
+    size_t BufferMaxSize(const size_t sizeIn) const final;
+
+    /**
+     * Compression signature for legacy libraries that use void*
+     * @param dataIn
+     * @param dimensions
+     * @param type
+     * @param bufferOut
+     * @param parameters
+     * @return size of compressed buffer in bytes
+     */
+    size_t Compress(const void *dataIn, const Dims &dimensions,
+                    const size_t elementSize, const std::string type,
+                    void *bufferOut,
+                    const Params &parameters = Params()) const final;
+
+    /**
+     * Decompression signature for legacy libraries that use void*
+     * @param bufferIn
+     * @param sizeIn
+     * @param dataOut
+     * @param dimensions
+     * @param type
+     * @return size of decompressed buffer in bytes
+     */
+    size_t Decompress(const void *bufferIn, const size_t sizeIn, void *dataOut,
+                      const size_t sizeOut) const final;
+
+private:
+    /**
+     * In debug mode, check status from BZip compression and decompression
+     * functions
+     * @param status returned by BZip2 library
+     * @param hint extra exception information
+     */
+    void CheckStatus(const int status, const std::string hint) const;
+};
+
+} // end namespace transform
+} // end namespace adios2
+
+#endif /* ADIOS2_TRANSFORM_COMPRESSION_COMPRESSBZIP2_H_ */
diff --git a/source/adios2/transform/compress/CompressZfp.cpp b/source/adios2/transform/compress/CompressZfp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b53f18c4f82e55281fb69e1cf210b3f5df8b6428
--- /dev/null
+++ b/source/adios2/transform/compress/CompressZfp.cpp
@@ -0,0 +1,278 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * CompressZfp.cpp
+ *
+ *  Created on: Jul 25, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#include "CompressZfp.h"
+
+#include "adios2/helper/adiosFunctions.h"
+
+namespace adios2
+{
+namespace transform
+{
+
+CompressZfp::CompressZfp(const bool debugMode) : Transform("zfp", debugMode) {}
+
+size_t CompressZfp::DoBufferMaxSize(const void *dataIn, const Dims &dimensions,
+                                    const std::string type,
+                                    const Params &parameters) const
+{
+    zfp_field *field = GetZFPField(dataIn, dimensions, type);
+    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);
+    const size_t maxSize = zfp_stream_maximum_size(stream, field);
+    zfp_field_free(field);
+    zfp_stream_close(stream);
+    return maxSize;
+}
+
+size_t CompressZfp::Compress(const void *dataIn, const Dims &dimensions,
+                             const size_t elementSize, const std::string type,
+                             void *bufferOut, const Params &parameters) const
+{
+
+    zfp_field *field = GetZFPField(dataIn, dimensions, type);
+    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);
+    size_t maxSize = zfp_stream_maximum_size(stream, field);
+    // associate bitstream
+    bitstream *bitstream = stream_open(bufferOut, maxSize);
+    zfp_stream_set_bit_stream(stream, bitstream);
+    zfp_stream_rewind(stream);
+
+    size_t sizeOut = zfp_compress(stream, field);
+
+    if (m_DebugMode == true)
+    {
+        if (sizeOut == 0)
+        {
+            throw std::invalid_argument("ERROR: zfp failed, compressed buffer "
+                                        "size is 0, in call to Compress");
+        }
+    }
+
+    zfp_field_free(field);
+    zfp_stream_close(stream);
+    return sizeOut;
+}
+
+size_t CompressZfp::Decompress(const void *bufferIn, const size_t sizeIn,
+                               void *dataOut, const Dims &dimensions,
+                               const std::string type,
+                               const Params &parameters) const
+{
+    auto lf_GetTypeSize = [](const zfp_type zfpType) -> size_t {
+
+        size_t size = 0;
+        if (zfpType == zfp_type_int32 || zfpType == zfp_type_float)
+        {
+            size = 4;
+        }
+        else if (zfpType == zfp_type_int64 || zfpType == zfp_type_double)
+        {
+            size = 8;
+        }
+        return size;
+    };
+
+    zfp_field *field = GetZFPField(dataOut, dimensions, type);
+    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);
+
+    // associate bitstream
+    bitstream *bitstream = stream_open(const_cast<void *>(bufferIn), sizeIn);
+    zfp_stream_set_bit_stream(stream, bitstream);
+    zfp_stream_rewind(stream);
+
+    int status = zfp_decompress(stream, field);
+
+    if (m_DebugMode)
+    {
+        if (!status)
+        {
+            throw std::invalid_argument(
+                "ERROR: zfp failed with status " + std::to_string(status) +
+                ", in call to CompressZfp Decompress\n");
+        }
+    }
+
+    zfp_field_free(field);
+    zfp_stream_close(stream);
+    stream_close(bitstream);
+
+    const size_t typeSizeBytes = lf_GetTypeSize(GetZfpType(type));
+    const size_t dataSizeBytes = GetTotalSize(dimensions) * typeSizeBytes;
+
+    return dataSizeBytes;
+}
+
+// PRIVATE
+zfp_type CompressZfp::GetZfpType(const std::string type) const
+{
+    zfp_type zfpType = zfp_type_none;
+
+    if (type == GetType<double>())
+    {
+        zfpType = zfp_type_double;
+    }
+    else if (type == GetType<float>())
+    {
+        zfpType = zfp_type_float;
+    }
+    else if (type == GetType<int64_t>())
+    {
+        zfpType = zfp_type_int64;
+    }
+    else if (type == GetType<int32_t>())
+    {
+        zfpType = zfp_type_int32;
+    }
+    else
+    {
+        if (m_DebugMode)
+        {
+
+            throw std::invalid_argument(
+                "ERROR: type " + type +
+                " not supported by zfp, only "
+                "signed int32_t, signed int64_t, float, and "
+                "double types are acceptable, from class "
+                "CompressZfp Transform\n");
+        }
+    }
+
+    return zfpType;
+}
+
+zfp_field *CompressZfp::GetZFPField(const void *data, const Dims &dimensions,
+                                    const std::string type) const
+{
+    auto lf_CheckField = [](const zfp_field *field,
+                            const std::string zfpFieldFunction,
+                            const std::string type) {
+
+        if (field == nullptr || field == NULL)
+        {
+            throw std::invalid_argument(
+                "ERROR: " + zfpFieldFunction + " failed for data of type " +
+                type + ", data pointer might be corrupted, from "
+                       "class CompressZfp Transform\n");
+        }
+    };
+
+    zfp_type zfpType = GetZfpType(type);
+    zfp_field *field = nullptr;
+
+    if (dimensions.size() == 1)
+    {
+        field = zfp_field_1d(const_cast<void *>(data), zfpType, dimensions[0]);
+        if (m_DebugMode)
+        {
+            lf_CheckField(field, "zfp_field_1d", type);
+        }
+    }
+    else if (dimensions.size() == 2)
+    {
+        field = zfp_field_2d(const_cast<void *>(data), zfpType, dimensions[0],
+                             dimensions[1]);
+        if (m_DebugMode)
+        {
+            lf_CheckField(field, "zfp_field_2d", type);
+        }
+    }
+    else if (dimensions.size() == 3)
+    {
+        field = zfp_field_3d(const_cast<void *>(data), zfpType, dimensions[0],
+                             dimensions[1], dimensions[2]);
+        if (m_DebugMode)
+        {
+            lf_CheckField(field, "zfp_field_3d", type);
+        }
+    }
+    else
+    {
+        if (m_DebugMode)
+        {
+            throw std::invalid_argument(
+                "ERROR: zfp_field* failed for data of type " + type +
+                ", only 1D, 2D and 3D dimensions are supported, from "
+                "class CompressZfp Transform\n");
+        }
+    }
+
+    return field;
+}
+
+zfp_stream *CompressZfp::GetZFPStream(const Dims &dimensions,
+                                      const std::string type,
+                                      const Params &parameters) const
+{
+    auto lf_HasKey = [](Params::const_iterator itKey,
+                        const Params &parameters) -> bool {
+
+        bool hasKey = false;
+        if (itKey != parameters.end())
+        {
+            hasKey = true;
+        }
+        return hasKey;
+    };
+
+    zfp_stream *stream = zfp_stream_open(NULL);
+
+    auto itTolerance = parameters.find("Tolerance");
+    const bool hasTolerance = lf_HasKey(itTolerance, parameters);
+
+    auto itRate = parameters.find("Rate");
+    const bool hasRate = lf_HasKey(itRate, parameters);
+
+    auto itPrecision = parameters.find("Precision");
+    const bool hasPrecision = lf_HasKey(itPrecision, parameters);
+
+    if (m_DebugMode)
+    {
+        if ((hasTolerance && hasRate) || (hasTolerance && hasPrecision) ||
+            (hasRate && hasPrecision) ||
+            !(hasTolerance || hasRate || hasPrecision))
+        {
+            throw std::invalid_argument("ERROR: zfp parameters Tolerance, "
+                                        "Rate, Precision are mutually "
+                                        "exclusive, only one of them is "
+                                        "mandatory, from "
+                                        "class CompressZfp Transform\n");
+        }
+    }
+
+    if (hasTolerance)
+    {
+        const double tolerance = StringToDouble(
+            itTolerance->second, m_DebugMode,
+            "setting Tolerance in call to CompressZfp class Transform\n");
+
+        zfp_stream_set_accuracy(stream, tolerance);
+    }
+    else if (hasRate)
+    {
+        const double rate = StringToDouble(
+            itRate->second, m_DebugMode,
+            "setting Rate in call to CompressZfp class Transform\n");
+        // TODO support last argument write random access?
+        zfp_stream_set_rate(stream, rate, GetZfpType(type),
+                            static_cast<unsigned int>(dimensions.size()), 0);
+    }
+    else if (hasPrecision)
+    {
+        const unsigned int precision = StringToUInt(
+            itPrecision->second, m_DebugMode,
+            "setting Precision in call to CompressZfp class Transform\n");
+        zfp_stream_set_precision(stream, precision);
+    }
+
+    return stream;
+}
+
+} // end namespace transform
+} // end namespace adios2
diff --git a/source/adios2/transform/compress/CompressZfp.h b/source/adios2/transform/compress/CompressZfp.h
new file mode 100644
index 0000000000000000000000000000000000000000..251d14b455a86b8d7dd86b8bf4cc756e912cd312
--- /dev/null
+++ b/source/adios2/transform/compress/CompressZfp.h
@@ -0,0 +1,101 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * CompressZfp.h : wrapper to Zfp compression library
+ *
+ *  Created on: Jul 25, 2017
+ *      Author: William F Godoy godoywf@ornl.gov
+ */
+
+#ifndef ADIOS2_TRANSFORM_COMPRESS_COMPRESSZFP_H_
+#define ADIOS2_TRANSFORM_COMPRESS_COMPRESSZFP_H_
+
+#include <zfp.h>
+
+#include "adios2/core/Transform.h"
+
+namespace adios2
+{
+
+namespace transform
+{
+
+class CompressZfp : public Transform
+{
+
+public:
+    /**
+     * Unique constructor
+     * @param debugMode
+     */
+    CompressZfp(const bool debugMode);
+
+    ~CompressZfp() = default;
+
+    /**
+     * Wrapper around zfp compression
+     * @param dataIn
+     * @param dimensions
+     * @param type
+     * @param bufferOut
+     * @param parameters
+     * @return size of compressed buffer in bytes
+     */
+    size_t Compress(const void *dataIn, const Dims &dimensions,
+                    const size_t elementSize, const std::string type,
+                    void *bufferOut, const Params &parameters) const final;
+
+    /**
+     * Wrapper around zfp decompression
+     * @param bufferIn
+     * @param sizeIn
+     * @param dataOut
+     * @param dimensions
+     * @param type
+     * @return size of decompressed data in dataOut
+     */
+    size_t Decompress(const void *bufferIn, const size_t sizeIn, void *dataOut,
+                      const Dims &dimensions, const std::string type,
+                      const Params &parameters) const final;
+
+private:
+    /**
+     * Returns Zfp supported zfp_type based on adios string type
+     * @param type adios type as string, see GetType<T> in
+     * helper/adiosType.inl
+     * @return zfp_type
+     */
+    zfp_type GetZfpType(const std::string type) const;
+
+    /**
+     * Constructor Zfp zfp_field based on input information around the data
+     * pointer
+     * @param data
+     * @param shape
+     * @param type
+     * @return zfp_field*
+     */
+    zfp_field *GetZFPField(const void *data, const Dims &shape,
+                           const std::string type) const;
+
+    zfp_stream *GetZFPStream(const Dims &dimensions, const std::string type,
+                             const Params &parameters) const;
+
+    size_t DoBufferMaxSize(const void *dataIn, const Dims &dimensions,
+                           const std::string type,
+                           const Params &parameters) const final;
+
+    /**
+     * In debug mode, check status from BZip compression and decompression
+     * functions
+     * @param status returned by BZip2 library
+     * @param hint extra exception information
+     */
+    void CheckStatus(const int status, const std::string hint) const;
+};
+
+} // end namespace transform
+} // end namespace adios2
+
+#endif /* ADIOS2_TRANSFORM_COMPRESS_COMPRESSZFP_H_ */
diff --git a/source/adios2/transform/compression/BZip2.cpp b/source/adios2/transform/compression/BZip2.cpp
deleted file mode 100644
index 89a61737a93408a1d44660cd32bda558be6443cb..0000000000000000000000000000000000000000
--- a/source/adios2/transform/compression/BZip2.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * BZIP2.cpp
- *
- *  Created on: Oct 19, 2016
- *      Author: William F Godoy godoywf@ornl.gov
- */
-
-#include "BZip2.h"
-
-namespace adios2
-{
-namespace transform
-{
-
-BZip2::BZip2() : Transform("bzip2") {}
-
-void BZip2::Compress(const std::vector<char> & /*bufferIn*/,
-                     std::vector<char> & /*bufferOut*/)
-{
-}
-
-void BZip2::Decompress(const std::vector<char> & /*bufferIn*/,
-                       std::vector<char> & /*bufferOut*/)
-{
-}
-
-} // end namespace transform
-} // end namespace adios
diff --git a/source/adios2/transform/compression/BZip2.h b/source/adios2/transform/compression/BZip2.h
deleted file mode 100644
index 1da04ed6d1656e954f5f99f966eca63300a407bc..0000000000000000000000000000000000000000
--- a/source/adios2/transform/compression/BZip2.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Distributed under the OSI-approved Apache License, Version 2.0.  See
- * accompanying file Copyright.txt for details.
- *
- * BZip2.h not yet implemented
- *
- *  Created on: Oct 17, 2016
- *      Author: William F Godoy godoywf@ornl.gov
- */
-
-#ifndef ADIOS2_TRANSFORM_COMPRESSION_BZIP2_H_
-#define ADIOS2_TRANSFORM_COMPRESSION_BZIP2_H_
-
-#include "adios2/ADIOSConfig.h"
-#include "adios2/core/Transform.h"
-
-namespace adios2
-{
-namespace transform
-{
-
-class BZip2 : public Transform
-{
-
-public:
-    /**
-     * Initialize parent method
-     * @param compressionLevel
-     * @param variable
-     */
-    BZip2();
-
-    virtual ~BZip2() = default;
-
-    void Compress(const std::vector<char> &bufferIn,
-                  std::vector<char> &bufferOut);
-
-    void Decompress(const std::vector<char> &bufferIn,
-                    std::vector<char> &bufferOut);
-};
-
-} // end namespace transform
-} // end namespace adios
-
-#endif /* ADIOS2_TRANSFORM_BZIP2_H_ */
diff --git a/testing/adios2/CMakeLists.txt b/testing/adios2/CMakeLists.txt
index 544e4099f8a6d3d309e8d97dbbf80c3deff1c91c..2115e42d9a8d60498548be59448f610ec898ff22 100644
--- a/testing/adios2/CMakeLists.txt
+++ b/testing/adios2/CMakeLists.txt
@@ -7,3 +7,4 @@ add_subdirectory(interface)
 add_subdirectory(engine)
 add_subdirectory(bindings)
 add_subdirectory(xml)
+add_subdirectory(transform)
diff --git a/testing/adios2/bindings/python/CMakeLists.txt b/testing/adios2/bindings/python/CMakeLists.txt
index 8da6af4e7613e9b777cfb092d9c805fa583282f5..96e47759aefee773095c388e50b3db42e08ac9b9 100644
--- a/testing/adios2/bindings/python/CMakeLists.txt
+++ b/testing/adios2/bindings/python/CMakeLists.txt
@@ -3,4 +3,10 @@
 # accompanying file Copyright.txt for details.
 #------------------------------------------------------------------------------#
 
-python_add_test(PythonBPWrite TestBPWriteTypes.py)
+if(NOT ADIOS2_HAVE_MPI)
+    python_add_test(PythonBPWrite TestBPWriteTypes_nompi.py)
+endif()
+
+if(ADIOS2_HAVE_MPI)
+    python_add_test(PythonBPWrite TestBPWriteTypes.py)
+endif()
\ No newline at end of file
diff --git a/testing/adios2/bindings/python/TestBPWriteTypes.py b/testing/adios2/bindings/python/TestBPWriteTypes.py
index 842adacd8cf1e9b87c53a66725ab50d7b3269aef..36cfe7243abae03f2aa12acf9556fec0c345d594 100644
--- a/testing/adios2/bindings/python/TestBPWriteTypes.py
+++ b/testing/adios2/bindings/python/TestBPWriteTypes.py
@@ -10,13 +10,15 @@
 
 
 from adios2NPTypes import SmallTestData
+from mpi4py import MPI
 import adios2
 
 
 # Test data
 data = SmallTestData()
 
-adios = adios2.ADIOS(adios2.DebugON)
+comm = MPI.COMM_WORLD
+adios = adios2.ADIOS(comm, adios2.DebugON)
 
 bpIO = adios.DeclareIO("NPTypes")
 
diff --git a/testing/adios2/bindings/python/TestBPWriteTypes_nompi.py b/testing/adios2/bindings/python/TestBPWriteTypes_nompi.py
new file mode 100644
index 0000000000000000000000000000000000000000..842adacd8cf1e9b87c53a66725ab50d7b3269aef
--- /dev/null
+++ b/testing/adios2/bindings/python/TestBPWriteTypes_nompi.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#
+# TestBPWriteTypes.py: test Python numpy types in ADIOS2 File Write
+#  Created on: Feb 2, 2017
+#      Author: William F Godoy godoywf@ornl.gov
+
+
+from adios2NPTypes import SmallTestData
+import adios2
+
+
+# Test data
+data = SmallTestData()
+
+adios = adios2.ADIOS(adios2.DebugON)
+
+bpIO = adios.DeclareIO("NPTypes")
+
+# ADIOS Variable name, shape, start, offset, constant dims
+# All local variables
+varI8 = bpIO.DefineVariable(
+    "varI8", [], [], [data.I8.size], adios2.ConstantDims)
+varI16 = bpIO.DefineVariable(
+    "varI16", [], [], [data.I16.size], adios2.ConstantDims)
+varI32 = bpIO.DefineVariable(
+    "varI32", [], [], [data.I32.size], adios2.ConstantDims)
+varI64 = bpIO.DefineVariable(
+    "varI64", [], [], [data.I64.size], adios2.ConstantDims)
+
+varU8 = bpIO.DefineVariable(
+    "varUI8", [], [], [data.U8.size], adios2.ConstantDims)
+varU16 = bpIO.DefineVariable(
+    "varUI16", [], [], [data.U16.size], adios2.ConstantDims)
+varU32 = bpIO.DefineVariable(
+    "varUI32", [], [], [data.U32.size], adios2.ConstantDims)
+varU64 = bpIO.DefineVariable(
+    "varUI64", [], [], [data.U64.size], adios2.ConstantDims)
+
+varR32 = bpIO.DefineVariable(
+    "varR32", [], [], [data.R32.size], adios2.ConstantDims)
+
+varR64 = bpIO.DefineVariable(
+    "varR64", [], [], [data.R64.size], adios2.ConstantDims)
+
+
+# ADIOS Engine
+bpFileWriter = bpIO.Open("npTypes.bp", adios2.OpenModeWrite)
+
+bpFileWriter.Write(varI8, data.I8)
+bpFileWriter.Write(varI16, data.I16)
+bpFileWriter.Write(varI32, data.I32)
+bpFileWriter.Write(varI64, data.I64)
+
+bpFileWriter.Write(varU8, data.U8)
+bpFileWriter.Write(varU16, data.U16)
+bpFileWriter.Write(varU32, data.U32)
+bpFileWriter.Write(varU64, data.U64)
+
+bpFileWriter.Write(varR32, data.R32)
+bpFileWriter.Write(varR64, data.R64)
+
+bpFileWriter.Close()
diff --git a/testing/adios2/engine/SmallTestData.h b/testing/adios2/engine/SmallTestData.h
index d7f736582dabc3eedc9c377973461e5578cc1260..05de0729e8e7fdf1ba957942892a24a945722082 100644
--- a/testing/adios2/engine/SmallTestData.h
+++ b/testing/adios2/engine/SmallTestData.h
@@ -10,21 +10,21 @@
 struct SmallTestData
 {
     std::array<char, 10> I8 = {{0, 1, -2, 3, -4, 5, -6, 7, -8, 9}};
-    std::array<int16_t, 10> I16 = {
+    std::array<short, 10> I16 = {
         {512, 513, -510, 515, -508, 517, -506, 519, -504, 521}};
-    std::array<int32_t, 10> I32 = {{131072, 131073, -131070, 131075, -131068,
-                                    131077, -131066, 131079, -131064, 131081}};
-    std::array<int64_t, 10> I64 = {
+    std::array<int, 10> I32 = {{131072, 131073, -131070, 131075, -131068,
+                                131077, -131066, 131079, -131064, 131081}};
+    std::array<long int, 10> I64 = {
         {8589934592, 8589934593, -8589934590, 8589934595, -8589934588,
          8589934597, -8589934586, 8589934599, -8589934584, 8589934601}};
     std::array<unsigned char, 10> U8 = {
         {128, 129, 130, 131, 132, 133, 134, 135, 136, 137}};
-    std::array<uint16_t, 10> U16 = {
+    std::array<unsigned short, 10> U16 = {
         {32768, 32769, 32770, 32771, 32772, 32773, 32774, 32775, 32776, 32777}};
-    std::array<uint32_t, 10> U32 = {
+    std::array<unsigned int, 10> U32 = {
         {2147483648, 2147483649, 2147483650, 2147483651, 2147483652, 2147483653,
          2147483654, 2147483655, 2147483656, 2147483657}};
-    std::array<uint64_t, 10> U64 = {
+    std::array<unsigned long int, 10> U64 = {
         {9223372036854775808UL, 9223372036854775809UL, 9223372036854775810UL,
          9223372036854775811UL, 9223372036854775812UL, 9223372036854775813UL,
          9223372036854775814UL, 9223372036854775815UL, 9223372036854775816UL,
diff --git a/testing/adios2/interface/CMakeLists.txt b/testing/adios2/interface/CMakeLists.txt
index e229416de28347dbe46931805724e7d05bbdfdb2..e68ccfa6187ab17710e4bca93579ede6ded95079 100644
--- a/testing/adios2/interface/CMakeLists.txt
+++ b/testing/adios2/interface/CMakeLists.txt
@@ -6,4 +6,8 @@
 add_executable(TestADIOSInterfaceWrite TestADIOSInterfaceWrite.cpp)
 target_link_libraries(TestADIOSInterfaceWrite adios2 gtest gtest_main)
 
+add_executable(TestADIOSDefineVariable TestADIOSDefineVariable.cpp)
+target_link_libraries(TestADIOSDefineVariable adios2 gtest gtest_main)
+
 gtest_add_tests(TARGET TestADIOSInterfaceWrite)
+gtest_add_tests(TARGET TestADIOSDefineVariable)
\ No newline at end of file
diff --git a/testing/adios2/interface/TestADIOSDefineVariable.cpp b/testing/adios2/interface/TestADIOSDefineVariable.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..100f05fc4e7df69a6512a749cf7b3cf1eb705260
--- /dev/null
+++ b/testing/adios2/interface/TestADIOSDefineVariable.cpp
@@ -0,0 +1,355 @@
+#include <cstdint>
+
+#include <iostream>
+#include <stdexcept>
+
+#include <adios2.h>
+
+#include <gtest/gtest.h>
+
+class ADIOSDefineVariableTest : public ::testing::Test
+{
+public:
+    ADIOSDefineVariableTest() : adios(true), io(adios.DeclareIO("TestIO")) {}
+
+protected:
+    // virtual void SetUp() { }
+
+    // virtual void TearDown() { }
+
+    adios2::ADIOS adios;
+    adios2::IO &io;
+};
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalValue)
+{
+    // Define ADIOS global value
+    auto &globalvalue = io.DefineVariable<int>("globalvalue");
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalvalue),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalvalue.m_Shape.size(), 0);
+    EXPECT_EQ(globalvalue.m_Start.size(), 0);
+    EXPECT_EQ(globalvalue.m_Count.size(), 0);
+    EXPECT_EQ(globalvalue.m_Name, "globalvalue");
+    EXPECT_EQ(globalvalue.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalValue)
+{
+    // Define ADIOS local value (a value changing across processes)
+    auto &localvalue =
+        io.DefineVariable<int>("localvalue", {adios2::LocalValueDim});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localvalue),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localvalue.m_Shape.size(), 1);
+    EXPECT_EQ(localvalue.m_Shape[0], adios2::LocalValueDim);
+    EXPECT_EQ(localvalue.m_Start.size(), 0);
+    EXPECT_EQ(localvalue.m_Count.size(), 0);
+    EXPECT_EQ(localvalue.m_Name, "localvalue");
+    EXPECT_EQ(localvalue.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArray)
+{
+    // Define ADIOS global array
+    std::size_t n = 50;
+    auto &globalarray = io.DefineVariable<int>("globalarray", {100, n, 30},
+                                               {50, n / 2, 0}, {10, n / 2, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalarray.m_Shape.size(), 3);
+    EXPECT_EQ(globalarray.m_Shape[0], 100);
+    EXPECT_EQ(globalarray.m_Shape[1], n);
+    EXPECT_EQ(globalarray.m_Shape[2], 30);
+    EXPECT_EQ(globalarray.m_Start.size(), 3);
+    EXPECT_EQ(globalarray.m_Start[0], 50);
+    EXPECT_EQ(globalarray.m_Start[1], n / 2);
+    EXPECT_EQ(globalarray.m_Start[2], 0);
+    EXPECT_EQ(globalarray.m_Count.size(), 3);
+    EXPECT_EQ(globalarray.m_Count[0], 10);
+    EXPECT_EQ(globalarray.m_Count[1], n / 2);
+    EXPECT_EQ(globalarray.m_Count[2], 30);
+    EXPECT_EQ(globalarray.m_Name, "globalarray");
+    EXPECT_EQ(globalarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayWithSelections)
+{
+    // Define ADIOS global array with postponed size definition in SetSelection
+    std::size_t n = 50;
+    auto &globalarray = io.DefineVariable<int>("globalarray", {100, n, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalarray),
+                                  adios2::Variable<int> &>();
+
+    // Make a 3D selection to describe the local dimensions of the
+    // variable we write and its offsets in the global spaces
+    adios2::SelectionBoundingBox sel({50, n / 2, 0}, {10, n / 2, 30});
+    globalarray.SetSelection(sel);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalarray.m_Shape.size(), 3);
+    EXPECT_EQ(globalarray.m_Shape[0], 100);
+    EXPECT_EQ(globalarray.m_Shape[1], n);
+    EXPECT_EQ(globalarray.m_Shape[2], 30);
+    EXPECT_EQ(globalarray.m_Start.size(), 3);
+    EXPECT_EQ(globalarray.m_Start[0], 50);
+    EXPECT_EQ(globalarray.m_Start[1], n / 2);
+    EXPECT_EQ(globalarray.m_Start[2], 0);
+    EXPECT_EQ(globalarray.m_Count.size(), 3);
+    EXPECT_EQ(globalarray.m_Count[0], 10);
+    EXPECT_EQ(globalarray.m_Count[1], n / 2);
+    EXPECT_EQ(globalarray.m_Count[2], 30);
+    EXPECT_EQ(globalarray.m_Name, "globalarray");
+    EXPECT_EQ(globalarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayConstantDims)
+{
+    // Define ADIOS global array with locked-down dimensions
+    std::size_t n = 50;
+    auto &globalarray = io.DefineVariable<int>(
+        "globalarray", {100, n, 30}, {50, n / 2, 0}, {10, n / 2, 30}, true);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalarray),
+                                  adios2::Variable<int> &>();
+
+    adios2::SelectionBoundingBox sel({50, n / 2, 0}, {10, n / 2, 30});
+    EXPECT_THROW(globalarray.SetSelection(sel), std::invalid_argument);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalarray.m_Shape.size(), 3);
+    EXPECT_EQ(globalarray.m_Shape[0], 100);
+    EXPECT_EQ(globalarray.m_Shape[1], n);
+    EXPECT_EQ(globalarray.m_Shape[2], 30);
+    EXPECT_EQ(globalarray.m_Start.size(), 3);
+    EXPECT_EQ(globalarray.m_Start[0], 50);
+    EXPECT_EQ(globalarray.m_Start[1], n / 2);
+    EXPECT_EQ(globalarray.m_Start[2], 0);
+    EXPECT_EQ(globalarray.m_Count.size(), 3);
+    EXPECT_EQ(globalarray.m_Count[0], 10);
+    EXPECT_EQ(globalarray.m_Count[1], n / 2);
+    EXPECT_EQ(globalarray.m_Count[2], 30);
+    EXPECT_EQ(globalarray.m_Name, "globalarray");
+    EXPECT_EQ(globalarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayInvalidLocalValueDim)
+{
+    // Define ADIOS global array
+    std::size_t n = 50;
+    adios2::Variable<int> *globalarray;
+    EXPECT_THROW(globalarray = &io.DefineVariable<int>(
+                     "globalarray", {100, adios2::LocalValueDim, 30},
+                     {50, n / 2, 0}, {10, n / 2, 30}),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArray)
+{
+    // Define ADIOS local array (no global dimensions, no offsets)
+    std::size_t n = 50;
+    auto &localarray =
+        io.DefineVariable<int>("localarray", {}, {}, {10, n / 2, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 10);
+    EXPECT_EQ(localarray.m_Count[1], n / 2);
+    EXPECT_EQ(localarray.m_Count[2], 30);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArrayWithSelection)
+{
+    // Define ADIOS local array with postponed size definition in SetSelection
+    std::size_t n = 50;
+    auto &localarray = io.DefineVariable<int>(
+        "localarray", {}, {},
+        {adios2::UnknownDim, adios2::UnknownDim, adios2::UnknownDim});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localarray),
+                                  adios2::Variable<int> &>();
+
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 0);
+    EXPECT_EQ(localarray.m_Count[1], 0);
+    EXPECT_EQ(localarray.m_Count[2], 0);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+
+    // Make a 3D selection to describe the local dimensions of the
+    // variable we write
+    adios2::SelectionBoundingBox sel({}, {10, n / 2, 30});
+    localarray.SetSelection(sel);
+
+    adios2::SelectionBoundingBox selbad({50, n / 2, 0}, {10, n / 2, 30});
+    EXPECT_THROW(localarray.SetSelection(selbad), std::invalid_argument);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 10);
+    EXPECT_EQ(localarray.m_Count[1], n / 2);
+    EXPECT_EQ(localarray.m_Count[2], 30);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArrayConstantDims)
+{
+    // Define ADIOS local array with locked down dimensions
+    std::size_t n = 50;
+    auto &localarray =
+        io.DefineVariable<int>("localarray", {}, {}, {10, n / 2, 30}, true);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localarray),
+                                  adios2::Variable<int> &>();
+
+    adios2::SelectionBoundingBox sel({}, {10, n / 2, 30});
+    EXPECT_THROW(localarray.SetSelection(sel), std::invalid_argument);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 10);
+    EXPECT_EQ(localarray.m_Count[1], n / 2);
+    EXPECT_EQ(localarray.m_Count[2], 30);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArrayInvalidOffsets)
+{
+    // Define ADIOS local array but try to add offsets
+    std::size_t n = 50;
+
+    adios2::Variable<int> *localarray;
+    EXPECT_THROW(localarray = &io.DefineVariable<int>(
+                     "localarray", {}, {50, n / 2, 0}, {10, n / 2, 30}),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArrayFirstDim)
+{
+    // Define ADIOS joined array
+    std::size_t n = 50;
+    auto &joinedarray = io.DefineVariable<int>(
+        "joinedarray", {adios2::JoinedDim, n, 30}, {}, {10, n, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(joinedarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(joinedarray.m_Shape.size(), 3);
+    EXPECT_EQ(joinedarray.m_Shape[0], adios2::JoinedDim);
+    EXPECT_EQ(joinedarray.m_Shape[1], n);
+    EXPECT_EQ(joinedarray.m_Shape[2], 30);
+    EXPECT_EQ(joinedarray.m_Start.size(), 0);
+    EXPECT_EQ(joinedarray.m_Count.size(), 3);
+    EXPECT_EQ(joinedarray.m_Count[0], 10);
+    EXPECT_EQ(joinedarray.m_Count[1], n);
+    EXPECT_EQ(joinedarray.m_Count[2], 30);
+    EXPECT_EQ(joinedarray.m_Name, "joinedarray");
+    EXPECT_EQ(joinedarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArraySecondDim)
+{
+    // Define ADIOS joined array
+    std::size_t n = 50;
+    auto &joinedarray = io.DefineVariable<int>(
+        "joinedarray", {n, adios2::JoinedDim, 30}, {0, 0, 0}, {n, 10, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(joinedarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(joinedarray.m_Shape.size(), 3);
+    EXPECT_EQ(joinedarray.m_Shape[0], n);
+    EXPECT_EQ(joinedarray.m_Shape[1], adios2::JoinedDim);
+    EXPECT_EQ(joinedarray.m_Shape[2], 30);
+    EXPECT_EQ(joinedarray.m_Start.size(), 3);
+    EXPECT_EQ(joinedarray.m_Start[0], 0);
+    EXPECT_EQ(joinedarray.m_Start[1], 0);
+    EXPECT_EQ(joinedarray.m_Start[2], 0);
+    EXPECT_EQ(joinedarray.m_Count.size(), 3);
+    EXPECT_EQ(joinedarray.m_Count[0], n);
+    EXPECT_EQ(joinedarray.m_Count[1], 10);
+    EXPECT_EQ(joinedarray.m_Count[2], 30);
+    EXPECT_EQ(joinedarray.m_Name, "joinedarray");
+    EXPECT_EQ(joinedarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArrayTooManyJoinedDims)
+{
+    // Define ADIOS joined array
+    std::size_t n = 50;
+    adios2::Variable<int> *joinedarray;
+    EXPECT_THROW(joinedarray = &io.DefineVariable<int>(
+                     "joinedarray", {n, adios2::JoinedDim, adios2::JoinedDim},
+                     {}, {n, 50, 30}),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArrayInvalidStart)
+{
+    // Define ADIOS joined array
+    std::size_t n = 10;
+    std::size_t WrongValue = 1;
+    adios2::Variable<int> *joinedarray;
+    // Start must be empty or full zero array
+    EXPECT_THROW(
+        joinedarray = &io.DefineVariable<int>(
+            "joinedarray", {adios2::JoinedDim, 50}, {0, WrongValue}, {n, 50}),
+        std::invalid_argument);
+}
+
+int main(int argc, char **argv)
+{
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Init(nullptr, nullptr);
+#endif
+
+    ::testing::InitGoogleTest(&argc, argv);
+    int result = RUN_ALL_TESTS();
+
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Finalize();
+#endif
+
+    return result;
+}
diff --git a/testing/adios2/transform/CMakeLists.txt b/testing/adios2/transform/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1f8111162515c3dbc40533f6ecd31bcc61031413
--- /dev/null
+++ b/testing/adios2/transform/CMakeLists.txt
@@ -0,0 +1,19 @@
+#------------------------------------------------------------------------------#
+# Distributed under the OSI-approved Apache License, Version 2.0.  See
+# accompanying file Copyright.txt for details.
+#------------------------------------------------------------------------------#
+
+
+if(ADIOS2_HAVE_BZip2)
+  add_executable(TestBZip2Wrapper TestBZip2Wrapper.cpp)
+  target_link_libraries(TestBZip2Wrapper adios2 gtest gtest_main)
+
+  gtest_add_tests(TARGET TestBZip2Wrapper)
+endif()
+
+if(ADIOS2_HAVE_ZFP)
+  add_executable(TestZfpWrapper TestZfpWrapper.cpp)
+  target_link_libraries(TestZfpWrapper adios2 gtest gtest_main)
+
+  gtest_add_tests(TARGET TestZfpWrapper)
+endif()
\ No newline at end of file
diff --git a/testing/adios2/transform/TestBZip2Wrapper.cpp b/testing/adios2/transform/TestBZip2Wrapper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..57f506ded62083af2155cf8588df67d454d4db7b
--- /dev/null
+++ b/testing/adios2/transform/TestBZip2Wrapper.cpp
@@ -0,0 +1,125 @@
+#include <cstdint>
+#include <iostream>
+#include <numeric> //std::iota
+#include <stdexcept>
+
+#include <adios2.h>
+
+#include <gtest/gtest.h>
+
+class ADIOSBZip2Wrapper : public ::testing::Test
+{
+public:
+    ADIOSBZip2Wrapper() : adios(true), io(adios.DeclareIO("TestADIOSBZip2")) {}
+
+protected:
+    adios2::ADIOS adios;
+    adios2::IO &io;
+};
+
+TEST_F(ADIOSBZip2Wrapper, UInt100)
+{
+    /** Application variable uints from 0 to 1000 */
+    std::vector<unsigned int> myUInts(100);
+    std::iota(myUInts.begin(), myUInts.end(), 0.f);
+    const std::size_t Nx = myUInts.size();
+    const std::size_t inputBytes = Nx * sizeof(unsigned int);
+
+    // Define ADIOS variable
+    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
+                                                     adios2::ConstantDims);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(var_UInt),
+                                  adios2::Variable<unsigned int> &>();
+
+    // Define bzip2 transform
+    adios2::Transform &adiosBZip2 = adios.GetTransform("BZip2");
+
+    const unsigned int bzip2ID =
+        var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "2"}});
+
+    const std::size_t estimatedSize =
+        adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize);
+    std::vector<char> compressedBuffer(estimatedSize);
+    size_t compressedSize = adiosBZip2.Compress(
+        myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize,
+        var_UInt.m_Type, compressedBuffer.data(),
+        var_UInt.m_TransformsInfo[bzip2ID].Parameters);
+
+    EXPECT_LE(compressedSize, estimatedSize);
+
+    compressedBuffer.resize(compressedSize);
+
+    // Allocate original data size
+    std::vector<unsigned int> decompressedBuffer(Nx);
+    size_t decompressedSize = adiosBZip2.Decompress(
+        compressedBuffer.data(), compressedSize, decompressedBuffer.data(),
+        decompressedBuffer.size() * sizeof(unsigned int));
+
+    // testing data recovery
+    for (size_t i = 0; i < Nx; ++i)
+    {
+        ASSERT_EQ(decompressedBuffer[i], myUInts[i]);
+    }
+}
+
+TEST_F(ADIOSBZip2Wrapper, WrongParameterValue)
+{
+    /** Application variable uints from 0 to 1000 */
+    std::vector<unsigned int> myUInts(100);
+    std::iota(myUInts.begin(), myUInts.end(), 0.f);
+    const std::size_t Nx = myUInts.size();
+    const std::size_t inputBytes = Nx * sizeof(unsigned int);
+
+    // Define ADIOS variable
+    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
+                                                     adios2::ConstantDims);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(var_UInt),
+                                  adios2::Variable<unsigned int> &>();
+
+    // Define bzip2 transform
+    adios2::Transform &adiosBZip2 = adios.GetTransform("BZip2");
+
+    const unsigned int bzip2ID =
+        var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "10"}});
+
+    const std::size_t estimatedSize =
+        adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize);
+    std::vector<char> compressedBuffer(estimatedSize);
+
+    EXPECT_THROW(size_t compressedSize = adiosBZip2.Compress(
+                     myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize,
+                     var_UInt.m_Type, compressedBuffer.data(),
+                     var_UInt.m_TransformsInfo[bzip2ID].Parameters),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSBZip2Wrapper, WrongBZip2Name)
+{
+    /** Application variable uints from 0 to 1000 */
+    std::vector<unsigned int> myUInts(100);
+    std::iota(myUInts.begin(), myUInts.end(), 0.f);
+    const std::size_t Nx = myUInts.size();
+    const std::size_t inputBytes = Nx * sizeof(unsigned int);
+
+    // Define ADIOS variable
+    auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx},
+                                                     adios2::ConstantDims);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(var_UInt),
+                                  adios2::Variable<unsigned int> &>();
+
+    // Check bzip2 lower case and camel case
+    EXPECT_NO_THROW(adios2::Transform &adiosBZip2 =
+                        adios.GetTransform("bzip2"));
+    EXPECT_NO_THROW(adios2::Transform &adiosBZip2 =
+                        adios.GetTransform("BZip2"));
+    EXPECT_THROW(adios2::Transform &adiosBZip2 = adios.GetTransform("bzip"),
+                 std::invalid_argument);
+    EXPECT_THROW(adios2::Transform &adiosBZip2 = adios.GetTransform("BZIP2"),
+                 std::invalid_argument);
+}
diff --git a/testing/adios2/transform/TestZfpWrapper.cpp b/testing/adios2/transform/TestZfpWrapper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..db2a2d2b09a00e91939feb977253952003348c91
--- /dev/null
+++ b/testing/adios2/transform/TestZfpWrapper.cpp
@@ -0,0 +1,123 @@
+#include <cmath> //std::abs
+#include <iostream>
+#include <numeric> //std::iota
+#include <stdexcept>
+
+#include <adios2.h>
+
+#include <gtest/gtest.h>
+
+class ADIOSZfpWrapper : public ::testing::Test
+{
+public:
+    ADIOSZfpWrapper() : adios(true), io(adios.DeclareIO("TestADIOSZfp")) {}
+
+protected:
+    adios2::ADIOS adios;
+    adios2::IO &io;
+};
+
+TEST_F(ADIOSZfpWrapper, Float100)
+{
+    /** Application variable uints from 0 to 1000 */
+    std::vector<float> myFloats(100);
+    std::iota(myFloats.begin(), myFloats.end(), 0.f);
+    const std::size_t Nx = myFloats.size();
+    const std::size_t inputBytes = Nx * sizeof(float);
+
+    // Define ADIOS variable
+    auto &var_Floats = io.DefineVariable<float>("myFloats", {}, {}, {Nx},
+                                                adios2::ConstantDims);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(var_Floats),
+                                  adios2::Variable<float> &>();
+
+    // Define bzip2 transform
+    adios2::Transform &adiosZfp = adios.GetTransform("Zfp");
+
+    const unsigned int zfpID =
+        var_Floats.AddTransform(adiosZfp, {{"Rate", "8"}});
+
+    const std::size_t estimatedSize =
+        adiosZfp.BufferMaxSize(myFloats.data(), var_Floats.m_Count,
+                               var_Floats.m_TransformsInfo[zfpID].Parameters);
+
+    std::vector<char> compressedBuffer(estimatedSize);
+
+    size_t compressedSize = adiosZfp.Compress(
+        myFloats.data(), var_Floats.m_Count, var_Floats.m_ElementSize,
+        var_Floats.m_Type, compressedBuffer.data(),
+        var_Floats.m_TransformsInfo[zfpID].Parameters);
+
+    compressedBuffer.resize(compressedSize);
+
+    // Allocate original data size
+    std::vector<float> decompressedBuffer(Nx);
+
+    size_t decompressedSize = adiosZfp.Decompress(
+        compressedBuffer.data(), compressedBuffer.size(),
+        decompressedBuffer.data(), var_Floats.m_Count, var_Floats.m_Type,
+        var_Floats.m_TransformsInfo[zfpID].Parameters);
+
+    // testing data recovery for rate = 8
+    for (size_t i = 0; i < Nx; ++i)
+    {
+        ASSERT_LT(std::abs(decompressedBuffer[i] - myFloats[i]), 1E-6);
+    }
+}
+
+TEST_F(ADIOSZfpWrapper, UnsupportedCall)
+{
+    /** Application variable uints from 0 to 1000 */
+    std::vector<float> myFloats(100);
+    std::iota(myFloats.begin(), myFloats.end(), 0.f);
+    const std::size_t Nx = myFloats.size();
+    const std::size_t inputBytes = Nx * sizeof(float);
+
+    // Define ADIOS variable
+    auto &var_Floats = io.DefineVariable<float>("myFloats", {}, {}, {Nx},
+                                                adios2::ConstantDims);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(var_Floats),
+                                  adios2::Variable<float> &>();
+
+    // Define bzip2 transform
+    adios2::Transform &adiosZfp = adios.GetTransform("zfp");
+
+    const unsigned int zfpID =
+        var_Floats.AddTransform(adiosZfp, {{"Rate", "8"}});
+
+    // Wrong signature for Zfp
+    EXPECT_THROW(const std::size_t estimatedSize =
+                     adiosZfp.BufferMaxSize(Nx * var_Floats.m_ElementSize),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSZfpWrapper, MissingMandatoryParameter)
+{
+    /** Application variable uints from 0 to 1000 */
+    std::vector<float> myFloats(100);
+    std::iota(myFloats.begin(), myFloats.end(), 0.f);
+    const std::size_t Nx = myFloats.size();
+    const std::size_t inputBytes = Nx * sizeof(float);
+
+    // Define ADIOS variable
+    auto &var_Floats = io.DefineVariable<float>("myFloats", {}, {}, {Nx},
+                                                adios2::ConstantDims);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(var_Floats),
+                                  adios2::Variable<float> &>();
+
+    // Define bzip2 transform
+    adios2::Transform &adiosZfp = adios.GetTransform("zfp");
+
+    const unsigned int zfpID = var_Floats.AddTransform(adiosZfp);
+
+    EXPECT_THROW(const std::size_t estimatedSize = adiosZfp.BufferMaxSize(
+                     myFloats.data(), var_Floats.m_Count,
+                     var_Floats.m_TransformsInfo[zfpID].Parameters),
+                 std::invalid_argument);
+}
diff --git a/testing/adios2/xml/TestXMLConfig.cpp b/testing/adios2/xml/TestXMLConfig.cpp
index 16b45d2f3f551ddc930097dad64f09b9b5e98f1d..5d3cb161b01080cd33a19083516deba70d3caaaa 100644
--- a/testing/adios2/xml/TestXMLConfig.cpp
+++ b/testing/adios2/xml/TestXMLConfig.cpp
@@ -51,6 +51,20 @@ TEST_F(XMLConfigTest, TwoIOs)
     });
 }
 
+TEST_F(XMLConfigTest, TwoEnginesException)
+{
+    std::string configFile = configDir + "/config2.xml";
+
+#ifdef ADIOS2_HAVE_MPI
+    EXPECT_THROW(
+        adios2::ADIOS adios(configFile, MPI_COMM_WORLD, adios2::DebugON),
+        std::invalid_argument);
+#else
+    EXPECT_THROW(adios2::ADIOS adios(configFile, adios2::DebugON),
+                 std::invalid_argument);
+#endif
+}
+
 int main(int argc, char **argv)
 {
 #ifdef ADIOS2_HAVE_MPI
diff --git a/testing/adios2/xml/config2.xml b/testing/adios2/xml/config2.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c26d2ec852400e34cf12d287ad3cbdf2b2b18672
--- /dev/null
+++ b/testing/adios2/xml/config2.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<adios-config>
+    <io name="Test IO 2">
+        <engine type="BPFileWriter" />
+        <engine type="Other" /> <!-- std::invalid_argument exception -->
+    </io>
+</adios-config>