diff --git a/examples/hello/writer/helloWriter_OOP.cpp b/examples/hello/writer/helloWriter_OOP.cpp
index 3996dca86a0aa99da7d693209656cf2d6aa1a9ea..ab19925677f177e4f22e7f8167aafd87902b644a 100644
--- a/examples/hello/writer/helloWriter_OOP.cpp
+++ b/examples/hello/writer/helloWriter_OOP.cpp
@@ -39,8 +39,10 @@ int main( int argc, char* argv [] )
         //Define group and variables with transforms, variables don't have functions, only group can access variables
         adios::Group& ioGroup = adios.DeclareGroup( "ioGroup" );
         adios::Var ioNx = ioGroup.DefineVariable<unsigned int>( "Nx" );
-        adios::Var ioMyDoubles = ioGroup.DefineVariable<double>( "myDoubles", "Nx" );
-        adios::Var ioMyFloats = ioGroup.DefineVariable<float>( "myFloats", "Nx" );
+
+        adios::Dims dimNx = ioGroup.SetDimensions( {ioNx} );
+        adios::Var ioMyDoubles = ioGroup.DefineVariable<double>( "myDoubles", dimNx );
+        adios::Var ioMyFloats = ioGroup.DefineVariable<float>( "myFloats", dimNx );
 
         //add transform to variable in group...not executed (just testing API)
         adios::Transform bzip2 = adios::transform::BZIP2( );
diff --git a/include/capsule/Heap.h b/include/capsule/Heap.h
index d6d95fc5a336320588fffd938b5bb80cc118e6f1..9138e4c7d3fbfd16f206b8ad74068a020380f92e 100644
--- a/include/capsule/Heap.h
+++ b/include/capsule/Heap.h
@@ -23,6 +23,9 @@ class Heap : public Capsule
 
 public:
 
+    std::vector<char> m_Data; ///< data buffer allocated using the STL in heap memory, default size = 16 Mb
+    std::vector<char> m_Metadata; ///< metadata buffer allocated using the STL in heap memory, default size = 100 Kb
+
     /**
      * Unique constructor
      * @param accessMode read, write or append
@@ -44,12 +47,6 @@ public:
     void ResizeData( const std::size_t size );
     void ResizeMetadata( const std::size_t size );
 
-
-private:
-
-    std::vector<char> m_Data; ///< data buffer allocated using the STL in heap memory, default size = 16 Mb
-    std::vector<char> m_Metadata; ///< metadata buffer allocated using the STL in heap memory, default size = 100 Kb
-
 };
 
 
diff --git a/include/core/Capsule.h b/include/core/Capsule.h
index ebc36d30e9ffb2515ca825de74de74303d3090f7..372ffdfaffdff6169b428b9687235606586c18ab 100644
--- a/include/core/Capsule.h
+++ b/include/core/Capsule.h
@@ -27,6 +27,9 @@ public:
     const std::string m_Type; ///< buffer type
     const std::string m_AccessMode; ///< 'w': write, 'r': read, 'a': append
 
+    std::size_t m_AbsoluteDataPosition; ///< includes the data flushed to transports
+    std::size_t m_AbsoluteMetadataPosition; ///< includes the metadata flushed to transports
+
     /**
      * Base class constructor providing type from derived class and accessMode
      * @param type derived class type
diff --git a/include/core/Group.h b/include/core/Group.h
index 60b983064796a4b63086b00cd6174fc8ff052c20..879d859035ac510201d93fbef9819f48e8aed1a4 100644
--- a/include/core/Group.h
+++ b/include/core/Group.h
@@ -15,6 +15,7 @@
 #include <vector>
 #include <ostream>
 #include <set>
+#include <initializer_list> //SetDimensions
 /// \endcond
 
 #ifdef HAVE_MPI
@@ -35,6 +36,8 @@ namespace adios
 {
 
 using Var = std::string; ///< used for returning variables from DefineVariable
+using Dims = std::string;
+
 /**
  * Class that defines each ADIOS Group composed of Variables, Attributes and GlobalBounds (if global variables exist)
  */
@@ -84,6 +87,9 @@ public:
 
     ~Group( ); ///< Using STL containers, no deallocation
 
