diff --git a/Makefile b/Makefile
index 0581afa17e57133858bfc748cb81c681fb987621..ea705d1d4e18a4eb215cd4dcc5b7fe35e7ccba2d 100644
--- a/Makefile
+++ b/Makefile
@@ -4,12 +4,24 @@
      
 #DEFAULT COMPILERS IN PATH, LIBS will be modified in Makefile.libs
 CC:=g++
-AR:=ar
 MPICC:=mpic++
 LIBS:=
 
+SHARED:=no
 CFLAGS:=-c -Wall -Wpedantic -std=c++11 -O0 -g
-ARFLAGS:=rcs
+LINKERMPI:=ar
+LINKERNoMPI:=ar
+LINKERFLAGS:= rcs
+LIBEXT:=a
+
+ifeq ($(SHARED),yes)
+	CFLAGS+= -fPIC
+	LINKERMPI=$(MPICC) 
+	LINKERNoMPI=$(CC)
+	LINKERFLAGS= -shared -o
+	LIBEXT=so
+endif
+
 
 #ADIOS 
 HFiles:=$(shell find ./include -type f -name "*.h")
@@ -38,23 +50,23 @@ all: mpi nompi
 
 mpi: $(HFiles) $(OBJMPI)
 	@( mkdir -p ./lib );
-	$(AR) $(ARFLAGS) ./lib/libadios.a $(OBJMPI)
-	@echo "Finished building MPI library lib/libadios.a";
+	$(LINKERMPI) $(LINKERFLAGS) ./lib/libadios.$(LIBEXT) $(OBJMPI)
+	@echo "Finished building MPI library ./lib/libadios.$(LIBEXT)";
 	@echo
     
 ./bin/mpi/%.o: %.cpp $(HFiles)
 	@( mkdir -p ./bin/mpi );
-	$(MPICC) $(CFLAGS) -DHAVE_MPI $(INC) -o $@ $<
+	$(MPICC) $(CFLAGS) $(INC) -o $@ $<
 
 nompi: $(HFiles) $(OBJNoMPI)
 	@( mkdir -p ./lib );
-	$(AR) $(ARFLAGS) ./lib/libadios_nompi.a $(OBJNoMPI)
-	@echo "Finished building noMPI library lib/libadios_nompi.a";
+	$(LINKERNoMPI) $(LINKERFLAGS) ./lib/libadios_nompi.$(LIBEXT) $(OBJNoMPI)
+	@echo "Finished building noMPI library ./lib/libadios.$(LIBEXT)";
 	@echo
 
 ./bin/nompi/%.o: %.cpp $(HFiles)
 	@( mkdir -p ./bin/nompi );
-	$(CC) $(CFLAGS) $(INC) -o $@ $<
+	$(CC) $(CFLAGS) $(INC) -DADIOS_NOMPI -o $@ $<
 	
 clean:
-	rm ./bin/mpi/*.o ./lib/libadios.a ./bin/nompi/*.o ./lib/libadios_nompi.a	
+	rm ./bin/mpi/*.o ./bin/nompi/*.o ./lib/*	
diff --git a/include/ADIOS.h b/include/ADIOS.h
index 3671e22bda8ce87e6988f6a56f7a6cabdf23bf09..e6d51dcc91f4d69a72d091373a343ab06b349c7b 100644
--- a/include/ADIOS.h
+++ b/include/ADIOS.h
@@ -18,10 +18,10 @@
 #include <complex>
 /// \endcond
 
-#ifdef HAVE_MPI
-  #include <mpi.h>
-#else
+#ifdef ADIOS_NOMPI
   #include "mpidummy.h"
+#else
+  #include <mpi.h>
 #endif
 
 #include "core/Transform.h"
@@ -58,6 +58,14 @@ class ADIOS
 
 public: // PUBLIC Constructors and Functions define the User Interface with ADIOS
 
+
+    MPI_Comm m_MPIComm = MPI_COMM_SELF; ///< only used as reference to MPI communicator passed from parallel constructor, MPI_Comm is a pointer itself. Public as called from C
+
+    int m_RankMPI = 0; ///< current MPI rank process
+    int m_SizeMPI = 1; ///< current MPI processes size
+
+    std::string m_HostLanguage = "C++";
+
     /**
      * @brief ADIOS empty constructor. Used for non XML config file API calls.
      */
@@ -91,6 +99,7 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO
 
     ~ADIOS( ); ///< empty, using STL containers for memory management
 
+    void InitMPI( ); ///< sets rank and size in m_rank and m_Size, respectively.
 
      /**
      * Look for template specialization
@@ -121,9 +130,10 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO
                                               const Dims globalOffsets = Dims() )
     {
         CheckVariableInput( name, dimensions );
-        m_Compound.emplace_back( name, sizeof(T), dimensions, globalDimensions, globalOffsets, m_DebugMode );
-        m_Variables.emplace( name, std::make_pair( GetType<T>(), m_Compound.size()-1 ) );
-        return m_Compound.back();
+        const unsigned int size = m_Compound.size();
+        m_Compound.emplace( size, VariableCompound( name, sizeof(T), dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+        m_Variables.emplace( name, std::make_pair( GetType<T>(), size ) );
+        return m_Compound.at( size );
     }
 
     VariableCompound& GetVariableCompound( const std::string name );
@@ -148,51 +158,51 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO
      * @param mpiComm option to modify communicator from ADIOS class constructor
      * @param method looks for corresponding Method object in ADIOS to initialize the engine
      * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent.
-     * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility
+     * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while)
+      * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility
      */
     std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, MPI_Comm mpiComm,
