From 3397c5e54d08f5571beb46e8b35cd9c3f62d9e4d Mon Sep 17 00:00:00 2001
From: wfg <wfg@pc0098504.ornl.gov>
Date: Thu, 13 Oct 2016 18:02:05 -0400
Subject: [PATCH] Ready to start testing hello Transport MPI and nonMPI POSIX
 methods.

Warning: Makefile only compiling for all, not nompi or mpi
---
 Makefile                                  |  42 ++---
 doc/Doxyfile                              |  14 +-
 examples/hello/helloADIOS_nompi.cpp       |   2 +-
 examples/hello/writer2Groups.xml          |  72 +++++++++
 include/ADIOS.h                           |  16 +-
 include/ADIOSFunctions.h                  |  15 ++
 include/CGroup.h                          |  65 +++++++-
 include/CTransport.h                      |  11 +-
 include/CVariable.h                       |   7 +-
 include/SSupport.h                        |  23 +--
 include/mpi/transport/CPOSIXMPI.h         |   2 +-
 include/mpi/transport/CTransportMPI.h     |   2 +-
 include/nompi/transport/CPOSIXNoMPI.h     |   2 +-
 include/nompi/transport/CTransportNoMPI.h |   2 +-
 src/ADIOS.cpp                             |  50 ++++--
 src/ADIOSFunctions.cpp                    | 177 +++++++++++++++++-----
 src/CGroup.cpp                            |  51 ++++++-
 src/mpi/transport/CPOSIXMPI.cpp           |   2 +-
 src/nompi/transport/CPOSIXNoMPI.cpp       |   2 +-
 19 files changed, 437 insertions(+), 120 deletions(-)
 create mode 100644 examples/hello/writer2Groups.xml

diff --git a/Makefile b/Makefile
index bf31f7bae..000cffe96 100644
--- a/Makefile
+++ b/Makefile
@@ -22,56 +22,46 @@ ADIOS_INC=-I./include
 INCLUDE=$(ADIOS_INC)
 
 #Build Header Dependencies, if one changes it will rebuild
-MPI_HFiles=$(shell find ./include/mpi/ -type f -name "*MPI.h")
-NoMPI_HFiles=$(shell find ./include/nompi/ -type f -name "*NoMPI.h")
-Local_HFiles=$(shell find ./include/ -type f -name "*.h")
+MPI_HFiles=$(shell find ./include/mpi -type f -name "*MPI.h")
+NoMPI_HFiles=$(shell find ./include/nompi -type f -name "*NoMPI.h")
+Local_HFiles=$(shell find ./include -type f -name "*.h")
 HFiles=$(MPI_HFiles) $(NoMPI_HFiles) $(Local_HFiles)
 
 #Source *.cpp Files and Object Files
-MPI_CPPFiles=$(shell find ./src/mpi/ -type f -name "*MPI.cpp")
+MPI_CPPFiles=$(shell find ./src/mpi -type f -name "*MPI.cpp")
 MPI_ObjFiles=$(patsubst ./src/mpi/transport/%.cpp, ./bin/%.o, $(MPI_CPPFiles))
 
-NoMPI_CPPFiles=$(shell find ./src/nompi/ -type f -name "*NoMPI.cpp")
+NoMPI_CPPFiles=$(shell find ./src/nompi -type f -name "*NoMPI.cpp")
 NoMPI_ObjFiles=$(patsubst ./src/nompi/transport/%.cpp, ./bin/%.o, $(NoMPI_CPPFiles))
 