+
+    Dims SetDimensions( std::initializer_list<Var> variables ); ///< returns adios::Dims object from a list of existing adios::Var objects
+
     /**
      * Define a new variable in the group object
      * @param name variable name, must be unique in the group. If name exists it removes the current variable. In debug mode program will exit.
@@ -95,16 +101,16 @@ public:
      * @param parameters corresponding parameter used by a Transform object in transforms (index should match), default is empty
      */
     Var DefineVariable( const std::string variableName, const std::string type,
-                        const std::string dimensionsCSV = "",
-                        const std::string globalDimensionsCSV = "", const std::string globalOffsetsCSV = "",
+                        const Dims dimensionsCSV = "1",
+                        const Dims globalDimensionsCSV = "", const Dims globalOffsetsCSV = "",
                         const std::vector<Transform*> transforms = std::vector<Transform*>(),
                         const std::vector<int> parameters = std::vector<int>() );
 
 
     template< class T >
     Var DefineVariable( const std::string variableName,
-                        const std::string dimensionsCSV = "",
-                        const std::string globalDimensionsCSV = "", const std::string globalOffsetsCSV = "",
+                        const Dims dimensionsCSV = "",
+                        const Dims globalDimensionsCSV = "", const Dims globalOffsetsCSV = "",
                         const std::vector<Transform*> transforms = std::vector<Transform*>(),
                         const std::vector<int> parameters = std::vector<int>() )
     {
@@ -117,7 +123,7 @@ public:
      * @param transform corresponding transform object, non-const as a pointer is created and pushed to a vector
      * @param parameter optional parameter interpreted by the corresponding Transform, default = -1
      */
-    void AddTransform( const std::string variableName, Transform& transform, const int parameter = -1 );
+    void AddTransform( const Var variableName, Transform& transform, const int parameter = -1 );
 
     /**
      * Define a new attribute
@@ -139,7 +145,7 @@ public:
      * @param dimensionsCSV comma separated dimensions "Nx,Ny,Nz"
      * @return actual vector values = { Nx, Ny, Nz }
      */
-    std::vector<unsigned long long int> GetDimensions( const std::string dimensionsCSV ) const;
+    std::vector<unsigned long long int> GetDimensions( const Dims dimensionsCSV ) const;
 
 private:
 
diff --git a/include/format/BP1Writer.h b/include/format/BP1Writer.h
index 3ec8674d39fade92cdc4ce212b78a0236d0a8ccf..0aef1cf1b8b6f78a40c92cd836a1829face11702 100644
--- a/include/format/BP1Writer.h
+++ b/include/format/BP1Writer.h
@@ -11,7 +11,7 @@
 
 #include <vector>
 #include <cstdint>
-#include <algorithm> //std::count
+#include <algorithm> //std::count, std::copy
 #include <cstring> //std::memcpy
 
 #include "core/Variable.h"
@@ -30,11 +30,20 @@ class BP1Writer
 
 public:
 
-    std::vector<char> m_PGIndex; ///< process group index
+    std::uint64_t m_ProcessGroupsCount = 0; ///< number of process groups
+    std::uint64_t m_ProcessGroupsLength = 0; ///< length in bytes of process groups
+    std::vector<char> m_ProcessGroupIndex; ///< process group index metadata
+
+    std::uint32_t m_VariablesCount = 0; ///< number of written Variables
+    std::uint64_t m_VariablesLength = 0; ///< length in bytes of written Variables
     std::vector<char> m_VariableIndex; ///< metadata variable index
+
+    std::uint32_t m_AttributesCount = 0; ///< number of Attributes
+    std::uint64_t m_AttributesLength = 0; ///< length in bytes of Attributes
     std::vector<char> m_AttributeIndex; ///< metadata attribute index
 
     const unsigned int m_Cores = 1;
+    const unsigned int m_Verbosity = 0;
 
     /**
      * DataTypes mapping in BP Format
@@ -151,7 +160,7 @@ public:
      */
     template< class T >
     size_t GetVariableIndexSize( const Group& group, const std::string variableName,
-                                 const Variable<T> variable, const unsigned int verbosity ) noexcept
+                                 const Variable<T> variable ) noexcept
     {
         //size_t indexSize = varEntryLength + memberID + lengthGroupName + groupName + lengthVariableName + lengthOfPath + path + datatype
         size_t indexSize = 23; //without characteristics
@@ -181,7 +190,7 @@ public:
         }
 
         //characteristic statistics