-                                  const Method& method, const IOMode iomode );
+                                  const Method& method, const IOMode iomode, const float timeout_sec = 0.0 );
 
     /**
-     * @brief Open to Read with a timeout value specified. Creates a new engine from previously defined method
+     * @brief Open to Write, Read. Creates a new engine from previously defined method.
+     * Reuses MPI communicator from ADIOS constructor.
      * @param streamName unique stream or file name
      * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or "update"
-     * @param mpiComm option to modify communicator from ADIOS class constructor
-     * @param method looks for corresponding Method object in ADIOS to initialize the engine
+     * @param method contains engine parameters
      * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent.
      * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while)
-     * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility
+      * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility
      */
-    std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, MPI_Comm mpiComm,
-                                  const Method& method, const IOMode iomode,
-                                  const float timeout_sec );
+    std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, 
+    							  const Method& method, const IOMode iomode, const float timeout_sec = 0.0 );
+
+
     /**
-     * @brief Open to Write, Read. Creates a new engine from previously defined method.
-     * Reuses MPI communicator from ADIOS constructor.
+     * Version required by the XML config file implementation, searches method inside ADIOS through a unique name
      * @param streamName unique stream or file name
-     * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or "update"
-     * @param method contains engine parameters
+     * @param accessMode "w" or "write", "r" or "read", "a" or "append"
+     * @param mpiComm mpi Communicator
+     * @param methodName used to search method object inside ADIOS object
      * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent.
+     * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while)
      * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility
      */
-    std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, const Method& method,
-                                  const IOMode iomode );
-
+    std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, MPI_Comm mpiComm,
+                                  const std::string methodName, const IOMode iomode, const float timeout_sec = 0.0 );
 
     /**
-     * @brief Open to Read with a timeout value specified. Creates a new engine from previously defined method
-     * Reuses MPI communicator from ADIOS constructor.
+     * Version required by the XML config file implementation, searches method inside ADIOS through a unique name.
+     * Reuses ADIOS MPI Communicator from constructor.
      * @param streamName unique stream or file name
-     * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or "update"
-     * @param method looks for corresponding Method object in ADIOS to initialize the engine
+     * @param accessMode "w" or "write", "r" or "read", "a" or "append"
+     * @param methodName used to search method object inside ADIOS object
      * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent.
      * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while)
      * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility
      */