+Common_CPPFiles=$(wildcard ./src/*.cpp)
+Common_ObjFiles=$(patsubst ./src/%.cpp, ./bin/%.o, $(Common_CPPFiles))
+ 
+
 ObjFiles=$(MPI_ObjFiles) $(NoMPI_ObjFiles)
 
 
 #Build all MPI and noMPI
-all: $(MPI_ObjFiles) $(NoMPI_ObjFiles) ./bin/ADIOS.o ./bin/ADIOSFunctions.o $(HFiles)
-	@echo "ADIOS MPI headers" $(MPI_HFiles);
-	@echo "ADIOS No MPI headers" $(NoMPI_HFiles);
+all: $(MPI_ObjFiles) $(NoMPI_ObjFiles) $(Common_ObjFiles) $(HFiles)
 	$(AR) rcs ./lib/libadios.a $(MPI_ObjFiles) $(NoMPI_ObjFiles) ./bin/ADIOS.o ./bin/ADIOSFunctions.o ./bin/CGroup.o
 
 #MPI build    
-mpi: $(MPI_ObjFiles) ./bin/ADIOS.o $(MPI_HFiles) $(Local_HFiles)
+mpi: $(MPI_ObjFiles) $(Common_ObjFiles) $(MPI_HFiles) $(Local_HFiles)
 	$(AR) rcs ./lib/libadios.a $(MPI_ObjFiles) ./bin/ADIOS.o ./bin/ADIOSFunctions.o ./bin/CGroup.o
 	
 ./bin/%.o: ./src/mpi/transport/%.cpp
 	$(MPICC) $(CFLAGS) -DHAVE_MPI $(INCLUDE) -o $@ $< 
-
-./bin/ADIOS.o: ./src/ADIOS.cpp
+	
+./bin/%.o: ./src/%.cpp
 	$(MPICC) $(CFLAGS) -DHAVE_MPI $(INCLUDE) -o $@ $<
-
     
 #NoMPI build    
-nompi: $(NoMPI_ObjFiles) ./bin/ADIOS_nompi.o ./bin/ADIOSFunctions.o ./bin/CGroup.o $(NoMPI_HFiles) $(Local_HFiles)
-	$(AR) rcs ./lib/libadios_nompi.a $(NoMPI_ObjFiles) ./bin/ADIOS_nompi.o ./bin/ADIOSFunctions.o ./bin/CGroup.o
+nompi: $(NoMPI_ObjFiles) $(Common_ObjFiles) $(NoMPI_HFiles) $(Local_HFiles)
+	$(AR) rcs ./lib/libadios_nompi.a $(NoMPI_ObjFiles) $(Common_ObjFiles)
 	
 ./bin/%.o: ./src/nompi/transport/%.cpp $(NoMPI_HFiles) $(Local_HFiles)
 	$(CC) $(CFLAGS) $(INCLUDE) -o $@ $<
-	
-./bin/ADIOS_nompi.o: ./src/ADIOS.cpp $(NoMPI_HFiles) $(Local_HFiles)
-	$(CC) $(CFLAGS) $(INCLUDE) -o $@ $<
-
-
-#Local common files
-./bin/ADIOSFunctions.o: ./src/ADIOSFunctions.cpp $(NoMPI_HFiles) $(Local_HFiles)
-	$(CC) $(CFLAGS) $(INCLUDE) -o $@ $<
-	
-./bin/CGroup.o: ./src/CGroup.cpp $(NoMPI_HFiles) $(Local_HFiles)
-	$(CC) $(CFLAGS) $(INCLUDE) -o $@ $<
-    
+	    
 clean:
 	rm ./bin/*.o ./lib/libadios.a ./lib/libadios_nompi.a
 	
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 0b9aae509..f4d1ec3b4 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -434,7 +434,7 @@ EXTRACT_PACKAGE = NO
 # included in the documentation.
 # The default value is: NO.
 
-EXTRACT_STATIC = YES
+EXTRACT_STATIC = NO
 
 # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
 # locally in source files will be included in the documentation. If set to NO,
@@ -771,7 +771,7 @@ WARN_LOGFILE =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT = /home/wfg/workspace/ADIOSPP/include /home/wfg/workspace/ADIOSPP/include/mpi/transport /home/wfg/workspace/ADIOSPP/include/nompi/transport
+INPUT = /home/wfg/workspace/ADIOSPP/include /home/wfg/workspace/ADIOSPP/include/mpi/transport /home/wfg/workspace/ADIOSPP/include/nompi/transport /home/wfg/workspace/ADIOSPP/src /home/wfg/workspace/ADIOSPP/src/mpi/transport /home/wfg/workspace/ADIOSPP/src/nompi/transport 
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -2218,7 +2218,7 @@ GROUP_GRAPHS = YES
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-UML_LOOK = NO
+UML_LOOK = YES
 
 # If the UML_LOOK tag is enabled, the fields and methods are shown inside the
 # class node. If there are many fields or methods and many nodes the graph may
@@ -2239,7 +2239,7 @@ UML_LIMIT_NUM_FIELDS = 10
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-TEMPLATE_RELATIONS = NO
+TEMPLATE_RELATIONS = YES
 
 # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
 # YES then doxygen will generate a graph for each documented file showing the
@@ -2281,7 +2281,7 @@ CALL_GRAPH = YES
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-CALLER_GRAPH = NO
+CALLER_GRAPH = YES
 
 # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
 # hierarchy of all classes instead of a textual one.
@@ -2339,7 +2339,7 @@ DOT_PATH =
 # command).
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-DOTFILE_DIRS = 
+DOTFILE_DIRS = /home/wfg/workspace/ADIOSPP/include /home/wfg/workspace/ADIOSPP/include/mpi/transport /home/wfg/workspace/ADIOSPP/include/nompi/transport 
 
 # The MSCFILE_DIRS tag can be used to specify one or more directories that
 # contain msc files that are included in the documentation (see the \mscfile
@@ -2388,7 +2388,7 @@ DOT_GRAPH_MAX_NODES = 50
 # Minimum value: 0, maximum value: 1000, default value: 0.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-MAX_DOT_GRAPH_DEPTH = 0
+MAX_DOT_GRAPH_DEPTH = 3
 
 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
 # background. This is disabled by default, because dot on Windows does not seem
diff --git a/examples/hello/helloADIOS_nompi.cpp b/examples/hello/helloADIOS_nompi.cpp
index e617aeef3..e01949eaa 100644
--- a/examples/hello/helloADIOS_nompi.cpp
+++ b/examples/hello/helloADIOS_nompi.cpp
@@ -18,7 +18,7 @@ int main( int argc, char* argv [] )
     {
         adios::ADIOS adiosFile( "writer2Groups.xml" ); //testing with CPOSIXNoMPI
         adiosFile.Init( );
-        adiosFile.MonitorGroups( );
+        adiosFile.MonitorGroups( std::cout );
         std::cout << "Finished initializing ADIOS\n";
     }
     catch( std::exception& e )
diff --git a/examples/hello/writer2Groups.xml b/examples/hello/writer2Groups.xml
new file mode 100644
index 000000000..d019bdfdc
--- /dev/null
+++ b/examples/hello/writer2Groups.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<adios-config host-language="Fortran">
+  <adios-group name="writer2D">
+
+    <var name="nproc" path="/info" type="integer"/>
+    <attribute name="description" path="/info/nproc" value="Number of writers"/>
+    <var name="npx"   path="/info" type="integer"/>
+    <attribute name="description" path="/info/npx" value="Number of processors in x dimension"/>
+    <var name="npy"   path="/info" type="integer"/>
+    <attribute name="description" path="/info/npy" value="Number of processors in y dimension"/>
+
+    <var name="gdx"  type="integer"/>
+    <attribute name="description" path="/gdx" value="Global array size in x dimension"/>
+    <var name="gdy"  type="integer"/>
+    <attribute name="description" path="/gdy" value="Global array size in y dimension"/>
+
+    <!-- Auxiliary variables for global array indexing written (overwritten) by each process -->
+    <var name="ox"   type="integer"/>
+    <var name="oy"   type="integer"/>
+    <var name="ldx"  type="integer"/>
+    <var name="ldy"  type="integer"/>
+
+    <!-- 2D array to write with block,block decomposition -->
+    <global-bounds dimensions="gdx,gdy" offsets="ox,oy">
+        <var name="xy" type="double" dimensions="ldx,ldy"/>
+    </global-bounds>
+    <attribute name="description" path="/xy" 
+               value="2D array with 2D decomposition"/>
+
+  </adios-group>
+
+  <!-- Use transport method 
+       DATASPACES for staging data in memory coupling or
+       FLEXPATH   for socket based staging between applications
+       MPI        for file-based coupling
+  -->
+  <!--transport group="writer2D" method="MPI">verbose=2</transport-->
+  <!--transport group="writer2D" method="DATASPACES">verbose=3</transport-->
+  <transport group="writer2D" method="DIMES">verbose=3</transport>
+  <!--transport group="writer2D" method="FLEXPATH">QUEUE_SIZE=10;verbose=3</transport-->
+  <adios-group name="writer3D">
+
+    <var name="nproc" path="/info" type="integer"/>
+    <attribute name="description" path="/info/nproc" value="Number of writers"/>
+    <var name="npx"   path="/info" type="integer"/>
+    <attribute name="description" path="/info/npx" value="Number of processors in x dimension"/>
+    <var name="npy"   path="/info" type="integer"/>
+    <attribute name="description" path="/info/npy" value="Number of processors in y dimension"/>
+
+    <var name="gdx"  type="integer"/>
+    <attribute name="description" path="/gdx" value="Global array size in x dimension"/>
+    <var name="gdy"  type="integer"/>
+    <attribute name="description" path="/gdy" value="Global array size in y dimension"/>
+
+    <!-- Auxiliary variables for global array indexing written (overwritten) by each process -->
+    <var name="ox"   type="integer"/>
+    <var name="oy"   type="integer"/>
+    <var name="ldx"  type="integer"/>
+    <var name="ldy"  type="integer"/>
+
+    <!-- 2D array to write with block,block decomposition -->
+    <global-bounds dimensions="gdx,gdy" offsets="ox,oy">
+        <var name="xy" type="double" dimensions="ldx,ldy"/>
+    </global-bounds>
+    <attribute name="description" path="/xy" 
+               value="2D array with 2D decomposition"/>
+
+  </adios-group>
+
+  <buffer size-MB="40" allocate-time="now"/>
+
+</adios-config>
diff --git a/include/ADIOS.h b/include/ADIOS.h
index be8e79247..825bb0dbe 100644
--- a/include/ADIOS.h
+++ b/include/ADIOS.h
@@ -10,6 +10,7 @@
 
 #include <string>
 #include <memory>
+#include <ostream>
 
 #ifdef HAVE_MPI
   #include <mpi.h>
@@ -78,16 +79,21 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO
      */
     unsigned long int GroupSize( const std::string groupName ) const;
 
-
     /**
      * Submits a data element values for writing and associates it with the given variableName
+     * @param groupName name of group that owns the variable
      * @param variableName name of existing scalar or vector variable in the XML file or created with CreateVariable
      * @param values pointer to the variable values passed from the user application, use dynamic_cast to check that pointer is of the same value type
      */
     template<class T>
     void Write( const std::string groupName, const std::string variableName, const T* values );
 
-    void MonitorGroups( );
+    /**
+     * @brief Dumps groups information to a file stream or standard output.
+     * Note that either the user closes this fileStream or it's closed at the end.
+     * @param logStream either std::cout standard output, or a std::ofstream file
+     */
+    void MonitorGroups( std::ostream& logStream ) const;
 
     void Close( ); // dumps to file?
 
@@ -124,6 +130,12 @@ private:
   #ifdef HAVE_MPI
     void InitMPI( ); ///< called from Init, initialize parallel MPI
   #endif
+
+    /**
+     * Checks for group existence in m_Groups
+     * @param groupName to be checked
+     */
+    void CheckGroup( const std::string groupName );
 };
 
 