-        if( verbosity == 0 ) //default, only min and max
+        if( m_Verbosity == 0 ) //default, only min and max
         {
             indexSize += 2 * ( sizeof(T) + 1 );
             indexSize += 1 + 1; //id
@@ -208,218 +217,244 @@ public:
         offset += size;
     }
 
-    template< class T >
-    void CopyToBuffers( std::vector<char*>& buffers, const T* source, std::size_t size, std::size_t& offset ) noexcept
+    template< class T, class U >
+    void CopyToBuffers( std::vector<char*>& buffers, const T* source, U size, std::size_t& offset ) noexcept
     {
         for( auto& buffer : buffers )
         {
             std::copy( source, source+size, &buffer[offset] );
-            //std::memcpy( &buffer[offset], source, size );
         }
         offset += size;
     }
 
-
-
     /**
-     *
+     * Writes a variable to BP format in data and metadata (index) buffers
      * @param group variable owner
      * @param variableName name of variable to be written
      * @param variable object carrying variable information
      * @param dataBuffers buffers to which variable metadata and payload (values) will be written. Metadata is added in case of system corruption to allow regeneration.
+     * @param dataPosition initial data position
      * @param metadataBuffers buffers to which only variable metadata will be written
-     * @param characteristicsVerbosity default = 0 min and max only,
+     * @param metadataPosition
+     * @param memberID
+     * @return number of bytes written, needed for variable entry length
      */
     template< class T >
