diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index cff55b7612dea88c6033417e74a3e199434fde0a..0ea4819bccbfb48f061076bbadb16dac07818466 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,6 +3,7 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# +add_subdirectory(basics) add_subdirectory(hello) add_subdirectory(heatTransfer) add_subdirectory(experimental) diff --git a/examples/basics/CMakeLists.txt b/examples/basics/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..94fa54cd4c435d3cb4b83e199e909d21e85e8194 --- /dev/null +++ b/examples/basics/CMakeLists.txt @@ -0,0 +1,9 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +add_subdirectory(globalArray) +add_subdirectory(joinedArray) +add_subdirectory(localArray) +add_subdirectory(values) diff --git a/examples/basics/globalArray/CMakeLists.txt b/examples/basics/globalArray/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7a0af15e3e998029c72366b30d034fddab35445c --- /dev/null +++ b/examples/basics/globalArray/CMakeLists.txt @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +add_executable(globalArray_write globalArray_write.cpp) + +if(ADIOS_USE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + + target_include_directories(globalArray_write PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(globalArray_write ${MPI_C_LIBRARIES}) + +endif() + +target_link_libraries(globalArray_write adios2) + diff --git a/examples/basics/globalArray/globalArray.xml b/examples/basics/globalArray/globalArray.xml new file mode 100644 index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba --- /dev/null +++ b/examples/basics/globalArray/globalArray.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="Output"> + <engine name="BPFileWriter"/> + <transport name= "File"/> + </io> + +</adios-config> + diff --git a/examples/basics/globalArray/globalArray_write.cpp b/examples/basics/globalArray/globalArray_write.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a27cda44e7978daecaf26fb5a8d790e46885286 --- /dev/null +++ b/examples/basics/globalArray/globalArray_write.cpp @@ -0,0 +1,136 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Write a global array from multiple processors. + * + * A global array is an N-dimensional array. A process can write a sub-array + * into the global array by stating the N-dimensional offset and the size of + * the sub-array. At reading, one can read back any portion of the array + * regardless of how many processors wrote that data. + * + * Processes are NOT required + * - to stay in the boundaries of the global dimensions. However, one will not + * be able to read back data outside of the boundaries. + * - to fill the whole global array, i.e. one can leave holes in it. At reading, + * one will get the fill-value set for the array for those coordinates that + * are not written by any process. + * + * The global dimensions of a global array MUST NOT change over time. + * If they are, then the array should be handled as a local array. Of course, if + * only a single output step is written to a file, that still shows up at + * reading as a global array. + * + * The decomposition of the array across the processes, however, can change + * between output steps. + * + * Created on: Jun 2, 2017 + * Author: pnorbert + */ + +#include <iostream> +#include <vector> + +#include <adios2.h> +#ifdef ADIOS2_HAVE_MPI +#include <mpi.h> +#endif + +int main(int argc, char *argv[]) +{ + int rank = 0, nproc = 1; +#ifdef ADIOS2_HAVE_MPI + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &nproc); +#endif + const bool adiosDebug = true; + const int NSTEPS = 5; + +#ifdef ADIOS2_HAVE_MPI + adios::ADIOS adios("globalArray.xml", MPI_COMM_WORLD); +#else + adios::ADIOS adios("globalArray.xml", adios::Verbose::WARN); +#endif + + // Application variables for output + const unsigned int Nx = 10; + // Global 2D array, size of nproc x Nx, with 1D decomposition + // Each process writes one "row" of the 2D matrix. + std::vector<double> row(Nx); + + try + { + // Get io settings from the config file or + // create one with default settings here + adios::IO &io = adios.DeclareIO("Output"); + + /* + * Define global array: type, name, global dimensions + * The local process' part (start, count) can be defined now or later + * before Write(). + */ + adios::Variable<double> &varGlobalArray = + io.DefineVariable<double>("GlobalArray", {(unsigned int)nproc, Nx}); + + // Open file. "w" means we overwrite any existing file on disk, + // but Advance() will append steps to the same file. + auto writer = io.Open("globalArray.bp", adios::OpenMode::Write); + + if (!writer) + throw std::ios_base::failure( + "ERROR: failed to open file with ADIOS\n"); + + for (int step = 0; step < NSTEPS; step++) + { + for (int i = 0; i < Nx; i++) + { + row[i] = step * Nx * nproc * 1.0 + rank * Nx * 1.0 + (double)i; + } + + // Make a 2D selection to describe the local dimensions of the + // variable we write and its offsets in the global spaces + adios::SelectionBoundingBox sel({(unsigned int)rank, 0}, {1, Nx}); + varGlobalArray.SetSelection(sel); + writer->Write<double>(varGlobalArray, row.data()); + + // Indicate we are done for this step. + // Disk I/O will be performed during this call unless + // time aggregation postpones all of that to some later step + writer->Advance(); + } + + // Called once: indicate that we are done with this output for the run + writer->Close(); + } + catch (std::invalid_argument &e) + { + if (rank == 0) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::ios_base::failure &e) + { + if (rank == 0) + { + std::cout << "System exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::exception &e) + { + if (rank == 0) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/basics/joinedArray/CMakeLists.txt b/examples/basics/joinedArray/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c4fe971950a755f41fff0c5b0917bee2c2b20987 --- /dev/null +++ b/examples/basics/joinedArray/CMakeLists.txt @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +add_executable(joinedArray_write joinedArray_write.cpp) + +if(ADIOS_USE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + + target_include_directories(joinedArray_write PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(joinedArray_write ${MPI_C_LIBRARIES}) + +endif() + +target_link_libraries(joinedArray_write adios2) + diff --git a/examples/basics/joinedArray/joinedArray.xml b/examples/basics/joinedArray/joinedArray.xml new file mode 100644 index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba --- /dev/null +++ b/examples/basics/joinedArray/joinedArray.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="Output"> + <engine name="BPFileWriter"/> + <transport name= "File"/> + </io> + +</adios-config> + diff --git a/examples/basics/joinedArray/joinedArray_write.cpp b/examples/basics/joinedArray/joinedArray_write.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf3e85ef1872b964dcfb855031da74a6de0a5175 --- /dev/null +++ b/examples/basics/joinedArray/joinedArray_write.cpp @@ -0,0 +1,138 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Write local arrays from multiple processors and make ADIOS join them + * at reading to show a global array + * + * If every process has an array that is different only in one dimension + * it can be presented as a global array by joining the arrays together. + * E.g. if every process has a table with a different number of rows, + * and one does not want to do a global communication to calculate the offsets + * in the global table, one can just write the local arrays and let ADIOS + * calculate the offsets at read time (when all sizes are known by any process). + * + * bpls can show the size of each block of the table: + * bpls -D <file> <variable> + * + * Note: only one dimension can be joinable, every other dimension must be the + * same on each process. + * + * Note: the local dimension size in the joinable dimension is allowed to change + * over time within each processor. However, if the sum of all local sizes + * changes over time, the result will look like a local array. + * (Because global arrays with changing global dimension over time can only be + * handled as local arrays in ADIOS) + * + * + * Created on: Jun 2, 2017 + * Author: pnorbert + */ + +#include <iostream> +#include <vector> + +#include <adios2.h> +#ifdef ADIOS2_HAVE_MPI +#include <mpi.h> +#endif + +int main(int argc, char *argv[]) +{ + int rank = 0, nproc = 1; +#ifdef ADIOS2_HAVE_MPI + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &nproc); +#endif + const bool adiosDebug = true; + const int NSTEPS = 5; + + // generate different random numbers on each process, + // but always the same sequence at each run + srand(rank * 32767); + +#ifdef ADIOS2_HAVE_MPI + adios::ADIOS adios("localArray.xml", MPI_COMM_WORLD); +#else + adios::ADIOS adios("localArray.xml", adios::Verbose::WARN); +#endif + + // Application variables for output + // random size per process, 5..10 each + const unsigned int Nrows = rand() % 6 + 5; + const unsigned int Ncols = 4; + // Local array, size is fixed over time on each process + std::vector<double> mytable(Nrows * Ncols); + + try + { + // Get io settings from the config file or + // create one with default settings here + adios::IO &io = adios.DeclareIO("Output"); + + /* + * Define joinable local array: type, name, global and local size + * Starting offset can be an empty vector + * Only one global dimension can be joined + */ + adios::Variable<double> &varTable = io.DefineVariable<double>( + "table", {adios::JoinedDim, Ncols}, {}, {Nrows, Ncols}); + + // Open file. "w" means we overwrite any existing file on disk, + // but Advance() will append steps to the same file. + auto writer = io.Open("joinedArray.bp", adios::OpenMode::Write); + + if (writer == nullptr) + throw std::ios_base::failure( + "ERROR: failed to open file with ADIOS\n"); + + for (int step = 0; step < NSTEPS; step++) + { + for (int row = 0; row < Nrows; row++) + { + for (int col = 0; col < Ncols; col++) + { + mytable[row * Ncols + col] = + rank * 1.0 + row * 0.1 + col * 0.01; + } + } + + writer->Write<double>(varTable, mytable.data()); + + writer->Advance(); + } + + writer->Close(); + } + catch (std::invalid_argument &e) + { + if (rank == 0) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::ios_base::failure &e) + { + if (rank == 0) + { + std::cout << "System exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::exception &e) + { + if (rank == 0) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/basics/localArray/CMakeLists.txt b/examples/basics/localArray/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..91077b8cedcd7a2abdb8412a74774f25e14e546d --- /dev/null +++ b/examples/basics/localArray/CMakeLists.txt @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +add_executable(localArray_write localArray_write.cpp) + +if(ADIOS_USE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + + target_include_directories(localArray_write PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(localArray_write ${MPI_C_LIBRARIES}) + +endif() + +target_link_libraries(localArray_write adios2) + diff --git a/examples/basics/localArray/localArray.xml b/examples/basics/localArray/localArray.xml new file mode 100644 index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba --- /dev/null +++ b/examples/basics/localArray/localArray.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="Output"> + <engine name="BPFileWriter"/> + <transport name= "File"/> + </io> + +</adios-config> + diff --git a/examples/basics/localArray/localArray_write.cpp b/examples/basics/localArray/localArray_write.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a38151c2ce07ecd50c1390e94ef04d770853deb --- /dev/null +++ b/examples/basics/localArray/localArray_write.cpp @@ -0,0 +1,151 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Write local arrays from multiple processors. + * + * If one cannot or does not want to organize arrays present on each process + * as one global array, still one can write them out with the same name. + * Reading, however, needs to be handled differently: each process' array has + * to be read separately, using Writeblock selections. The size of each process + * block should be discovered by the reading application by inquiring per-block + * size information of the variable, and allocate memory for reading + * accordingly. + * + * bpls can show the size of each block of the variable: + * bpls -D <file> <variable> + * + * + * Created on: Jun 2, 2017 + * Author: pnorbert + */ + +#include <iostream> +#include <vector> + +#include <adios2.h> +#ifdef ADIOS2_HAVE_MPI +#include <mpi.h> +#endif + +int main(int argc, char *argv[]) +{ + int rank = 0, nproc = 1; +#ifdef ADIOS2_HAVE_MPI + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &nproc); +#endif + const bool adiosDebug = true; + const int NSTEPS = 5; + + // generate different random numbers on each process, + // but always the same sequence at each run + srand(rank * 32767); + +#ifdef ADIOS2_HAVE_MPI + adios::ADIOS adios("localArray.xml", MPI_COMM_WORLD); +#else + adios::ADIOS adios("localArray.xml", adios::Verbose::WARN); +#endif + + // Application variables for output + // random size per process, 5..10 each + unsigned int Nx = rand() % 6 + 5; + // Local array, size is fixed over time on each process + std::vector<double> v1(Nx); + + // random size per process, a different size at each step + unsigned int Nelems; + // Local array, size is changing over time on each process + std::vector<double> v2; + + try + { + // Get io settings from the config file or + // create one with default settings here + adios::IO &io = adios.DeclareIO("Output"); + + /* + * Define local array: type, name, local size + * Global dimension and starting offset must be an empty vector + */ + adios::Variable<double> &varV1 = + io.DefineVariable<double>("v1", {}, {}, {Nx}); + + /* + * Define local array: type, name + * Global dimension and starting offset must be an empty vector + * but local size must NOT be an empty vector. + * We can use {adios::UnknownDim} for this purpose or any number + * but we will modify it before writing + */ + adios::Variable<double> &varV2 = + io.DefineVariable<double>("v2", {}, {}, {adios::UnknownDim}); + + // Open file. "w" means we overwrite any existing file on disk, + // but Advance() will append steps to the same file. + auto writer = io.Open("localArray.bp", adios::OpenMode::Write); + + if (writer == nullptr) + throw std::ios_base::failure( + "ERROR: failed to open file with ADIOS\n"); + + for (int step = 0; step < NSTEPS; step++) + { + for (int i = 0; i < Nx; i++) + { + v1[i] = rank * 1.0 + step * 0.1; + } + + writer->Write<double>(varV1, v1.data()); + + // random size per process per step, 5..10 each + Nelems = rand() % 6 + 5; + v2.reserve(Nelems); + for (int i = 0; i < Nelems; i++) + { + v2[i] = rank * 1.0 + step * 0.1; + } + + // Set the size of the array now because we did not know + // the size at the time of definition + varV2.SetSelection({}, {Nelems}); + writer->Write<double>(varV2, v2.data()); + + writer->Advance(); + } + + writer->Close(); + } + catch (std::invalid_argument &e) + { + if (rank == 0) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::ios_base::failure &e) + { + if (rank == 0) + { + std::cout << "System exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::exception &e) + { + if (rank == 0) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/basics/values/CMakeLists.txt b/examples/basics/values/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b5894f894d855a004bcce67448470ea633b18b67 --- /dev/null +++ b/examples/basics/values/CMakeLists.txt @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +add_executable(values_write values_write.cpp) + +if(ADIOS_USE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + + target_include_directories(values_write PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(values_write ${MPI_C_LIBRARIES}) + +endif() + +target_link_libraries(values_write adios2) + diff --git a/examples/basics/values/values.xml b/examples/basics/values/values.xml new file mode 100644 index 0000000000000000000000000000000000000000..68b7e9f6e33fd48b7a5fffcbf36754babc6ae3ba --- /dev/null +++ b/examples/basics/values/values.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="Output"> + <engine name="BPFileWriter"/> + <transport name= "File"/> + </io> + +</adios-config> + diff --git a/examples/basics/values/values_write.cpp b/examples/basics/values/values_write.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90e3fd4bde97188564eebbb9d1bdb9936eae6171 --- /dev/null +++ b/examples/basics/values/values_write.cpp @@ -0,0 +1,158 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Write single values to a file. There are four different cases: + * 1. Global constant - same on all processes, constant over time + * 2. Global value - same on all processes, may change over time + * 3. Local constants - different across processes, constant over time + * 4. Local value - different across processes, may change over time + * + * Constants are not handled separately from time-varying values in ADIOS. + * Simply write them only in the first step. + * + * Writing a global value from multiple processes does not hurt but it is + * useless. + * + * Created on: Jun 2, 2017 + * Author: pnorbert + */ + +#include <iostream> +#include <vector> + +#include <adios2.h> +#ifdef ADIOS2_HAVE_MPI +#include <mpi.h> +#endif + +int main(int argc, char *argv[]) +{ + int rank = 0, nproc = 1; +#ifdef ADIOS2_HAVE_MPI + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &nproc); +#endif + const bool adiosDebug = true; + const int NSTEPS = 5; + + // generate different random numbers on each process, + // but always the same sequence at each run + srand(rank * 32767); + +#ifdef ADIOS2_HAVE_MPI + adios::ADIOS adios("values.xml", MPI_COMM_WORLD); +#else + adios::ADIOS adios("values.xml"); +#endif + + // Application variables for output + // 1. Global value, constant across processes, constant over time + // This is 'nproc' + + // 2. Global value, constant across processes, varying value over time + // This is 'step' + + // 3. Local value, varying across processes, constant over time + // It will appear in reading as a 1D array of nproc elements. + // This is 'rank' + + // 4. Local value, varying across processes, varying over time + unsigned int Nparts; // random size per process, 5..10 each + + try + { + // Get io settings from the config file or + // create one with default settings here + adios::IO &io = adios.DeclareIO("Output"); + + /* + * Define variables + */ + // 1. Global constant, same value across processes, constant over time + adios::Variable<int> &varNproc = io.DefineVariable<int>("Nproc"); + + // 2. Global value, same value across processes, varying value over time + adios::Variable<int> &varStep = io.DefineVariable<int>("Step"); + + // 3. Local value, varying across processes, constant over time + adios::Variable<int> &varProcessID = + io.DefineVariable<int>("ProcessID", {adios::LocalValueDim}); + + // 4. Local value, varying across processes, varying over time + adios::Variable<unsigned int> &varNparts = + io.DefineVariable<unsigned int>("Nparts", {adios::LocalValueDim}); + + // Open file. "w" means we overwrite any existing file on disk, + // but Advance() will append steps to the same file. + auto writer = io.Open("values.bp", adios::OpenMode::Write); + + if (!writer) + throw std::ios_base::failure( + "ERROR: failed to open file with ADIOS\n"); + + for (int step = 0; step < NSTEPS; step++) + { + // random size per process, 5..10 each + Nparts = rand() % 6 + 5; + + // 1. and 2. Writing a global value from only one process + if (rank == 0) + { + // 1. Writing a global constant value only once + if (step == 0) + { + writer->Write<int>("Nproc", nproc); + } + writer->Write<int>(varStep, step); + } + + // 3. and 4. Writing a local value on every process. Will be shown + // at reading as a 1D array + if (step == 0) + { + writer->Write<int>(varProcessID, rank); + } + writer->Write<unsigned int>(varNparts, Nparts); + + // Indicate we are done for this step. + // Disk I/O will be performed during this call unless + // time aggregation postpones all of that to some later step + writer->Advance(); + } + + // Called once: indicate that we are done with this output for the run + writer->Close(); + } + catch (std::invalid_argument &e) + { + if (rank == 0) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::ios_base::failure &e) + { + if (rank == 0) + { + std::cout << "System exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch (std::exception &e) + { + if (rank == 0) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return 0; +}