-    std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, const Method& method,
-                                  const IOMode iomode,
-                                  const float timeout_sec );
-
+    std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode,
+                                  const std::string methodName, const IOMode iomode, const float timeout_sec = 0.0 );
 
     /**
      * @brief Open to Read all steps from a file. No streaming, advancing is possible here. All steps in the file
@@ -215,7 +225,338 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO
 
 
 
-private: //no const to allow default empty and copy constructors
+protected: //no const to allow default empty and copy constructors
+
+    std::map<unsigned int, Variable<char> > m_Char;
+    std::map<unsigned int, Variable<unsigned char> > m_UChar;
+    std::map<unsigned int, Variable<short> > m_Short;
+    std::map<unsigned int, Variable<unsigned short> > m_UShort;
+    std::map<unsigned int, Variable<int> > m_Int;
+    std::map<unsigned int, Variable<unsigned int> > m_UInt;
+    std::map<unsigned int, Variable<long int> > m_LInt;
+    std::map<unsigned int, Variable<unsigned long int> > m_ULInt;
+    std::map<unsigned int, Variable<long long int> > m_LLInt;
+    std::map<unsigned int, Variable<unsigned long long int> > m_ULLInt;
+    std::map<unsigned int, Variable<float> > m_Float;
+    std::map<unsigned int, Variable<double> > m_Double;
+    std::map<unsigned int, Variable<long double> > m_LDouble;
+    std::map<unsigned int, Variable<std::complex<float>> > m_CFloat;
+    std::map<unsigned int, Variable<std::complex<double>> > m_CDouble;
+    std::map<unsigned int, Variable<std::complex<long double>> > m_CLDouble;
+    std::map<unsigned int, VariableCompound > m_Compound;
+
+    std::string m_ConfigFile; ///< XML File to be read containing configuration information
+    bool m_DebugMode = false; ///< if true will do more checks, exceptions, warnings, expect slower code
+
+    //Variables
+    std::map< std::string, std::pair< std::string, unsigned int > > m_Variables; ///< Makes variable name unique, key: variable name, value: pair.first = type, pair.second = index in corresponding vector of Variable
+
+    std::vector< std::shared_ptr<Transform> > m_Transforms; ///< transforms associated with ADIOS run
+
+
+    /**
+     * @brief List of Methods (engine metadata) defined from either ADIOS XML configuration file or the DeclareMethod function.
+     * <pre>
+     *     Key: std::string unique method name
+     *     Value: Method class
+     * </pre>
+     */
+    std::map< std::string, Method > m_Methods;
+    std::set< std::string > m_EngineNames; ///< set used to check Engine name uniqueness in debug mode
+
+    /**
+     * @brief Checks for group existence in m_Groups, if failed throws std::invalid_argument exception
+     * @param itGroup m_Groups iterator, usually from find function
+     * @param groupName unique name, passed for thrown exception only
+     * @param hint adds information to thrown exception
+     */
+    void CheckVariableInput( const std::string name, const Dims& dimensions ) const;
+
+    /**
+     * Checks for variable name, if not found throws an invalid exception
+     * @param itVariable iterator pointing to the variable name in m_Variables
+     * @param name variable name
+     * @param hint message to be thrown for debugging purporses
+     */
+    void CheckVariableName( std::map< std::string, std::pair< std::string, unsigned int > >::const_iterator itVariable,
+                            const std::string name, const std::string hint ) const;
+
+    /**
+     * @brief Checks for method existence in m_Methods, if failed throws std::invalid_argument exception
+     * @param itMethod m_Methods iterator, usually from find function
+     * @param methodName unique name, passed for thrown exception only
+     * @param hint adds information to thrown exception
+     */
+    void CheckMethod( std::map< std::string, Method >::const_iterator itMethod,
+                      const std::string methodName, const std::string hint ) const;
+
+    template< class T >
+    unsigned int GetVariableIndex( const std::string name )
+    {
+        auto itVariable = m_Variables.find( name );
+        CheckVariableName( itVariable, name, "in call to GetVariable<" + GetType<T>() + ">, or call to GetVariableCompound if <T> = <compound>\n" );
+        return itVariable->second.second;
+    }
+
+};
+
+//template specializations of DefineVariable:
+template<> inline
+Variable<char>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                       const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_Char.size();
+    m_Char.emplace( size, Variable<char>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<char>(), size ) );
+    return m_Char.at( size );
+}
+
+
+template<> inline
+Variable<unsigned char>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_UChar.size();
+    m_UChar.emplace( size, Variable<unsigned char>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<unsigned char>(), size ) );
+    return m_UChar.at( size );
+}
+
+
+template<> inline
+Variable<short>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                        const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_Short.size();
+    m_Short.emplace( size, Variable<short>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<unsigned char>(), size ) );
+    return m_Short.at( size );
+}
+
+
+template<> inline
+Variable<unsigned short>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                 const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_UShort.size();
+    m_UShort.emplace( size, Variable<unsigned short>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<unsigned short>(), size ) );
+    return m_UShort.at( size );
+}
+
+
+template<> inline
+Variable<int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                      const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_Int.size();
+    m_Int.emplace( size, Variable<int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<int>(), size ) );
+    return m_Int.at( size );
+}
+
+
+template<> inline
+Variable<unsigned int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                               const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_UInt.size();
+    m_UInt.emplace( size, Variable<unsigned int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<unsigned int>(), size ) );
+    return m_UInt.at( size );
+}
+
+
+template<> inline
+Variable<long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                           const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_LInt.size();
+    m_LInt.emplace( size, Variable<long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<long int>(), size ) );
+    return m_LInt.at( size );
+}
+
+
+template<> inline
+Variable<unsigned long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                    const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_LInt.size();
+    m_ULInt.emplace( size, Variable<unsigned long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<unsigned long int>(), size ) );
+    return m_ULInt.at( size );
+}
+
+
+template<> inline
+Variable<long long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_LLInt.size();
+    m_LLInt.emplace( size, Variable<long long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<long long int>(), size ) );
+    return m_LLInt.at( size );
+}
+
+
+template<> inline
+Variable<unsigned long long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                         const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_ULLInt.size();
+    m_ULLInt.emplace( size, Variable<unsigned long long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<unsigned long long int>(), size ) );
+    return m_ULLInt.at( size );
+}
+
+template<> inline
+Variable<float>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                        const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_Float.size();
+    m_Float.emplace( size, Variable<float>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<float>(), size ) );
+    return m_Float.at( size );
+}
+
+
+template<> inline
+Variable<double>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                         const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_Double.size();
+    m_Double.emplace( size, Variable<double>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<double>(), size ) );
+    return m_Double.at( size );
+}
+
+
+template<> inline
+Variable<long double>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                              const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_LDouble.size();
+    m_LDouble.emplace( size, Variable<long double>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<long double>(), size ) );
+    return m_LDouble.at( size );
+}
+
+
+template<> inline
+Variable<std::complex<float>>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                      const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_CFloat.size();
+    m_CFloat.emplace( size, Variable<std::complex<float>>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<std::complex<float>>(), size ) );
+    return m_CFloat.at( size );
+}
+
+
+template<> inline
+Variable<std::complex<double>>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                       const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_CDouble.size();
+    m_CDouble.emplace( size, Variable<std::complex<double>>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<std::complex<double>>(), size ) );
+    return m_CDouble.at( size );
+}
+
+
+template<> inline
+Variable<std::complex<long double>>& ADIOS::DefineVariable( const std::string name, const Dims dimensions,
+                                                            const Dims globalDimensions, const Dims globalOffsets )
+{
+    CheckVariableInput( name, dimensions );
+    const unsigned int size = m_CLDouble.size();
+    m_CLDouble.emplace( size, Variable<std::complex<long double>>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) );
+    m_Variables.emplace( name, std::make_pair( GetType<std::complex<long double>>(), size ) );
+    return m_CLDouble.at( size );
+}
+
+
+//Get template specialization
+template<> inline
+Variable<char>& ADIOS::GetVariable( const std::string name )
+{ return m_Char.at( GetVariableIndex<char>(name) ); }
+
+template<> inline
+Variable<unsigned char>& ADIOS::GetVariable( const std::string name )
+{ return m_UChar.at( GetVariableIndex<unsigned char>(name) ); }
+
+template<> inline
+Variable<short>& ADIOS::GetVariable( const std::string name )
+{ return m_Short.at( GetVariableIndex<short>(name) ); }
+
+template<> inline
+Variable<unsigned short>& ADIOS::GetVariable( const std::string name )
+{ return m_UShort.at( GetVariableIndex<unsigned short>(name) ); }
+
+template<> inline
+Variable<int>& ADIOS::GetVariable( const std::string name )
+{ return m_Int.at( GetVariableIndex<int>(name) ); }
+
+template<> inline
+Variable<unsigned int>& ADIOS::GetVariable( const std::string name )
+{ return m_UInt.at( GetVariableIndex<unsigned int>(name) ); }
+
+template<> inline
+Variable<long int>& ADIOS::GetVariable( const std::string name )
+{ return m_LInt.at( GetVariableIndex<unsigned int>(name) ); }
+
+template<> inline
+Variable<unsigned long int>& ADIOS::GetVariable( const std::string name )
+{ return m_ULInt.at( GetVariableIndex<unsigned long int>(name) ); }
+
+template<> inline
+Variable<long long int>& ADIOS::GetVariable( const std::string name )
+{ return m_LLInt.at( GetVariableIndex<long long int>(name) ); }
+
+template<> inline
+Variable<unsigned long long int>& ADIOS::GetVariable( const std::string name )
+{ return m_ULLInt.at( GetVariableIndex<unsigned long long int>(name) ); }
+
+template<> inline
+Variable<float>& ADIOS::GetVariable( const std::string name )
+{ return m_Float.at( GetVariableIndex<float>(name) ); }
+
+template<> inline
+Variable<double>& ADIOS::GetVariable( const std::string name )
+{ return m_Double.at( GetVariableIndex<double>(name) ); }
+
+template<> inline
+Variable<long double>& ADIOS::GetVariable( const std::string name )
+{ return m_LDouble.at( GetVariableIndex<long double>(name) ); }
+
+template<> inline
+Variable<std::complex<float>>& ADIOS::GetVariable( const std::string name )
+{ return m_CFloat.at( GetVariableIndex<std::complex<float>>(name) ); }
+
+template<> inline
+Variable<std::complex<double>>& ADIOS::GetVariable( const std::string name )
+{ return m_CDouble.at( GetVariableIndex<std::complex<double>>(name) ); }
+
+template<> inline
+Variable<std::complex<long double>>& ADIOS::GetVariable( const std::string name )
+{ return m_CLDouble.at( GetVariableIndex<std::complex<long double>>(name) ); }
+
 
 };
 