diff --git a/include/ADIOSFunctions.h b/include/ADIOSFunctions.h
index 8e20700a2..5b57869fa 100644
--- a/include/ADIOSFunctions.h
+++ b/include/ADIOSFunctions.h
@@ -12,6 +12,10 @@
 #include <vector>
 #include <map>
 
+#ifdef HAVE_MPI
+#include <mpi.h> //Just for MPI_Comm argument in SetMembersMPI
+#endif
+
 #include "CGroup.h"
 
 
@@ -72,6 +76,17 @@ void GetPairsFromTag( const std::string& fileContent, const std::string tag,
 void SetMembers( const std::string& fileContent, std::string& hostLanguage, std::map< std::string, CGroup >& groups );
 
 
+#ifdef HAVE_MPI
+/**
+ * Set members m_Groups and m_HostLanguage from XML file content, called within Init functions
+ * @param fileContent file Content in a single string
+ * @param hostLanguage return the host language from fileContent
+ * @param groups passed returns the map of groups defined in fileContent
+ */
+void SetMembers( const std::string& fileContent, std::string& hostLanguage, std::map< std::string, CGroup >& groups,
+                 const MPI_Comm mpiComm );
+#endif
+
 } //end namespace
 
 
diff --git a/include/CGroup.h b/include/CGroup.h
index a38f98189..018a021df 100644
--- a/include/CGroup.h
+++ b/include/CGroup.h
@@ -12,6 +12,11 @@
 #include <string>
 #include <memory> //for shared_pointer
 #include <vector>