-    void WriteVariable( const Group& group, const std::string variableName,
+    void WriteVariable( const Group& group, const Var variableName,
                         const Variable<T>& variable,
                         std::vector<char*>& dataBuffers, const std::size_t dataPosition,
-                        std::vector<char*>& metadataBuffers, const std::size_t metadataPosition,
-                        const unsigned int memberID, const bool writeDimensionsInData,
-                        const unsigned int verbose ) noexcept
+                        std::vector<char*>& metadataBuffers, const std::size_t metadataPosition ) noexcept
     {
-       std::size_t metadataOffset = metadataPosition + 8; //length of var, will come at the end from this offset
-       std::size_t dataOffset = dataPosition + 8; //length of var, will come at the end from this offset
-
-       //memberID
-       WriteToBuffers( metadataBuffers, &memberID, 4, metadataOffset );
-       //group
-       const std::uint16_t lengthGroupName = group.m_Name.length();
-       WriteToBuffers( metadataBuffers, &lengthGroupName, 2, metadataOffset ); //2 bytes
-       //const char* groupName = ;
-       WriteToBuffers( metadataBuffers, group.m_Name.c_str(), lengthGroupName, metadataOffset );
-       //variable name to metadata and data
-       const std::uint16_t lengthVariableName = variableName.length();
-       WriteToBuffers( metadataBuffers, &lengthVariableName, 2, metadataOffset );
-       WriteToBuffers( metadataBuffers, variableName.c_str(), lengthVariableName, metadataOffset );
-       WriteToBuffers( dataBuffers, &lengthVariableName, 2, dataOffset );
-       WriteToBuffers( dataBuffers, variableName.c_str(), lengthVariableName, dataOffset );
-       //skip path (jump 2 bytes)
-       metadataOffset += 2;
-       dataOffset += 2;
-       //dataType
-       const std::uint8_t dataType = GetBPDataType( variable );
-       WriteToBuffers( metadataBuffers, &dataType, 1, metadataOffset );
-       WriteToBuffers( dataBuffers, &dataType, 1, dataOffset );
-
-       //Characteristics Sets in Metadata and Data
-       const std::size_t metadataCharacteristicsSetsCountPosition = metadataOffset; //very important piece
-       std::size_t dataCharacteristicsCountPosition = dataOffset;
-       const std::uint64_t sets = 1; //write one for now
-       WriteToBuffers( metadataBuffers, &sets, 8, metadataOffset );
-
-       unsigned int characteristicsCounter = 0; //used for characteristics count, characteristics length will be calculated at the end
-
-       //DIMENSIONS CHARACTERISTIC
-       const std::vector<unsigned long long int> localDimensions = group.GetDimensions( variable.DimensionsCSV );
-
-       //write to metadata characteristic
-       //characteristic: dimension
-       std::uint8_t characteristicID = characteristic_dimensions;
-       WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset );
-       const std::uint8_t dimensions = localDimensions.size();
-       WriteToBuffers( metadataBuffers, &dimensions, 1, metadataOffset );
-       const std::uint16_t dimensionsLength = dimensions * 24; //24 is from 8 bytes for each: local dimension, global dimension, global offset
-       WriteToBuffers( metadataBuffers, &dimensionsLength, 2, metadataOffset );
-
-       //dimensions in data buffer, header
-       if( writeDimensionsInData == true )
-       {
-           const char yes = 'y'; // dimension y or n
-           WriteToBuffers( dataBuffers, &yes, 1, dataOffset );
-           //for now only support unsigned long integer value (8 bytes), as in metadata
-           WriteToBuffers( dataBuffers, &dimensions, 1, dataOffset );
-           const std::uint16_t dimensionsLengthInData = dimensions * 27; //27 is from 9 bytes for each: var y/n + local, var y/n + global dimension, var y/n + global offset
-           WriteToBuffers( dataBuffers, &dimensionsLengthInData, 2, dataOffset );
-       }
-       else
-       {
-           const char no = 'n'; // dimension y or n
-           WriteToBuffers( dataBuffers, &no, 1, dataOffset );
-           dataCharacteristicsCountPosition += 1;
-       }
-
-       if( variable.GlobalBoundsIndex == -1 ) //local variable
-       {
-           for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
-           {
-               //metadata characteristics
-               WriteToBuffers( metadataBuffers, &localDimensions[d], 8, metadataOffset );
-               metadataOffset += 16; //skipping global dimension(8), global offset (8)
-           }
-
-           if( writeDimensionsInData == true )
-           {
-               for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
-               {
-                   const char no = 'n'; //dimension format unsigned int value
-                   WriteToBuffers( dataBuffers, &no, 1, dataOffset );
-                   WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
-                   dataOffset += 18; //skipping var no + global dimension(8), var no + global offset (8)
-               }
-           }
-           //dimensions in data characteristic entry (might not be required)
-           dataCharacteristicsCountPosition = dataOffset;
-           dataOffset += 5; //skip characteristics count(1) + length (4)
-           WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset );
-
-           std::int16_t lengthOfDimensionsCharacteristic = 3 + 24 * dimensions; // 3 = dimension(1) + length(2) ; 24 = 3 local, global, global offset x 8 bytes/each
-           WriteToBuffers( dataBuffers, &lengthOfDimensionsCharacteristic, 2, dataOffset );
-
-           WriteToBuffers( dataBuffers, &dimensions, 1, dataOffset );
-           WriteToBuffers( dataBuffers, &dimensionsLength, 2, dataOffset );
-
-           for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
-           {
-               //metadata characteristics
-               WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
-               metadataOffset += 16; //skipping global dimension(8), global offset (8)
-           }
-       }
-       else //global variable
-       {
-           std::vector<unsigned long long int> globalDimensions = group.GetDimensions( group.m_GlobalBounds[variable.GlobalBoundsIndex].first );
-           std::vector<unsigned long long int> globalOffsets = group.GetDimensions( group.m_GlobalBounds[variable.GlobalBoundsIndex].second );
-
-           //metadata, writing in characteristics
-           for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
-           {
-               WriteToBuffers( metadataBuffers, &localDimensions[d], 8, metadataOffset );
-               WriteToBuffers( metadataBuffers, &globalDimensions[d], 8, metadataOffset );
-               WriteToBuffers( metadataBuffers, &globalOffsets[d], 8, metadataOffset );
-           }
-
-           //data dimensions entry
-           if( writeDimensionsInData == true )
-           {
-               for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
-               {
-                   const char no = 'n'; //dimension format unsigned int value
-                   WriteToBuffers( dataBuffers, &no, 1, dataOffset );
-                   WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
-                   WriteToBuffers( dataBuffers, &no, 1, dataOffset );
-                   WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
-               }
-           }
-           //dimensions in data characteristic entry (might not be required)
-           dataCharacteristicsCountPosition = dataOffset;
-           dataOffset += 5; //skip characteristics count(1) + length (4)
-           WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset ); //id
-
-           std::int16_t lengthOfDimensionsCharacteristic = 3 + 24 * dimensions; // 3 = dimension(1) + length(2) ; 24 = 3 local, global, global offset x 8 bytes/each
-           WriteToBuffers( dataBuffers, &lengthOfDimensionsCharacteristic, 2, dataOffset );
-
-           WriteToBuffers( dataBuffers, &dimensions, 1, dataOffset );
-           WriteToBuffers( dataBuffers, &dimensionsLength, 2, dataOffset );
-
-           for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
-           {
-               WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
-               WriteToBuffers( dataBuffers, &globalDimensions[d], 8, dataOffset );
-               WriteToBuffers( dataBuffers, &globalOffsets[d], 8, dataOffset );
-           }
-       }
-
-       ++characteristicsCounter;
-       //Stat -> Min, Max
-       characteristicID = characteristic_stat;
-       if( verbose == 0 ) //default verbose
-       {
-           const std::size_t valuesSize = GetTotalSize( localDimensions );
-           //here we can make decisions for threads based on valuesSize
-           T min, max;
-
-           if( valuesSize >= 10000000 ) //ten million? this needs actual results
-               GetMinMax( variable.Values, valuesSize, min, max, m_Cores ); //here we can add cores from constructor
-           else
-               GetMinMax( variable.Values, valuesSize, min, max );
-
-           const std::int8_t statisticMinID = statistic_min;
-           const std::int8_t statisticMaxID = statistic_max;
-
-           //write min and max to metadata
-           WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset  ); //min
-           WriteToBuffers( metadataBuffers, &statisticMinID, 1, metadataOffset  );
-           WriteToBuffers( metadataBuffers, &min, sizeof(T), metadataOffset );
-
-           WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset  ); //max
-           WriteToBuffers( metadataBuffers, &statisticMaxID, 1, metadataOffset  );
-           WriteToBuffers( metadataBuffers, &max, sizeof(T), metadataOffset );
-
-           //write min and max to data
-           WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset  ); //min
-           const std::int16_t lengthCharacteristic = 1 + sizeof( T );
-           WriteToBuffers( dataBuffers, &lengthCharacteristic, 2, dataOffset  );
-           WriteToBuffers( dataBuffers, &statisticMinID, 1, dataOffset  );
-           WriteToBuffers( dataBuffers, &min, sizeof(T), dataOffset );
-
-           WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset  ); //max
-           WriteToBuffers( dataBuffers, &lengthCharacteristic, 2, dataOffset  );
-           WriteToBuffers( dataBuffers, &statisticMaxID, 1, dataOffset  );
-           WriteToBuffers( dataBuffers, &max, sizeof(T), dataOffset );
-       }
-       //Offsets should be last and only written to metadata
+        std::size_t metadataOffset = metadataPosition + 4; //length of var, will come at the end from this offset
+        std::size_t dataOffset = dataPosition + 8; //length of var, will come at the end from this offset
+
+        //memberID
+        WriteToBuffers( metadataBuffers, &m_VariablesCount, 4, metadataOffset );
+        //group, only in metadata
+        const std::uint16_t lengthGroupName = group.m_Name.length();
+        WriteToBuffers( metadataBuffers, &lengthGroupName, 2, metadataOffset ); //2 bytes
+        WriteToBuffers( metadataBuffers, group.m_Name.c_str(), lengthGroupName, metadataOffset );
+        //variable name to metadata and data
+        const std::uint16_t lengthVariableName = variableName.length();
+        WriteToBuffers( metadataBuffers, &lengthVariableName, 2, metadataOffset );
+        WriteToBuffers( metadataBuffers, variableName.c_str(), lengthVariableName, metadataOffset );
+        WriteToBuffers( dataBuffers, &lengthVariableName, 2, dataOffset );
+        WriteToBuffers( dataBuffers, variableName.c_str(), lengthVariableName, dataOffset );
+        //skip path (jump 2 bytes, already set to zero)
+        metadataOffset += 2;
+        dataOffset += 2;
+        //dataType
+        const std::uint8_t dataType = GetDataType( variable );
+        WriteToBuffers( metadataBuffers, &dataType, 1, metadataOffset );
+        WriteToBuffers( dataBuffers, &dataType, 1, dataOffset );
+
+        //Characteristics Sets in Metadata and Data
+        const std::size_t metadataCharacteristicsSetsCountPosition = metadataOffset; //very important piece
+        std::size_t dataCharacteristicsCountPosition = dataOffset;
+        const std::uint64_t sets = 1; //write one for now
+        WriteToBuffers( metadataBuffers, &sets, 8, metadataOffset );
+
+        std::uint8_t characteristicsCounter = 0; //used for characteristics count, characteristics length will be calculated at the end
+
+        //DIMENSIONS CHARACTERISTIC
+        const std::vector<unsigned long long int> localDimensions = group.GetDimensions( variable.DimensionsCSV );
+
+        //write to metadata characteristic
+        //characteristic: dimension
+        std::uint8_t characteristicID = characteristic_dimensions;
+        WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset );
+        const std::uint8_t dimensions = localDimensions.size();
+        WriteToBuffers( metadataBuffers, &dimensions, 1, metadataOffset );
+        const std::uint16_t dimensionsLength = dimensions * 24; //24 is from 8 bytes for each: local dimension, global dimension, global offset
+        WriteToBuffers( metadataBuffers, &dimensionsLength, 2, metadataOffset );
+
+        //write in data if it's a dimension variable (scalar) y or n
+        const char dimensionYorN = ( variable.IsDimension ) ? 'y' : 'n';
+        WriteToBuffers( dataBuffers, &dimensionYorN, 1, dataOffset );
+        WriteToBuffers( dataBuffers, &dimensions, 1, dataOffset );
+        const std::uint16_t dimensionsLengthInData = dimensions * 27; //27 is from 9 bytes for each: var y/n + local, var y/n + global dimension, var y/n + global offset
+        WriteToBuffers( dataBuffers, &dimensionsLengthInData, 2, dataOffset );
+
+        if( variable.GlobalBoundsIndex == -1 ) //local variable
+        {
+            for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
+            {
+                //metadata characteristics
+                WriteToBuffers( metadataBuffers, &localDimensions[d], 8, metadataOffset );
+                metadataOffset += 16; //skipping global dimension(8), global offset (8)
+            }
+
+            const char no = 'n'; //dimension format unsigned int value (not using memberID for now)
+            for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
+            {
+                //data dimensions
+                WriteToBuffers( dataBuffers, &no, 1, dataOffset );
+                WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
+                dataOffset += 18; //skipping var no + global dimension(8), var no + global offset (8)
+            }
+
+            //dimensions in data characteristic entry
+            dataCharacteristicsCountPosition = dataOffset;
+            dataOffset += 5; //skip characteristics count(1) + length (4)
+            WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset );
+
+            std::int16_t lengthOfDimensionsCharacteristic = 3 + 24 * dimensions; // 3 = dimension(1) + length(2) ; 24 = 3 local, global, global offset x 8 bytes/each
+            WriteToBuffers( dataBuffers, &lengthOfDimensionsCharacteristic, 2, dataOffset );
+
+            WriteToBuffers( dataBuffers, &dimensions, 1, dataOffset );
+            WriteToBuffers( dataBuffers, &dimensionsLength, 2, dataOffset );
+
+            for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
+            {
+                //data characteristics
+                WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
+                metadataOffset += 16; //skipping global dimension(8), global offset (8)
+            }
+        }
+        else //global variable
+        {
+            std::vector<unsigned long long int> globalDimensions = group.GetDimensions( group.m_GlobalBounds[variable.GlobalBoundsIndex].first );
+            std::vector<unsigned long long int> globalOffsets = group.GetDimensions( group.m_GlobalBounds[variable.GlobalBoundsIndex].second );
+
+            //metadata, writing in characteristics
+            for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
+            {
+                WriteToBuffers( metadataBuffers, &localDimensions[d], 8, metadataOffset );
+                WriteToBuffers( metadataBuffers, &globalDimensions[d], 8, metadataOffset );
+                WriteToBuffers( metadataBuffers, &globalOffsets[d], 8, metadataOffset );
+            }
+
+            //data dimensions entry
+            for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
+            {
+                const char no = 'n'; //dimension format unsigned int value
+                WriteToBuffers( dataBuffers, &no, 1, dataOffset );
+                WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
+                WriteToBuffers( dataBuffers, &no, 1, dataOffset );
+                WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
+            }
+
+            //dimensions in data characteristic entry (might not be required)
+            dataCharacteristicsCountPosition = dataOffset;
+            dataOffset += 5; //skip characteristics count(1) + length (4)
+            WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset ); //id
+
+            std::int16_t lengthOfDimensionsCharacteristic = 3 + 24 * dimensions; // 3 = dimension(1) + length(2) ; 24 = 3 local, global, global offset x 8 bytes/each
+            WriteToBuffers( dataBuffers, &lengthOfDimensionsCharacteristic, 2, dataOffset );
+
+            WriteToBuffers( dataBuffers, &dimensions, 1, dataOffset );
+            WriteToBuffers( dataBuffers, &dimensionsLength, 2, dataOffset );
+
+            for( unsigned int d = 0; d < (unsigned int)localDimensions.size(); ++d )
+            {
+                WriteToBuffers( dataBuffers, &localDimensions[d], 8, dataOffset );
+                WriteToBuffers( dataBuffers, &globalDimensions[d], 8, dataOffset );
+                WriteToBuffers( dataBuffers, &globalOffsets[d], 8, dataOffset );
+            }
+        }
+        ++characteristicsCounter;
+
+        //VALUE for SCALAR or STAT min, max for ARRAY
+        //Value for scalar
+        if( variable.DimensionsCSV == "1" ) //scalar //just doing string scalars for now (by name), needs to be modified when user passes value
+        {
+            characteristicID = characteristic_value;
+            std::int16_t lenghtOfName = variableName.length();
+            //metadata
+            WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset  );
+            WriteToBuffers( metadataBuffers, &lenghtOfName, 2, metadataOffset  );
+            WriteToBuffers( metadataBuffers, variableName.c_str(), lenghtOfName, metadataOffset  );
+
+            //data
+            WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset  );
+            std::int16_t lengthOfCharacteristic = 2 + lenghtOfName;
+            WriteToBuffers( dataBuffers, &lengthOfCharacteristic, 2, dataOffset );
+            WriteToBuffers( dataBuffers, &lenghtOfName, 2, dataOffset  );
+            WriteToBuffers( dataBuffers, variableName.c_str(), lenghtOfName, dataOffset  );
+        }
+        else // Stat -> Min, Max for arrays,
+        {
+            if( m_Verbosity == 0 ) //default verbose
+            {
+                //Get min and max
+                const std::size_t valuesSize = GetTotalSize( localDimensions );
+                //here we can make decisions for threads based on valuesSize
+                T min, max;
+
+                if( valuesSize >= 10000000 ) //ten million? this needs actual results
+                    GetMinMax( variable.Values, valuesSize, min, max, m_Cores ); //here we can add cores from constructor
+                else
+                    GetMinMax( variable.Values, valuesSize, min, max );
+
+                //set characteristic ids for min and max
+                characteristicID = characteristic_stat;
+                const std::int8_t statisticMinID = statistic_min;
+                const std::int8_t statisticMaxID = statistic_max;
+
+                //write min and max to metadata
+                WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset  ); //min
+                WriteToBuffers( metadataBuffers, &statisticMinID, 1, metadataOffset  );
+                WriteToBuffers( metadataBuffers, &min, sizeof(T), metadataOffset );
+
+                WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset  ); //max
+                WriteToBuffers( metadataBuffers, &statisticMaxID, 1, metadataOffset  );
+                WriteToBuffers( metadataBuffers, &max, sizeof(T), metadataOffset );
+
+                //write min and max to data
+                WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset  ); //min
+                const std::int16_t lengthCharacteristic = 1 + sizeof( T );
+                WriteToBuffers( dataBuffers, &lengthCharacteristic, 2, dataOffset  );
+                WriteToBuffers( dataBuffers, &statisticMinID, 1, dataOffset  );
+                WriteToBuffers( dataBuffers, &min, sizeof(T), dataOffset );
+
+                WriteToBuffers( dataBuffers, &characteristicID, 1, dataOffset  ); //max
+                WriteToBuffers( dataBuffers, &lengthCharacteristic, 2, dataOffset  );
+                WriteToBuffers( dataBuffers, &statisticMaxID, 1, dataOffset  );
+                WriteToBuffers( dataBuffers, &max, sizeof(T), dataOffset );
+            }
+        }
+        ++characteristicsCounter;
+        //here write characteristics count and length to data
+        std::uint32_t characteristicsLengthInData = dataOffset - dataCharacteristicsCountPosition;
+        WriteToBuffers( dataBuffers, &characteristicsCounter, 1, dataCharacteristicsCountPosition );
+        WriteToBuffers( dataBuffers, &characteristicsLengthInData, 4, dataCharacteristicsCountPosition );
+        dataCharacteristicsCountPosition -= 5;
+
+        //Offsets should be last and only written to metadata
+        characteristicID = characteristic_offset;
+        WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset  ); //variable offset id
+        WriteToBuffers( metadataBuffers, &dataPosition, 8, metadataOffset ); //variable offset
+        ++characteristicsCounter;
+
+        characteristicID = characteristic_payload_offset;
+        WriteToBuffers( metadataBuffers, &characteristicID, 1, metadataOffset  ); //variable payload offset id
+        WriteToBuffers( metadataBuffers, &dataOffset, 8, metadataOffset ); //variable offset
+        ++characteristicsCounter;
+
+        //here write var entry length in metadata
+
 