diff --git a/include/core/Capsule.h b/include/core/Capsule.h
index e7b54b5558b021883bce7a89f7be03d840a9849a..c04680b028f0ce2789f478495f0a09f4ffbd90da 100644
--- a/include/core/Capsule.h
+++ b/include/core/Capsule.h
@@ -39,6 +39,7 @@ public:
      * @param type derived class type
      * @param accessMode 'w':write, 'r':read, 'a':append
      * @param rankMPI current MPI rank
+     * @param debugMode
      */
     Capsule( const std::string type, const std::string accessMode, const int rankMPI, const bool debugMode );
 
diff --git a/include/core/Engine.h b/include/core/Engine.h
index 90c20a019bde84c4080e8696b39eb4da3dc1223e..55dd7aa176cd9ab6258f2f7aed543f9350308be8 100644
--- a/include/core/Engine.h
+++ b/include/core/Engine.h
@@ -1,5 +1,5 @@
 /*
- * Capsule.h
+ * Engine.h
  *
  *  Created on: Nov 7, 2016
  *      Author: wfg
@@ -18,10 +18,10 @@
 #include <complex> //std::complex
 /// \endcond
 
-#ifdef HAVE_MPI
-  #include <mpi.h>
-#else
+#ifdef ADIOS_NOMPI
   #include "mpidummy.h"
+#else
+  #include <mpi.h>
 #endif
 
 #include "ADIOS.h"
@@ -31,7 +31,7 @@
 #include "core/Transform.h"
 #include "core/Transport.h"
 #include "core/Capsule.h"
-
+#include "core/Profiler.h"
 
 namespace adios
 {
@@ -52,6 +52,19 @@ class Engine
 
 public:
 
+
+    MPI_Comm m_MPIComm = MPI_COMM_SELF;
+
+    const std::string m_EngineType; ///< from derived class
+    const std::string m_Name; ///< name used for this engine
+    const std::string m_AccessMode; ///< accessMode for buffers used by this engine
+    const Method& m_Method; ///< associated method containing engine metadata
+
+    int m_RankMPI = 0; ///< current MPI rank process
+    int m_SizeMPI = 1; ///< current MPI processes size
+
+    const std::string m_HostLanguage = "C++"; ///< default host language
+
     /**
      * Unique constructor
      * @param adios
@@ -89,11 +102,11 @@ public:
         throw std::invalid_argument( "ERROR: type not supported for variable " + var->name + " in call to GetVariable\n" );
     }
 
-    /*
+    /**
      * Needed for DataMan Engine
-     * @param callback
+     * @param callback function passed from the user
      */