+#include <ostream>
+
+#ifdef HAVE_MPI
+#include <mpi.h> //for MPI_Comm in overloaded SetTransform
+#endif
 
 #include "CVariable.h"
 #include "SAttribute.h"
@@ -37,6 +42,23 @@ public:
 
     ~CGroup( ); ///< Using STL containers
 
+    /**
+     * Opens group and passes fileName and accessMode to m_Transport
+     * @param fileName
+     * @param accessMode
+     */
+    void Open( const std::string fileName, const std::string accessMode = "w" );
+
+
+    /**
+     * Passes variableName and values to m_Transport
+     * @param variableName
+     * @param values
+     */
+    template<class T>
+    void Write( const std::string variableName, const T* values );
+
+
     /**
      * @brief Sets a variable in current Group, name must be unique
      * @param name
@@ -46,7 +68,7 @@ public:
      * @param transform method, format = lib or lib:level, where lib = zlib, bzip2, szip, and level=1:9 . If no level is defined then library default is taken
      */
     void SetVariable( const std::string name, const bool isGlobal, const std::string type,
-                      const std::string dimensionsCSV = {1}, const std::string transform = "" );
+                      const std::string dimensionsCSV = "1", const std::string transform = "" );
 
     /**
      * @brief Sets a variable in current Group
@@ -66,16 +88,34 @@ public:
      */
     void SetGlobalBounds( const std::string dimensionsCSV, const std::string offsetsCSV = "" );
 
+
     /**
-     * Set a transport method for this group
-     * @param transport supported values in SSupport.h TransportMethods
+     * @brief Set a transport method for this group, if existing it will replace current transport method
+     * @param method supported values in SSupport.h TransportMethods
      * @param priority numeric priority for the I/O to schedule this write with others that might be pending
      * @param iteration iterations between writes of a group to gauge how quickly this data should be evacuated from the compute node
-     * @param verbose level
      */
-    void SetTransportMethod( const std::string transport, unsigned int priority = 1, unsigned int iteration=1, unsigned int verbose = 0 );
+    void SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration );
 
-    void MonitorGroup( ); ///< Dumps information about Group variables
+    #ifdef HAVE_MPI
+    /**
+     * @brief MPI version of SetTransport, includes the communicator
+     * @param method supported values in SSupport.h TransportMethods
+     * @param priority numeric priority for the I/O to schedule this write with others that might be pending
+     * @param iteration iterations between writes of a group to gauge how quickly this data should be evacuated from the compute node
+     * @param mpiComm MPI communicator from User->ADIOS->Group
+     */
+    void SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration,
+                       const MPI_Comm mpiComm );
+    #endif
+
+
+    /**
+     * @brief Dumps groups information to a file stream or standard output.
+     * Note that either the user closes this fileStream or it's closed at the end.
+     * @param logStream either std::cout standard output, or a std::ofstream file
+     */
+    void Monitor( std::ostream& logStream ) const; ///< Dumps information about Group variables
 
 
 private:
@@ -93,9 +133,12 @@ private:
     std::vector< std::string > m_GlobalDimensions; ///< from global-bounds in XML File, data in global space
     std::vector< std::string > m_GlobalOffsets; ///< from global-bounds in XML File, data in global space
 
-    std::shared_ptr< CTransport > m_TransportMethod; ///< transport method defined in XML File, using shared pointer as SGroup can be uninitialized
-    std::string m_ActiveMethod;
+    std::shared_ptr< CTransport > m_Transport; ///< transport method defined in XML File, using shared pointer as SGroup can be uninitialized
+    std::string m_ActiveTransport;
 
+    bool m_IsOpen = false; ///< checks if group was opened for operations;
+    std::string m_FileName; ///< associated fileName is the Group is opened.
+    std::string m_AcessMode; ///< file access mode
 
     /**
      * Called from XML constructor
@@ -103,6 +146,12 @@ private:
      * @param groupName returns the groupName from <adios-group name=" "
      */
     void ParseXMLGroup( const std::string& xmlGroup, std::string& groupName );
+
+    /**
+     * Function that checks if transport method is valid, called from overloaded SetTransform functions
+     * @param method transport method to be checked from SSupport
+     */
+    void CheckTransport( const std::string method );
 };
 
 
diff --git a/include/CTransport.h b/include/CTransport.h
index 7f3c31d60..63de67c57 100644
--- a/include/CTransport.h
+++ b/include/CTransport.h
@@ -25,6 +25,8 @@ public:
     const unsigned int m_Priority;
     const unsigned int m_Iteration;
     const bool m_IsUsingMPI;
+    std::string m_FileName;
+    std::string m_AccessMode;
 
     CTransport( const std::string method, const unsigned int priority, const unsigned int iteration,
                 bool isUsingMPI ):
