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 );