diff --git a/examples/heatTransfer/HeatTransfer.cpp b/examples/heatTransfer/HeatTransfer.cpp
index 970f7d2f10911c3fa4309a4eb9bb977f1f183fb9..fd6d84f6c0a4b77449f34587238a19859dd3d960 100644
--- a/examples/heatTransfer/HeatTransfer.cpp
+++ b/examples/heatTransfer/HeatTransfer.cpp
@@ -27,7 +27,7 @@ HeatTransfer::HeatTransfer( const Settings& settings )
     m_T1[0] = new double[ (m_s.ndx+2) * (m_s.ndy+2) ];
     m_T2 = new double*[ m_s.ndx+2 ];
     m_T2[0] = new double[ (m_s.ndx+2) * (m_s.ndy+2) ];
-    for (int i = 1; i < m_s.ndx+2; i++)
+    for (unsigned int i = 1; i < m_s.ndx+2; i++)
     {
         m_T1[i] = m_T1[i-1] + m_s.ndy+2;
         m_T2[i] = m_T2[i-1] + m_s.ndy+2;
@@ -49,8 +49,8 @@ void HeatTransfer::init(bool init_with_rank)
 {
     if (init_with_rank)
     {
-        for (int i = 0; i < m_s.ndx+2; i++)
-            for (int j = 0; j < m_s.ndy+2; j++)
+        for (unsigned int i = 0; i < m_s.ndx+2; i++)
+            for (unsigned int j = 0; j < m_s.ndy+2; j++)
                 m_T1[i][j] = m_s.rank;
     }
     else
@@ -59,10 +59,10 @@ void HeatTransfer::init(bool init_with_rank)
         const double hy = 2.0 * 4.0*atan(1.0)/m_s.ndy;
 
         double x, y;
-        for (int i = 0; i < m_s.ndx+2; i++)
+        for (unsigned int i = 0; i < m_s.ndx+2; i++)
         {
             x = 0.0 + hx*(i-1);
-            for (int j = 0; j < m_s.ndy+2; j++)
+            for (unsigned int j = 0; j < m_s.ndy+2; j++)
             {
                 y = 0.0 + hy*(j-1);
                 m_T1[i][j] = cos(8*x) + cos(6*x) - cos(4*x) + cos(2*x) - cos(x) +
@@ -88,10 +88,10 @@ void HeatTransfer::printT(std::string message, MPI_Comm comm) const
     }
 
     std::cout << "Rank " << rank << " " << message << std::endl;
-    for (int i = 0; i < m_s.ndx+2; i++)
+    for (unsigned int i = 0; i < m_s.ndx+2; i++)
     {
         std::cout << "  T[" << i << "][] = ";
-        for (int j = 0; j < m_s.ndy+2; j++)
+        for (unsigned int j = 0; j < m_s.ndy+2; j++)
         {
             std::cout << std::setw(6) << m_TCurrent[i][j];
         }
@@ -115,9 +115,9 @@ void HeatTransfer::switchCurrentNext()
 
 void HeatTransfer::iterate()
 {
-    for( int i = 1; i <= m_s.ndx; ++i)
+    for( unsigned int i = 1; i <= m_s.ndx; ++i)
     {
-        for( int j = 1; j <= m_s.ndy; ++j)
+        for( unsigned int j = 1; j <= m_s.ndy; ++j)
         {
             m_TNext[i][j] =
                     omega/4*(m_TCurrent[i-1][j] +
@@ -134,19 +134,19 @@ void HeatTransfer::heatEdges()
 {
     // Heat the whole global edges
     if( m_s.posx==0 )
-        for( int j = 0; j < m_s.ndy+2; ++j)
+        for( unsigned int j = 0; j < m_s.ndy+2; ++j)
             m_TCurrent[0][j]= edgetemp;
 
     if( m_s.posx==m_s.npx-1 )
-        for( int j = 0; j < m_s.ndy+2; ++j)
+        for( unsigned int j = 0; j < m_s.ndy+2; ++j)
             m_TCurrent[m_s.ndx+1][j]= edgetemp;
 
     if (m_s.posy==0)
-        for( int i = 0; i < m_s.ndx+2; ++i)
+        for( unsigned int i = 0; i < m_s.ndx+2; ++i)
             m_TCurrent[i][0]= edgetemp;
 
     if (m_s.posy==m_s.npy-1)
-        for( int i = 0; i < m_s.ndx+2; ++i)
+        for( unsigned int i = 0; i < m_s.ndx+2; ++i)
             m_TCurrent[i][m_s.ndy+1]= edgetemp;
 }
 
@@ -163,7 +163,7 @@ void HeatTransfer::exchange( MPI_Comm comm )
     if( m_s.rank_left >= 0 )
     {
         std::cout << "Rank " << m_s.rank << " send left to rank " <<  m_s.rank_left << std::endl;
-        for( int i = 0; i < m_s.ndx+2; ++i)
+        for( unsigned int i = 0; i < m_s.ndx+2; ++i)
             send_x[i] = m_TCurrent[i][1];
          MPI_Send(send_x, m_s.ndx+2, MPI_REAL8, m_s.rank_left, tag, comm);
     }
@@ -171,7 +171,7 @@ void HeatTransfer::exchange( MPI_Comm comm )
     {
         std::cout << "Rank " << m_s.rank << " receive from right from rank " <<  m_s.rank_right << std::endl;
         MPI_Recv(recv_x, m_s.ndx+2, MPI_REAL8, m_s.rank_right, tag, comm, &status);
-        for( int i = 0; i < m_s.ndx+2; ++i)
+        for( unsigned int i = 0; i < m_s.ndx+2; ++i)
             m_TCurrent[i][m_s.ndy+1] = recv_x[i];
     }
 
@@ -180,7 +180,7 @@ void HeatTransfer::exchange( MPI_Comm comm )
     if( m_s.rank_right >= 0 )
     {
         std::cout << "Rank " << m_s.rank << " send right to rank " <<  m_s.rank_right << std::endl;
-        for( int i = 0; i < m_s.ndx+2; ++i)
+        for( unsigned int i = 0; i < m_s.ndx+2; ++i)
             send_x[i] = m_TCurrent[i][m_s.ndy];
         MPI_Send(send_x, m_s.ndx+2, MPI_REAL8, m_s.rank_right, tag, comm);
     }
@@ -188,7 +188,7 @@ void HeatTransfer::exchange( MPI_Comm comm )
     {
         std::cout << "Rank " << m_s.rank << " receive from left from rank " <<  m_s.rank_left << std::endl;
         MPI_Recv(recv_x, m_s.ndx+2, MPI_REAL8, m_s.rank_left, tag, comm, &status);
-        for( int i = 0; i < m_s.ndx+2; ++i)
+        for( unsigned int i = 0; i < m_s.ndx+2; ++i)
             m_TCurrent[i][0] = recv_x[i];
     }
 
@@ -230,7 +230,7 @@ void HeatTransfer::exchange( MPI_Comm comm )
 std::vector<double> HeatTransfer::data_noghost() const
 {
     std::vector<double>d( m_s.ndx * m_s.ndy );
-    for( int i = 1; i <= m_s.ndx; ++i )
+    for( unsigned int i = 1; i <= m_s.ndx; ++i )
     {
         std::memcpy( &d[(i-1)*m_s.ndy], m_TCurrent[i]+1, m_s.ndy*sizeof(double));
     }
diff --git a/examples/heatTransfer/IO_adios2.cpp b/examples/heatTransfer/IO_adios2.cpp
index d2e5618aab1d17aa7e120448f399facc90f3156e..8290337c874c3443fd4c7b68a081b0cccf229cd0 100644
--- a/examples/heatTransfer/IO_adios2.cpp
+++ b/examples/heatTransfer/IO_adios2.cpp
@@ -6,18 +6,91 @@
  */
 
 #include "IO.h"
+#include "ADIOS_CPP.h"
 
+#include <string>
+
+static int rank_saved;
+adios::ADIOS * ad = nullptr;
+std::shared_ptr<adios::Engine> bpWriter;
+adios::Variable<double> * varT = nullptr;
 
 IO::IO( const Settings& s, MPI_Comm comm )
 {
+    rank_saved = s.rank;
     m_outputfilename = s.outputfile + ".bp";
+    ad = new adios::ADIOS( "adios2.xml", comm, adios::INFO );
+
+    //Define method for engine creation
+    // 1. Get method def from config file or define new one
+
+    adios::Method& bpWriterSettings = ad->DeclareMethod( "output" );
+    if( ! bpWriterSettings.isUserDefined())
+    {
+        // if not defined by user, we can change the default settings
+        bpWriterSettings.SetEngine( "BP" ); // BP is the default engine
+        bpWriterSettings.SetAvailableCores( 2); // no threading for data processing (except for staging)
+        bpWriterSettings.AddTransport( "File", "lucky=yes" ); // ISO-POSIX file is the default transport
+                                                              // Passing parameters to the transport
+        bpWriterSettings.SetParameters("have_metadata_file","yes" ); // Passing parameters to the engine
+        bpWriterSettings.SetParameters( "Aggregation", std::to_string((s.nproc+1)/2) ); // number of aggregators
+    }
+
+
+    // define T as 2D global array
+    varT = &ad->DefineVariable<double>(
+            "T",
+            {s.gndx,s.gndy},  // Global dimensions
+            {s.ndx,s.ndy},    // local size, could be defined later using SetSelection()
+            {s.offsx,s.offsy} // offset of the local array in the global space
+    );
+
+
+    //add transform to variable
+    //adios::Transform tr = adios::transform::BZIP2( );
+    //varT.AddTransform( tr, "" );
+    // varT.AddTransform( tr,"accuracy=0.001" );  // for ZFP
+
+    bpWriter = ad->Open( m_outputfilename, "w", comm, bpWriterSettings, adios::COLLECTIVE_IO);
+
+    if( bpWriter == nullptr )
+        throw std::ios_base::failure( "ERROR: failed to open ADIOS bpWriter\n" );
+
+
 }
 
 IO::~IO()
 {
+    bpWriter->Close();
+    delete ad;
+}
+
+void /*IO::*/old_style_write(int step, const HeatTransfer& ht, const Settings& s, MPI_Comm comm )
+{
+    bpWriter->Write<double>( *varT, ht.data_noghost().data());
+    bpWriter->Advance( );
 }
 
 void IO::write(int step, const HeatTransfer& ht, const Settings& s, MPI_Comm comm )
 {
+    /* This selection is redundant and not required, since we defined
+     * the selection already in DefineVariable(). It is here just as an example.
+     */
+    // Make a selection to describe the local dimensions of the variable we write and
+    // its offsets in the global spaces. This could have been done in adios.DefineVariable()
+    adios::Selection sel = adios.SelectionBoundingBox( {s.ndx,s.ndy}, {s.offsx,s.offsy} ); // local dims and offsets; both as list
+    var2D.SetSelection( sel );
+
+    /* Select the area that we want to write from the data pointer we pass to the writer.
+       Think HDF5 memspace, just not hyperslabs, only a bounding box selection.
+       Engine will copy this bounding box from the data pointer into the output buffer.
+       Size of the bounding box should match the "space" selection which was given above.
+       Default memspace is always the full selection.
+    */
+    adios::Selection memspace = adios.SelectionBoundingBox( {s.ndx,s.ndy}, {1,1} );
+    var2D.SetMemorySelection( memspace );
+
+    bpWriter->Write<double>( *varT, ht.data());
+    bpWriter->Advance( );
 }
 
diff --git a/examples/heatTransfer/Settings.cpp b/examples/heatTransfer/Settings.cpp
index 6cd14307dab7f0dee79990db7d2fa97620c1b032..8910cbc838a084511d8142eaaffd3a3480f2419d 100644
--- a/examples/heatTransfer/Settings.cpp
+++ b/examples/heatTransfer/Settings.cpp
@@ -13,7 +13,7 @@
 #include "Settings.h"
 
 
-static int convertToInt( std::string varName, char *arg )
+static unsigned int convertToUint( std::string varName, char *arg )
 {
     char *end;
     int retval = std::strtoll( arg, &end, 10);
@@ -22,26 +22,32 @@ static int convertToInt( std::string varName, char *arg )
         throw std::invalid_argument( "Invalid value given for " + varName + ": "
                 + std::string(arg) );
     }
-    return retval;
+    if( retval < 0 )
+    {
+        throw std::invalid_argument( "Negative value given for " + varName + ": "
+                + std::string(arg) );
+    }
+    return (unsigned int) retval;
 }
 
 Settings::Settings( int argc, char* argv [], int rank, int nproc )
-: rank{rank}, nproc{nproc}
+: rank{rank}
 {
     if (argc < 8)
     {
         throw std::invalid_argument( "Not enough arguments" );
     }
+    this->nproc = (unsigned int) nproc;
 
     outputfile = argv[1];
-    npx = convertToInt("N", argv[2]);
-    npy = convertToInt("M", argv[3]);
-    ndx = convertToInt("nx", argv[4]);
-    ndy = convertToInt("ny", argv[5]);
-    steps = convertToInt("steps", argv[6]);
-    iterations = convertToInt("iterations", argv[7]);
-
-    if( npx * npy != nproc )
+    npx = convertToUint("N", argv[2]);
+    npy = convertToUint("M", argv[3]);
+    ndx = convertToUint("nx", argv[4]);
+    ndy = convertToUint("ny", argv[5]);
+    steps = convertToUint("steps", argv[6]);
+    iterations = convertToUint("iterations", argv[7]);
+
+    if( npx * npy != this->nproc )
     {
         throw std::invalid_argument( "N*M must equal the number of processes" );
     }
diff --git a/examples/heatTransfer/Settings.h b/examples/heatTransfer/Settings.h
index 0db8b28d9cea08666a6448ef8289d6610eb79956..26ec50e18b270dc8945fd6df242116de89536931 100644
--- a/examples/heatTransfer/Settings.h
+++ b/examples/heatTransfer/Settings.h
@@ -16,27 +16,27 @@ class Settings
 public:
     // user arguments
     std::string outputfile;
-    int npx; // Number of processes in X (slow) dimension
-    int npy; // Number of processes in Y (fast) dimension
-    int ndx; // Local array size in X dimension per process
-    int ndy; // Local array size in y dimension per process
-    int steps; // Number of output steps
-    int iterations; // Number of computing iterations between steps
+    unsigned int npx; // Number of processes in X (slow) dimension
+    unsigned int npy; // Number of processes in Y (fast) dimension
+    unsigned int ndx; // Local array size in X dimension per process
+    unsigned int ndy; // Local array size in y dimension per process
+    unsigned int steps; // Number of output steps
+    unsigned int iterations; // Number of computing iterations between steps
 
     // calculated values from those arguments and number of processes
-    int gndx; // Global array size in slow dimension
-    int gndy; // Global array size in fast dimension
+    unsigned int gndx; // Global array size in slow dimension
+    unsigned int gndy; // Global array size in fast dimension
     // X dim positions: rank 0, npx, 2npx... are in the same X position
     // Y dim positions: npx number of consecutive processes belong to one row (npx columns)
-    int posx; // Position of this process in X dimension
-    int posy; // Position of this process in Y dimension
-    int offsx; // Offset of local array in X dimension on this process
-    int offsy; // Offset of local array in Y dimension on this process
+    unsigned int posx; // Position of this process in X dimension
+    unsigned int posy; // Position of this process in Y dimension
+    unsigned int offsx; // Offset of local array in X dimension on this process
+    unsigned int offsy; // Offset of local array in Y dimension on this process
 
     int rank;  // MPI rank
-    int nproc; // number of processors
+    unsigned int nproc; // number of processors
 
-    // neighbours by their MPI ranks
+    // neighbors by their MPI ranks, -1 if there is no such neighbor
     int rank_left;
     int rank_right;
     int rank_up;
diff --git a/examples/heatTransfer/main.cpp b/examples/heatTransfer/main.cpp
index f000dbd185b571308480bf3cef303ee7f5804741..22fd919cefd2338b3bd79d8df3ef8ec81d7cd8a6 100644
--- a/examples/heatTransfer/main.cpp
+++ b/examples/heatTransfer/main.cpp
@@ -68,11 +68,11 @@ int main( int argc, char* argv [] )
         ht.printT("Heated T:", mpiHeatTransferComm);
         io.write( 0, ht, settings, mpiHeatTransferComm );
 
-        for( int t = 1; t <= settings.steps; ++t )
+        for( unsigned int t = 1; t <= settings.steps; ++t )
         {
             if( rank == 0 )
                 std::cout << "Step " << t << ":\n";
-            for( int iter = 1; iter <= settings.iterations; ++iter )
+            for( unsigned int iter = 1; iter <= settings.iterations; ++iter )
             {
                 ht.iterate();
                 ht.exchange( mpiHeatTransferComm );