@@ -37,7 +39,14 @@ public:
     virtual ~CTransport( )
     { }
 
-    virtual void Write( CVariable& variable ) = 0;
+
+    void Open( const std::string fileName, const std::string accessMode = "w" )
+    {
+        m_FileName = fileName;
+        m_AccessMode = accessMode;
+    }
+
+    virtual void Write( const CVariable& variable ) = 0;
 };
 
 
diff --git a/include/CVariable.h b/include/CVariable.h
index a1960b17c..5344f3833 100644
--- a/include/CVariable.h
+++ b/include/CVariable.h
@@ -48,7 +48,7 @@ public:
     template<class T, class U> void Set(const U& rhs);
 
 
-//protected:
+//protected: turned off for testing
     bool m_IsGlobal = false;
     std::string m_Type = "NONE"; ///< mandatory, double, float, unsigned integer, integer, etc.
     std::vector<std::string> m_Dimensions = {"1"}; ///< if empty variable is a scalar, else N-dimensional variable
@@ -67,6 +67,7 @@ public:
     /**
      * Template constructor class required for putting CVariable objects as value in a STL map container
      * @param isGlobal
+     * @param type
      * @param dimensionsCSV
      * @param transform
      */
@@ -77,8 +78,10 @@ public:
     ~CVariableTemplate( )
     { }
 
+    T* m_Value; // pointer or no pointer?
+
     const T& Get() const { return m_Value; }
-    T m_Value;
+
 
 };
 
diff --git a/include/SSupport.h b/include/SSupport.h
index 5d4c06831..e07d4399d 100644
--- a/include/SSupport.h
+++ b/include/SSupport.h
@@ -15,9 +15,10 @@
 namespace adios
 {
 
-const std::string Version{"2.00"};
+const std::string c_Version{"2.00"};
 
-const std::set<std::string> HostLanguages {
+
+const std::set<std::string> c_HostLanguages {
     "C",
     "C++",
     "Fortran",
@@ -25,7 +26,7 @@ const std::set<std::string> HostLanguages {
     "Java"
 };
 
-const std::set<std::string> TransportMethods {
+const std::set<std::string> c_Transports {
     "NULL",
     "POSIX",
     "MPI",
@@ -39,14 +40,14 @@ const std::set<std::string> TransportMethods {
     "ICEE"
 };
 
-const std::set<std::string> Tranformations {
+const std::set<std::string> c_Transformations {
     "none",
     "identity",
     "bzip2",
     "isobar"
 };
 
-const std::map<std::string, std::string> DataTypes {
+const std::map<std::string, std::string> c_DataTypes {
     { "unsigned integer", "unsigned int" },
     { "integer", "int" },
     { "real" , "float" },
@@ -55,17 +56,7 @@ const std::map<std::string, std::string> DataTypes {
 };
 
 
-
-
-
-
-
-
-
-
-
-
-}
+} //end namespace
 
 
 #endif /* SSUPPORT_H_ */
diff --git a/include/mpi/transport/CPOSIXMPI.h b/include/mpi/transport/CPOSIXMPI.h
index 3b337e032..db2977e7a 100644
--- a/include/mpi/transport/CPOSIXMPI.h
+++ b/include/mpi/transport/CPOSIXMPI.h
@@ -29,7 +29,7 @@ public:
 
     ~CPOSIXMPI( );
 
-    void Write( CVariable& variable );
+    void Write( const CVariable& variable );
 
 };
 
diff --git a/include/mpi/transport/CTransportMPI.h b/include/mpi/transport/CTransportMPI.h
index d70aeeb2d..77633cd74 100644
--- a/include/mpi/transport/CTransportMPI.h
+++ b/include/mpi/transport/CTransportMPI.h
@@ -32,7 +32,7 @@ public:
     virtual ~CTransportMPI( )
     { }
 
-    virtual void Write( CVariable& variable ) = 0;
+    virtual void Write( const CVariable& variable ) = 0;
 };
 
 
diff --git a/include/nompi/transport/CPOSIXNoMPI.h b/include/nompi/transport/CPOSIXNoMPI.h
index e590b1419..4bd390f8f 100644
--- a/include/nompi/transport/CPOSIXNoMPI.h
+++ b/include/nompi/transport/CPOSIXNoMPI.h
@@ -27,7 +27,7 @@ public:
 
     ~CPOSIXNoMPI( );
 
-    void Write( CVariable& variable );
+    void Write( const CVariable& variable );
 
 };
 
diff --git a/include/nompi/transport/CTransportNoMPI.h b/include/nompi/transport/CTransportNoMPI.h
index f45caeb57..7e212bcdf 100644
--- a/include/nompi/transport/CTransportNoMPI.h
+++ b/include/nompi/transport/CTransportNoMPI.h
@@ -26,7 +26,7 @@ public:
     virtual ~CTransportNoMPI( )
     { }
 
-    virtual void Write( CVariable& variable ) = 0;
+    virtual void Write( const CVariable& variable ) = 0;
 };
 
 
diff --git a/src/ADIOS.cpp b/src/ADIOS.cpp
index 0bba0cdf6..a2b55deba 100644
--- a/src/ADIOS.cpp
+++ b/src/ADIOS.cpp
@@ -62,41 +62,69 @@ void ADIOS::InitNoMPI( )
     std::string xmlFileContent;
     DumpFileToStream( m_XMLConfigFile, xmlFileContent ); //in ADIOSFunctions.h dumps all XML Config File to xmlFileContent
     SetMembers( xmlFileContent, m_HostLanguage,  m_Groups );
-
-    //SetMembersFromXMLConfigFile( xmlFileContent, m_HostLanguage,  m_Groups ); //in ADIOSFunctions.h sets m_HostLanguage and m_Groups
-    //std::cout << "Finishing Initialization";
 }
 
-#ifdef MPI_VERSION
+
+#ifdef HAVE_MPI
 void ADIOS::InitMPI( )
 {
-    std::cout << "Just testing the InitMPI Function\n";
+    int rank;
+    MPI_Comm_rank( m_MPIComm, &rank );
+
+    int xmlFileContentSize; // common
+    std::string xmlFileContent;
+
+    if( rank == 0 )
+    {
+        std::string xmlFileContent;
+        DumpFileToStream( m_XMLConfigFile, xmlFileContent ); //in ADIOSFunctions.h dumps all XML Config File to xmlFileContent
+        xmlFileContentSize = m_XMLConfigFile.size( ) + 1; // add one for the null character
+
+        MPI_Bcast( &xmlFileContentSize, 1, MPI_INT, 0, m_MPIComm  ); //broadcast size
+        MPI_Bcast( (char*)xmlFileContent.c_str(), xmlFileContentSize, MPI_CHAR, 0, m_MPIComm );
+
+        SetMembers( xmlFileContent, m_HostLanguage,  m_Groups );
+    }
+    else
+    {
+        MPI_Bcast( &xmlFileContentSize, 1, MPI_INT, 0, m_MPIComm  ); //broadcast size
+        char* xmlFileContentMPI = new char[ xmlFileContentSize ]; //allocate C char
+        MPI_Bcast( xmlFileContentMPI, xmlFileContentSize, MPI_CHAR, 0, m_MPIComm ); //receive from rank=0
+
+        xmlFileContent.assign( xmlFileContentMPI );
+        SetMembers( xmlFileContent, m_HostLanguage,  m_Groups );
+    }
 }
 #endif
 
 
 void ADIOS::Open( const std::string groupName, const std::string fileName, const std::string accessMode )
 {
-    //retrieve a group name from m_Groups
-    std::cout << "Just testing the Open function\n";
+    m_Groups.at( groupName ).Open( fileName, accessMode );
 }
 
 
 template<class T> void ADIOS::Write( const std::string groupName, const std::string variableName, const T* values )
 {
-    std::cout << "Just testing the Write function\n";
+    m_Groups.at( groupName ).Write( variableName, values );
 }
 
 
-void ADIOS::MonitorGroups( )
+void ADIOS::MonitorGroups( std::ostream& logStream ) const
 {
     for( auto& groupPair : m_Groups )
     {
-        std::cout << "Group:..." << groupPair.first << "\n";
-        groupPair.second.MonitorGroup();
+        logStream << "Group:..." << groupPair.first << "\n";
+        groupPair.second.Monitor( logStream );
     }
 }
 
+void ADIOS::CheckGroup( const std::string groupName )
+{
+    auto it = m_Groups.find( groupName );
+    if( it == m_Groups.end() ) throw std::invalid_argument( "ERROR: group " + groupName + " not found\n" );
+}
+
 
 
 } //end namespace
