Skip to content
Snippets Groups Projects
writer_multistep.cpp 6.44 KiB
Newer Older
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * writer.cpp
 *
 *  Created on: Feb 13, 2017
 *      Author: pnorbert
 */

#include <iostream>
#include <vector>
#include <mpi.h>
namespace adios
{
typedef enum { VARYING_DIMENSION = -1, LOCAL_VALUE = 0, GLOBAL_VALUE = 1 };
int main(int argc, char *argv[])
    int rank, nproc;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
    const bool adiosDebug = true;
    const int NSTEPS = 5;
    adios::ADIOS adios(MPI_COMM_WORLD, adiosDebug);
    // Application variable
    const unsigned int Nx = 10;
    int Nparts; // random size per process, 5..10 each
    std::vector<double> NiceArray(Nx);
    for (int i = 0; i < Nx; i++)
        NiceArray[i] = rank * Nx + (double)i;
    std::vector<float> RaggedArray;

    try
    {
        // Define group and variables with transforms, variables don't have
        // functions, only group can access variables
        adios::Variable<unsigned int> &varNX =
            adios.DefineVariable<unsigned int>(
                "NX"); // global single-value across processes
        adios::Variable<int> &varNproc = adios.DefineVariable<int>(
            "nproc", adios::GLOBAL_VALUE); // same def for global value
        adios::Variable<int> &varNparts =
            adios.DefineVariable<int>("Nparts",
                                      adios::LOCAL_VALUE); // a single-value
                                                           // different on
                                                           // every process
        adios::Variable<double> &varNice = adios.DefineVariable<double>(
            "Nice", {nproc * Nx}); // 1D global array
        adios::Variable<float> &varRagged = adios.DefineVariable<float>(
            "Ragged", {nproc, adios::VARYING_DIMENSION}); // ragged array

        // add transform to variable in group...not executed (just testing API)
        adios::Transform bzip2 = adios::transform::BZIP2();
        varNice->AddTransform(bzip2, 1);

        // Define method for engine creation
        // 1. Get method def from config file or define new one
        adios::Method &bpWriterSettings = adios.GetMethod("output");
        if (bpWriterSettings.undeclared())
        {
            // if not defined by user, we can change the default settings
            bpWriterSettings.SetEngine("BP"); // BP is the default engine
            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",
                                           (nproc + 1) /
                                               2); // number of aggregators
        }

        // Open returns a smart pointer to Engine containing the Derived class
        // Writer
        // "w" means we overwrite any existing file on disk, but AdvanceStep
        // will
        // append steps later.
        auto bpWriter = adios.Open("myNumbers.bp", "w", bpWriterSettings);

        if (bpWriter == nullptr)
            throw std::ios_base::failure(
                "ERROR: failed to open ADIOS bpWriter\n");

        for (int step; step < NSTEPS; step++)
        {
            int Nparts = rand() % 6 + 5; // random size per process, 5..10 each
            RaggedArray.reserve(Nparts);
            for (int i = 0; i < Nparts; i++)
            {
                RaggedArray[i] = rank * Nx + (float)i;
            }

            if (rank == 0)
            {
                // Writing a global scalar from only one process
                bpWriter->Write<unsigned int>(varNX, &Nx);
            }
            // Writing a local scalar on every process. Will be shown at reading
            // as a
            // 1D array
            bpWriter->Write<int>(varNparts, &Nparts);

            // Writing a global scalar on every process is useless. Information
            // will
            // be thrown away
            // and only rank 0's data will be in the output
            bpWriter->Write<int>(varNproc, &nproc);

            // Make a 1D selection to describe the local dimensions of the
            // variable we
            // write and
            // its offsets in the global spaces
            adios::Selection &sel = adios.SelectionBoundingBox(
                {Nx}, {rank * Nx}); // local dims and offsets; both as list
            NiceArray.SetSelection(sel);
            bpWriter->Write<double>(varNice,
                                    NiceArray.data()); // Base class Engine
                                                       // own the Write<T>
                                                       // that will call
                                                       // overloaded Write
                                                       // from Derived

            adios::Selection &lsel =
                adios.SelectionBoundingBox({1, Nparts}, {rank, 0});
            RaggedArray.SetSelection(sel);
            bpWriter->Write<float>(varRagged, RaggedArray.data()); // Base class
            // Engine own the
            // Write<T> that
            // will call
            // overloaded Write
            // from Derived

            // Indicate we are done for this step
            // N-to-M Aggregation, disk I/O will be performed during this call,
            // unless
            // time aggregation postpones all of that to some later step
            bpWriter->Advance();
        }

        // Called once: indicate that we are done with this output for the run
        bpWriter->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";
        }