-    //virtual void SetCallBack( std::function<void( const void*, std::string, std::string, std::string, Dims )> callback );
+    virtual void SetCallBack( std::function<void( const void*, std::string, std::string, std::string, Dims )> callback );
 
     /**
      * Write function that adds static checking on the variable to be passed by values
@@ -125,20 +138,22 @@ public:
      * @param values
      */
     template< class T >
-    void Write( Variable<T>& variable, const T& values )
+    void Write( Variable<T>& variable, const T values )
     {
-        Write( variable, &values );
+        const T val = values;
+        Write( variable, &val );
     }
 
     /**
-     * Single value version using string as variable handlers
+     * Single value version using string as variable handlers, allows rvalues to be passed
      * @param variableName
      * @param values
      */
     template< class T >
-    void Write( const std::string variableName, const T& values )
+    void Write( const std::string variableName, const T values )
     {
-        Write( variableName, &values );
+        const T val = values;
+        Write( variableName, &val );
     }
 
     virtual void Write( Variable<char>& variable,                      const char* values );
@@ -316,7 +331,6 @@ public:
      */
     void PerformReads( PerformReadMode mode );
 
-
     /**
      * Reader application indicates that no more data will be read from the current stream before advancing.
      * This is necessary to allow writers to advance as soon as possible.
@@ -381,6 +395,41 @@ public:
 
     virtual void Close( const int transportIndex = -1  ) = 0; ///< Closes a particular transport, or all if -1
 
+
+protected:
+
+    ADIOS& m_ADIOS; ///< reference to ADIOS object that creates this Engine at Open
+    std::vector< std::shared_ptr<Transport> > m_Transports; ///< transports managed
+    const bool m_DebugMode = false; ///< true: additional checks, false: by-pass checks
+    unsigned int m_Cores = 1;
+    const std::string m_EndMessage; ///< added to exceptions to improve debugging
+    std::set<std::string> m_WrittenVariables; ///< contains the names of the variables that are being written
+
+    virtual void Init( ); ///< Initialize m_Capsules and m_Transports, called from constructor
+    virtual void InitParameters( ); ///< Initialize parameters from Method, called from Initi in constructor
+    virtual void InitTransports( ); ///< Initialize transports from Method, called from Init in constructor
+
+    /**
+     * Used to verify parameters in m_Method containers
+     * @param itParam iterator to a certain parameter
+     * @param parameters map of parameters, from m_Method
+     * @param parameterName used if exception is thrown to provide debugging information
+     * @param hint used if exception is thrown to provide debugging information
+     */
+    void CheckParameter( const std::map<std::string, std::string>::const_iterator itParam,
+                         const std::map<std::string, std::string>& parameters,
+                         const std::string parameterName,
+                         const std::string hint ) const;
+
+    bool TransportNamesUniqueness( ) const; ///< checks if transport names are unique among the same types (file I/O)
+
+
+    /**
+     * Throws an exception in debug mode if transport index is out of range.
+     * @param transportIndex must be in the range [ -1 , m_Transports.size()-1 ]
+     */
+    void CheckTransportIndex( const int transportIndex );
+
 };
 
 
diff --git a/include/core/Transport.h b/include/core/Transport.h
index cb4d3ea08cc26bf5513a0c8932f160277f53e7a4..1c2c0d0bacec7fb76e4584ab5774723b0c0da8fd 100644
--- a/include/core/Transport.h
+++ b/include/core/Transport.h
@@ -13,12 +13,13 @@
 #include <vector>
 /// \endcond
 
-#ifdef HAVE_MPI
-    #include <mpi.h>
+#ifdef ADIOS_NOMPI
+  #include "mpidummy.h"
 #else
-    #include "mpidummy.h"
+  #include <mpi.h>
 #endif
 
+#include "core/Profiler.h"
 
 
 namespace adios