diff --git a/src/ADIOSFunctions.cpp b/src/ADIOSFunctions.cpp
index 73ca9ff20..e83428196 100644
--- a/src/ADIOSFunctions.cpp
+++ b/src/ADIOSFunctions.cpp
@@ -136,13 +136,14 @@ void SetMembers( const std::string& fileContent, std::string& hostLanguage, std:
         startComment = currentContent.find( "<!--" );
     }
 
+    std::string tag; //use for < > tags
+    std::vector< std::pair<const std::string, const std::string> > pairs; // pairs in tag
+
     //Tag <adios-config
-    std::string configTag;
     currentPosition = 0;
-    GetSubString( "<", ">", currentContent, configTag, currentPosition );
-    configTag = configTag.substr( 1, configTag.size() - 2 ); //eliminate < >
-    std::vector< std::pair<const std::string, const std::string> > pairs;
-    GetPairsFromTag( currentContent, configTag, pairs );
+    GetSubString( "<", ">", currentContent, tag, currentPosition );
+    tag = tag.substr( 1, tag.size() - 2 ); //eliminate < >
+    GetPairsFromTag( currentContent, tag, pairs );
 
     for( auto& pair : pairs )
     {
@@ -150,7 +151,7 @@ void SetMembers( const std::string& fileContent, std::string& hostLanguage, std:
     }
 
     //adios-group
-    std::string xmlGroup( "Used for groups" );
+    std::string xmlGroup;
     while( currentPosition != std::string::npos )
     {
         GetSubString("<adios-group ", "</adios-group>", currentContent, xmlGroup, currentPosition );
@@ -159,43 +160,147 @@ void SetMembers( const std::string& fileContent, std::string& hostLanguage, std:
         std::string groupName;
         CGroup group( xmlGroup, groupName );
         groups[ groupName ] = group; //copy as it's a small object
-    }
 
+        currentContent.erase( currentContent.find( xmlGroup ), xmlGroup.size() );
+        currentPosition = 0;
+    }
 
+    //transport
+    currentPosition = 0;
+    while( currentPosition != std::string::npos )
+    {
+        GetSubString( "<transport ", ">", currentContent, tag, currentPosition );
+        if( tag.empty() ) break;
+        tag = tag.substr( 1, tag.size() - 2 ); //eliminate < >
+        pairs.clear();
+        GetPairsFromTag( currentContent, tag, pairs );
+
+        std::string groupName, method, priorityStr, iterationStr;
+        for( auto& pair : pairs )
+        {
+            if( pair.first == "group" )  groupName = pair.second;
+            else if( pair.first == "method" ) method = pair.second;
+            else if( pair.first == "priority" ) priorityStr = pair.second;
+            else if( pair.first == "iteration" ) iterationStr = pair.second;
+        }
 
+        auto itGroup = groups.find( groupName );
+        if( itGroup == groups.end() ) //not found
+        {
+            continue;
+        }
 
-    //transports tag
-//    std::map< std::string, std::map<std::string,std::string> > groupsTransport;
-//    std::string::size_type startTransport = currentContent.find("<transport ");
-//
-//    while( startTransport != currentContent.npos )
-//    {
-//        std::string::size_type endTransport( currentContent.find( "</transport>") );
-//        std::string::size_type endTag( currentContent.find('>', startTransport ) );
-//
-//        const std::string transportTag( currentContent.substr( startTransport+1, endTag-startTransport-1 ) );
-//        std::vector< std::pair<const std::string, const std::string> > transportPairs;
-//        std::cout << "Transport tag..." << transportTag << "...\n";
-//        GetPairsFromTag( currentContent, transportTag, transportPairs );
-//
-//        for( auto& pair : pairs )
-//        {
-//            if( pair.first == "group" )
-//            {
-//
-//            }
-//        }
-//        const std::string transportContents( currentContent.substr( startTransport, endTransport-startTransport)  );
-//        std::cout << "Transport contents..." << transportContents << "...\n";
-//
-//        currentContent.erase( startTransport, endTransport-startComment + 12 );
-//        std::cout << "Current content..." << currentContent << "...\n";
-//
-//        startTransport = currentContent.find( "<transport " );
-//    }
+        //lambda function to check priority and iteration
+        auto lf_UIntCheck = []( const std::string method, const std::string fieldStr, const std::string fieldName, int& field )
+        {
+            field = 0;
+            if( fieldStr.empty() == false )
+            {
+                field = std::stoi( fieldStr ); //throws invalid_argument
+                if( field < 0 ) throw std::invalid_argument("ERROR: " + fieldName + " in transport " + method + " can't be negative\n" );
+            }
+        };
+
+        int priority, iteration;
+        lf_UIntCheck( method, priorityStr, "priority", priority );
+        lf_UIntCheck( method, iterationStr, "iteration", iteration );
+
+        itGroup->second.SetTransport( method, (unsigned int)priority, (unsigned int)iteration );
+    }
 }
 