+        ++m_VariablesCount;
     } //end of function
 
 
diff --git a/src/core/Group.cpp b/src/core/Group.cpp
index c2013331c6cd4b23c88da248f14960eb6a4e6edf..a0679e813853ef05f8c47e39fd40cbdbfa498d03 100644
--- a/src/core/Group.cpp
+++ b/src/core/Group.cpp
@@ -29,7 +29,8 @@ Group::Group( const std::string name, const bool debugMode ):
 { }
 
 
-Group::Group( const std::string name, const std::string& xmlGroup, std::vector< std::shared_ptr<Transform> >& transforms, const bool debugMode ):
+Group::Group( const std::string name, const std::string& xmlGroup, std::vector< std::shared_ptr<Transform> >& transforms,
+              const bool debugMode ):
     m_Name{ name },
     m_DebugMode{ debugMode }
 {
@@ -41,9 +42,32 @@ Group::~Group( )
 { }
 
 
+Dims Group::SetDimensions( std::initializer_list<Var> variableList )
+{
+    if( m_DebugMode == true )
+    {
+        if( variableList.size() == 0 )
+            throw std::invalid_argument( "ERROR: variableList is empty, in call to SetDimensions\n" );
+    }
+
+    Dims dimensionsCSV;
+    for( const auto variable : variableList )
+    {
+        if( m_DebugMode == true )
+        {
+            if( variable.find(",") != variable.npos )
+                throw std::invalid_argument( "ERROR: variable can't contain a comma character, in call to SetDimensions\n" );
+        }
+        dimensionsCSV += variable + ",";
+    }
+    dimensionsCSV.pop_back();
+    return dimensionsCSV;
+}
+
+
 Var Group::DefineVariable( const std::string variableName, const std::string type,
-                           const std::string dimensionsCSV,
-                           const std::string globalDimensionsCSV, const std::string globalOffsetsCSV,
+                           const Dims dimensionsCSV,
+                           const Dims globalDimensionsCSV, const Dims globalOffsetsCSV,
                            std::vector<Transform*> transforms, std::vector<int> parameters )
 {
     auto lf_CheckDimensionVariables = [&]( const std::string csv, const std::string dimensionType, const std::string variableName )
@@ -305,6 +329,11 @@ unsigned long long int Group::GetIntVariableValue( const std::string variableNam
 
 std::vector<unsigned long long int> Group::GetDimensions( const std::string dimensionsCSV ) const
 {
+    if( dimensionsCSV == "1" ) //scalar
+    {
+        return std::vector<unsigned long long int>{ 1 };
+    }
+
     std::vector<unsigned long long int> dimensions;
 
     if( dimensionsCSV.find(',') == dimensionsCSV.npos ) //check if 1D