@@ -34,14 +35,11 @@ public:
     std::string m_AccessMode; ///< from Open
     bool m_IsOpen = false;
 
-    #ifdef HAVE_MPI
-    MPI_Comm m_MPIComm = NULL; ///< only used as reference to MPI communicator passed from parallel constructor, MPI_Comm is a pointer itself. Public as called from C
-    #else
-    MPI_Comm m_MPIComm = 0; ///< only used as reference to MPI communicator passed from parallel constructor, MPI_Comm is a pointer itself. Public as called from C
-    #endif
+    MPI_Comm m_MPIComm = MPI_COMM_SELF;
 
     int m_RankMPI = 0; ///< current MPI rank process
     int m_SizeMPI = 1; ///< current MPI processes size
+    Profiler m_Profiler; ///< collects information about Open and bytes Transport
 
     /**
      * Base constructor that all derived classes pass
@@ -80,10 +78,11 @@ public:
     virtual void Close( ); ///< closes current transport and flushes everything, transport becomes unreachable
 
 
+    virtual void InitProfiler( const std::string accessMode, const Support::Resolutions resolution );
+
 protected:
 
     const bool m_DebugMode = false; ///< if true: additional checks and exceptions
-
 };
 
 
diff --git a/include/core/Variable.h b/include/core/Variable.h
index 81f552ac4c306946ff8dcc65501c1bbc609f60df..ec8c636df6507073bf214f61037af98536a4d020 100644
--- a/include/core/Variable.h
+++ b/include/core/Variable.h
@@ -40,7 +40,7 @@ class Variable : public VariableBase
 public:
 
     const T* m_AppValues = nullptr; ///< pointer to values passed from user in ADIOS Write, it might change in ADIOS Read
-    //std::vector<T> m_Values; ///< Vector variable returned to user, might be used for zero-copy?
+
     std::vector< TransformData > m_Transforms; ///< associated transforms, sequence determines application order, e.g. first Transforms[0] then Transforms[1]. Pointer used as reference (no memory management).
 
     Variable<T>( const std::string name, const Dims dimensions, const Dims globalDimensions, const Dims globalOffsets,
@@ -67,6 +67,40 @@ public:
      *  @return Number of steps
      */
     int GetSteps();
+    
+    void Monitor( std::ostream& logInfo ) const noexcept
+    {
+        logInfo << "Variable: " << m_Name << "\n";
+        logInfo << "Type: " << m_Type << "\n";
+        logInfo << "Size: " << TotalSize() << " elements\n";
+        logInfo << "Payload: " << PayLoadSize() << " bytes\n";
+
+        if( m_AppValues != nullptr )
+        {
+            logInfo << "Values (first 10 or max_size): \n";
+            std::size_t size = TotalSize();
+            if( size > 10 )
+                size = 10;
+
+            if( m_Type.find("complex") != m_Type.npos ) //it's complex
+            {
+                for( unsigned int i = 0; i < size; ++i  )
+                {
+                    logInfo << "( " << std::real( m_AppValues[i] ) << " , " << std::imag( m_AppValues[i] ) << " )  ";
+                }
+            }
+            else
+            {
+                for( unsigned int i = 0; i < size; ++i  )
+                {
+                    logInfo << m_AppValues[i] << " ";
+                }
+            }
+
+            logInfo << " ...";
+        }
+        logInfo << "\n";
+    }
 
 };
 
diff --git a/src/ADIOS.cpp b/src/ADIOS.cpp
index 0b05d9de871d9d53977bca51006874b2ab2c658f..0d4eefce363ebd94c2edb9b7b0fbba9061e421ea 100644
--- a/src/ADIOS.cpp
+++ b/src/ADIOS.cpp
@@ -13,13 +13,11 @@
 /// \endcond
 
 #include "ADIOS.h"
-
-
 #include "functions/adiosFunctions.h"
 
 //Engines
-#include "engine/bp/BPWriter.h"
-#include "engine/bp/BPReader.h"
+#include "engine/bp/BPFileWriter.h"
+#include "engine/bp/BPFileReader.h"
 
 #ifdef HAVE_DATAMAN  //external dependencies
 #include "engine/dataman/DataManWriter.h"
@@ -46,7 +44,8 @@ ADIOS::ADIOS( const std::string configFileName, const bool debugMode ):
 }
 
 
-ADIOS::ADIOS( const std::string xmlConfigFile, const MPI_Comm mpiComm, const bool debugMode  ):
+
+ADIOS::ADIOS( const std::string xmlConfigFile, MPI_Comm mpiComm, const bool debugMode  ):
     m_MPIComm{ mpiComm },
     m_ConfigFile{ xmlConfigFile },
 	m_DebugMode{ debugMode }
@@ -56,7 +55,7 @@ ADIOS::ADIOS( const std::string xmlConfigFile, const MPI_Comm mpiComm, const boo
 }
 
 