+#ifdef HAVE_MPI
+void SetMembers( const std::string& fileContent, std::string& hostLanguage, std::map< std::string, CGroup >& groups,
+                 const MPI_Comm mpiComm )
+{
+    //adios-config
+    std::string currentContent;
+    std::string::size_type currentPosition( 0 );
+    GetSubString( "<adios-config ", "</adios-config>", fileContent, currentContent, currentPosition );
+
+    //remove comment sections
+    std::string::size_type startComment ( currentContent.find( "<!--" ) );
+
+    while( startComment != currentContent.npos )
+    {
+        std::string::size_type endComment( currentContent.find( "-->") );
+        currentContent.erase( startComment, endComment-startComment+3 );
+        startComment = currentContent.find( "<!--" );
+    }
+
+    std::string tag; //use for < > tags
+    std::vector< std::pair<const std::string, const std::string> > pairs; // pairs in tag
+
+    //Tag <adios-config
+    currentPosition = 0;
+    GetSubString( "<", ">", currentContent, tag, currentPosition );
+    tag = tag.substr( 1, tag.size() - 2 ); //eliminate < >
+    GetPairsFromTag( currentContent, tag, pairs );
+
+    for( auto& pair : pairs )
+    {
+        if( pair.first == "host-language" ) hostLanguage = pair.second;
+    }
+
+    //adios-group
+    std::string xmlGroup;
+    while( currentPosition != std::string::npos )
+    {
+        GetSubString("<adios-group ", "</adios-group>", currentContent, xmlGroup, currentPosition );
+        if( xmlGroup.empty() ) break;
+
+        std::string groupName;
+        CGroup group( xmlGroup, groupName );
+        groups[ groupName ] = group; //copy as it's a small object
+
+        currentContent.erase( currentContent.find( xmlGroup ), xmlGroup.size() );
+        currentPosition = 0;
+    }
 
+    //transport
+    currentPosition = 0;
+    while( currentPosition != std::string::npos )
+    {
+        GetSubString( "<transport ", ">", currentContent, tag, currentPosition );
+        if( tag.empty() ) break;
+        tag = tag.substr( 1, tag.size() - 2 ); //eliminate < >
+        pairs.clear();
+        GetPairsFromTag( currentContent, tag, pairs );
+
+        std::string groupName, method, priorityStr, iterationStr;
+        for( auto& pair : pairs )
+        {
+            if( pair.first == "group" )  groupName = pair.second;
+            else if( pair.first == "method" ) method = pair.second;
+            else if( pair.first == "priority" ) priorityStr = pair.second;
+            else if( pair.first == "iteration" ) iterationStr = pair.second;
+        }
+
+        auto itGroup = groups.find( groupName );
+        if( itGroup == groups.end() ) //not found
+        {
+            continue;
+        }
+
+        //lambda function to check priority and iteration
+        auto lf_UIntCheck = []( const std::string method, const std::string fieldStr, const std::string fieldName, int& field )
+        {
+            field = 0;
+            if( fieldStr.empty() == false )
+            {
+                field = std::stoi( fieldStr ); //throws invalid_argument
+                if( field < 0 ) throw std::invalid_argument("ERROR: " + fieldName + " in transport " + method + " can't be negative\n" );
+            }
+        };
+
+        int priority, iteration;
+        lf_UIntCheck( method, priorityStr, "priority", priority );
+        lf_UIntCheck( method, iterationStr, "iteration", iteration );
+
+        itGroup->second.SetTransport( method, (unsigned int)priority, (unsigned int)iteration, mpiComm );
+    }
+}
+#endif
 
 
 