-ADIOS::ADIOS( const MPI_Comm mpiComm, const bool debugMode ):
+ADIOS::ADIOS( MPI_Comm mpiComm, const bool debugMode ):
     m_MPIComm{ mpiComm },
     m_DebugMode{ debugMode }
 {
@@ -70,6 +69,13 @@ ADIOS::~ADIOS( )
 
 void ADIOS::InitMPI( )
 {
+    if( m_DebugMode == true )
+    {
+        if( m_MPIComm == MPI_COMM_NULL )
+            throw std::ios_base::failure( "ERROR: engine communicator is MPI_COMM_NULL,"
+                                          " in call to ADIOS Open or Constructor\n" );
+    }
+
     MPI_Comm_rank( m_MPIComm, &m_RankMPI );
     MPI_Comm_size( m_MPIComm, &m_SizeMPI );
 }
@@ -87,7 +93,8 @@ Method& ADIOS::DeclareMethod( const std::string methodName, const std::string ty
 }
 
 
-std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string accessMode, MPI_Comm mpiComm, const Method& method, const unsigned int cores )
+std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string accessMode, MPI_Comm mpiComm,
+                                     const Method& method, const unsigned int cores )
 {
     if( m_DebugMode == true )
     {
@@ -99,16 +106,18 @@ std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string a
 
     const std::string type( method.m_Type );
 
-    const bool isDefaultWriter = ( accessMode == "w" || accessMode == "write" ) && type.empty() ? true : false;
+    const bool isDefaultWriter = ( accessMode == "w" || accessMode == "write" ||
+                                   accessMode == "a" || accessMode == "append" ) && type.empty() ? true : false;
+
     const bool isDefaultReader = ( accessMode == "r" || accessMode == "read" ) && type.empty() ? true : false;
 
-    if( isDefaultWriter || type == "BPWriter" || type == "bpwriter" )
+    if( isDefaultWriter || type == "BPFileWriter" || type == "bpfilewriter" )
     {
-        return std::make_shared<BPWriter>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores );
+        return std::make_shared<BPFileWriter>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores );
     }
     else if( isDefaultReader || type == "BPReader" || type == "bpreader" )
     {
-        return std::make_shared<BPReader>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores );
+        return std::make_shared<BPFileReader>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores );
     }
     else if( type == "SIRIUS" || type == "sirius" || type == "Sirius" )
     {
@@ -176,7 +185,7 @@ std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string a
 
 VariableCompound& ADIOS::GetVariableCompound( const std::string name )
 {
-    return m_Compound[ GetVariableIndex<void>(name) ];
+    return m_Compound.at( GetVariableIndex<void>(name) );
 }
 
 
@@ -227,6 +236,15 @@ void ADIOS::MonitorVariables( std::ostream& logStream )
 
         else if( type == GetType<long double>() )
             GetVariable<long double>( name ).Monitor( logStream );
+
+        else if( type == GetType<std::complex<float>>() )
+            GetVariable<std::complex<float>>( name ).Monitor( logStream );
+
+        else if( type == GetType<std::complex<double>>() )
+            GetVariable<std::complex<double>>( name ).Monitor( logStream );
+
+        else if( type == GetType<std::complex<long double>>() )
+            GetVariable<std::complex<long double>>( name ).Monitor( logStream );
     }
 }
 
diff --git a/src/core/Transport.cpp b/src/core/Transport.cpp
index 1b5cec2861f2bfe84a679828bad1136f9a0c48c4..4bbc1f7439e6f2db0e09859f16b0aecae7697bcb 100644
--- a/src/core/Transport.cpp
+++ b/src/core/Transport.cpp
@@ -37,5 +37,26 @@ void Transport::Close( )
 { }
 
 
+void Transport::InitProfiler( const std::string accessMode, const Support::Resolutions resolution )
+{
+    m_Profiler.m_Timers.emplace_back( "open", Support::Resolutions::mus );
+
+    if( accessMode == "w" || accessMode == "write" )
+        m_Profiler.m_Timers.emplace_back( "write", resolution );
+
+    else if( accessMode == "a" || accessMode == "append" )
+        m_Profiler.m_Timers.emplace_back( "append", resolution );
+
+    else if( accessMode == "r" || accessMode == "read" )
+        m_Profiler.m_Timers.emplace_back( "read", resolution );
+
+    m_Profiler.m_Timers.emplace_back( "close", Support::Resolutions::mus );
+
+    m_Profiler.m_TotalBytes.push_back( 0 );
+    m_Profiler.m_IsActive = true;
+}
+
+
+
 } //end namespace
 
diff --git a/src/mpidummy.cpp b/src/mpidummy.cpp
index 811e90c7b7effed30d683502ec3140fec926e2b7..e58e1b817cdf2756be130428857f0c844079f0f4 100644
--- a/src/mpidummy.cpp
+++ b/src/mpidummy.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
  * ADIOS is freely available under the terms of the BSD license described
  * in the COPYING file in the top level directory of this source distribution.
  *
@@ -9,6 +9,7 @@
    A dummy MPI implementation for the BP READ API, to have an MPI-free version of the API
 */
 /// \cond EXCLUDE_FROM_DOXYGEN
+#define __STDC_FORMAT_MACROS
 #include <stdint.h>
 #include <inttypes.h>
 #include <stdio.h>
@@ -24,7 +25,7 @@
 
 
 
-#if defined(__APPLE__) || defined(__WIN32__) || defined(__CYGWIN__) 
+#if defined(__APPLE__) || defined(__WIN32__) || defined(__CYGWIN__)
 #    define lseek64 lseek
 #    define open64  open
 #endif
@@ -35,16 +36,16 @@ namespace adios
 
 static char mpierrmsg[MPI_MAX_ERROR_STRING];
 
-int MPI_Init(int *argc, char ***argv) 
-{ 
-    mpierrmsg[0] = '\0'; 
-    return MPI_SUCCESS; 
+int MPI_Init(int *argc, char ***argv)
+{
+    mpierrmsg[0] = '\0';
+    return MPI_SUCCESS;
 }
 
-int MPI_Finalize() 
-{ 
-    mpierrmsg[0] = '\0'; 
-    return MPI_SUCCESS; 
+int MPI_Finalize()
+{
+    mpierrmsg[0] = '\0';
+    return MPI_SUCCESS;
 }
 
 int MPI_Initialized( int* flag )
@@ -64,8 +65,8 @@ int MPI_Comm_size(MPI_Comm comm, int *size) { *size = 1; return MPI_SUCCESS; }
 int MPI_Comm_free(MPI_Comm *comm) { *comm = 0; return MPI_SUCCESS; }
 MPI_Comm MPI_Comm_f2c(MPI_Fint comm) { return comm; }
 
-int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, 
-               void *recvbuf, int recvcnt, MPI_Datatype recvtype, 
+int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype,
+               void *recvbuf, int recvcnt, MPI_Datatype recvtype,
                int root, MPI_Comm comm)
 {
   int ier = MPI_SUCCESS;
@@ -97,8 +98,8 @@ int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype,
   return ier ;
 }
 
-int MPI_Gatherv(void *sendbuf, int sendcnt, MPI_Datatype sendtype, 
-                void *recvbuf, int *recvcnts, int *displs, 
+int MPI_Gatherv(void *sendbuf, int sendcnt, MPI_Datatype sendtype,
+                void *recvbuf, int *recvcnts, int *displs,
                 MPI_Datatype recvtype, int root, MPI_Comm comm)
 {
   int ier = MPI_SUCCESS;
@@ -117,8 +118,8 @@ int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
     return MPI_Gather (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, 0, comm);
 }
 
-int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype, 
-               void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, 
+int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype,
+               void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root,
                MPI_Comm comm)
 {
   int ier = MPI_SUCCESS;
@@ -150,7 +151,7 @@ int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype,
   return ier ;
 }
 
-int MPI_Scatterv( void *sendbuf, int *sendcnts, int *displs, 
+int MPI_Scatterv( void *sendbuf, int *sendcnts, int *displs,
                  MPI_Datatype sendtype, void *recvbuf, int recvcnt,
                  MPI_Datatype recvtype,
                  int root, MPI_Comm comm)
@@ -167,10 +168,19 @@ int MPI_Scatterv( void *sendbuf, int *sendcnts, int *displs,
 int MPI_Recv( void *recvbuffer, int count, MPI_Datatype type, int source, int tag, MPI_Comm comm, MPI_Status* status )
 { return 0; }
 
+int MPI_Irecv( void *recvbuffer, int count, MPI_Datatype type, int source, int tag, MPI_Comm comm, MPI_Request* request )
+{ return 0; }
+
 int MPI_Send( void *sendbuffer, int count, MPI_Datatype type, int destination, int tag, MPI_Comm comm )
 { return 0; }
 
-int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh) 
+int MPI_Isend( void *recvbuffer, int count, MPI_Datatype type, int source, int tag, MPI_Comm comm, MPI_Request* request )
+{ return 0; }
+
+int MPI_Wait( MPI_Request* request, MPI_Status* status )
+{ return 0; }
+
+int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh)
 {
     *fh = open64 (filename, amode);
     if (*fh == -1) {
@@ -214,15 +224,15 @@ int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence)
     return MPI_SUCCESS;
 }
 
-int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count) 
-{ 
+int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count)
+{
     *count = (int) *status;
     return MPI_SUCCESS;
 }
 
 int MPI_Error_string(int errorcode, char *string, int *resultlen)
 {
-    //sprintf(string, "Dummy lib does not know error strings. Code=%d\n",errorcode); 
+    //sprintf(string, "Dummy lib does not know error strings. Code=%d\n",errorcode);
     strcpy(string, mpierrmsg);
     *resultlen = strlen(string);
     return MPI_SUCCESS;
@@ -233,7 +243,7 @@ double MPI_Wtime()
     // Implementation not tested
     struct timeval tv;
     gettimeofday (&tv, NULL);
-    return (double)(tv.tv_sec) + (double)(tv.tv_usec) / 1000000;    
+    return (double)(tv.tv_sec) + (double)(tv.tv_usec) / 1000000;
 }
 
 int MPI_Get_processor_name (char *name, int *resultlen)