diff --git a/src/CGroup.cpp b/src/CGroup.cpp
index 31c5871f2..dcb47db68 100644
--- a/src/CGroup.cpp
+++ b/src/CGroup.cpp
@@ -9,6 +9,14 @@
 
 #include "CGroup.h"
 #include "ADIOSFunctions.h"
+#include "SSupport.h"
+
+//MPI transport methods
+#ifdef HAVE_MPI
+#include "mpi/transport/CPOSIXMPI.h"
+#endif
+
+#include "nompi/transport/CPOSIXNoMPI.h"
 
 
 namespace adios
@@ -25,6 +33,12 @@ CGroup::CGroup( const std::string& xmlGroup, std::string& groupName )
 CGroup::~CGroup( )
 { }
 
+void CGroup::Open( const std::string fileName, const std::string accessMode )
+{
+    m_IsOpen = true;
+    m_Transport->Open( fileName, accessMode );
+}
+
 
 void CGroup::SetVariable( const std::string name, const bool isGlobal, const std::string type, const std::string dimensionsCSV,
                           const std::string transform )
@@ -73,17 +87,36 @@ void CGroup::SetGlobalBounds( const std::string dimensionsCSV, const std::string
     }
 }
 
-void CGroup::MonitorGroup( )
+void CGroup::SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration )
+{
+    CheckTransport( method );
+    if( m_ActiveTransport == "POSIX" ) m_Transport = std::make_shared<CPOSIXNoMPI>( method, priority, iteration );
+}
+
+#ifdef HAVE_MPI
+void CGroup::SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration,
+                           const MPI_Comm mpiComm )
+{
+    CheckTransport( method );
+    if( m_ActiveTransport == "POSIX" ) m_Transport = std::make_shared<CPOSIXMPI>( method, priority, iteration, mpiComm );
+}
+#endif
+
+
+//PRIVATE FUNCTIONS BELOW
+
+void CGroup::Monitor( std::ostream& logStream ) const
 {
     for( auto& variablePair : m_Variables )
     {
-        std::cout << "VarName:..." << variablePair.first << "  Type:..." << variablePair.second->m_Type << "\n";
+        logStream << "VarName:..." << variablePair.first << "  Type:..." << variablePair.second->m_Type << "\n";
     }
 
-    std::cout << "Transport Method Unique?: " << m_TransportMethod.unique() << "\n";
-
+    logStream << "Transport Method " << m_ActiveTransport << "\n";
+    logStream << std::ostream::boolalpha << "Transport Method Unique?: " << m_Transport.unique() << "\n";
 }
 
+
 void CGroup::ParseXMLGroup( const std::string& xmlGroup, std::string& groupName )
 {
     //get name
@@ -153,6 +186,16 @@ void CGroup::ParseXMLGroup( const std::string& xmlGroup, std::string& groupName
 }
 
 
+void CGroup::CheckTransport( const std::string method )
+{
+    if( c_Transports.count( method ) == 0 )
+        throw std::invalid_argument( "ERROR: transport method " + method + " not supported. Check spelling or case sensitivity.\n" );
+
+    if( m_ActiveTransport.empty() == false ) //there is an existing transport method
+        m_Transport.reset();
+
+    m_ActiveTransport = method;
+}
 
 
 } //end namespace
diff --git a/src/mpi/transport/CPOSIXMPI.cpp b/src/mpi/transport/CPOSIXMPI.cpp
index 1d697f694..3670c4620 100644
--- a/src/mpi/transport/CPOSIXMPI.cpp
+++ b/src/mpi/transport/CPOSIXMPI.cpp
@@ -25,7 +25,7 @@ CPOSIXMPI::~CPOSIXMPI( )
 { }
 
 
-void CPOSIXMPI::Write( CVariable& variable )
+void CPOSIXMPI::Write( const CVariable& variable )
 {
     int rank;
     MPI_Comm_rank( m_MPIComm, &rank );
diff --git a/src/nompi/transport/CPOSIXNoMPI.cpp b/src/nompi/transport/CPOSIXNoMPI.cpp
index 3bc5ed640..623e7d836 100644
--- a/src/nompi/transport/CPOSIXNoMPI.cpp
+++ b/src/nompi/transport/CPOSIXNoMPI.cpp
@@ -24,7 +24,7 @@ CPOSIXNoMPI::~CPOSIXNoMPI( )
 { }
 
 
-void Write( CVariable& variable )
+void CPOSIXNoMPI::Write( const CVariable& variable )
 {
     std::cout << "Just saying Hello from CPOSIXNoMPI Write\n";
 }
-- 
GitLab