/* * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * * reader.cpp * * Created on: Feb 13, 2017 * Author: pnorbert */ #include <iostream> #include <vector> #include <adios2.h> #include <mpi.h> 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; adios::ADIOS adios(MPI_COMM_WORLD, adiosDebug); // Application variable std::vector<double> NiceArray; std::vector<float> RaggedArray; int Nparts; int Nwriters; int Nsteps; try { // Define method for engine creation // 1. Get method def from config file or define new one adios::Method &bpReaderSettings = adios.GetMethod("input"); if (bpReaderSettings.undeclared()) { // if not defined by user, we can change the default settings bpReaderSettings.SetEngine("BP"); // BP is the default engine // By default we see all steps available in a file, so the next line // is // not needed bpReaderSettings.SetParameters("Stepping", false); } // Create engine smart pointer due to polymorphism, // Default behavior // auto bpReader = adios.Open( "myNumbers.bp", "r" ); // this would just open with a default transport, which is "BP" auto bpReader = adios.Open("myNumbers.bp", "r", bpReaderSettings); // All the above is same as default use: // auto bpReader = adios.Open( "myNumbers.bp", "r"); if (bpReader == nullptr) throw std::ios_base::failure( "ERROR: failed to open ADIOS bpReader\n"); /* Note: there is no global number of steps. Each variable has its own * number of steps */ /* NX */ /* There is a single value for each step. We can read all into a 1D * array * with a step selection. * We can also just conveniently get the first with a simple read * statement. * Steps are not automatically presented as an array dimension and read * does * not read it as array. */ unsigned int Nx; bpReader->Read<unsigned int>( "NX", &Nx); // read a Global scalar which has a single value in a step std::shared_ptr<adios::Variable<void>> varNx = bpReader.InquiryVariable("Nx"); std::vector<int> Nxs(varNx->nsteps()); // number of steps available // make a StepSelection to select multiple steps. Args: From, #of // consecutive steps std::unique_ptr<adios::StepSelection> stepsNx = adios.StepSelection(0, varNx->nsteps()); // ? How do we make a selection for an arbitrary list of steps ? varNX.SetStepSelection(stepsNx); bpReader->Read<unsigned int>(varNx, Nxs.data()); auto itmax = std::max_element(std::begin(Nxs), std::end(Nxs)); auto itmin = std::min_element(std::begin(Nxs), std::end(Nxs)); if (*itmin != *itmax) { throw std::ios_base::failure( "ERROR: NX is not the same at all steps!\n"); } /* nproc */ bpReader->Read<int>("nproc", &Nwriters); // also a global scalar /* Nparts */ // Nparts local scalar is presented as a 1D array of Nwriters elements. // We can read all steps into a 2D array of nproc * Nwriters std::shared_ptr<adios::Variable<void>> varNparts = bpReader.InquiryVariable("Nparts"); std::vector<int> partsV(Nproc * Nwriters); varNparts->SetStepSelection( adios.StepSelection(0, varNparts->nsteps())); bpReader->Read<int>(varNparts, partsV.data()); // missing spatial selection = whole // array at each step /* Nice */ // inquiry about a variable, whose name we know std::shared_ptr<adios::Variable<void>> varNice = bpReader.InquiryVariable("Nice"); if (varNice == nullptr) throw std::ios_base::failure("ERROR: failed to find variable " "'myDoubles' in input file\n"); // ? how do we know about the type? std::string varNice->m_Type unsigned long long int gdim = varMyDoubles->m_GlobalDimensions[0]; // ?member var or member func? unsigned long long int ldim = gdim / nproc; unsigned long long int offs = rank * ldim; if (rank == nproc - 1) { ldim = gdim - (ldim * gdim); } NiceArray.reserve(ldim); // Make a 1D selection to describe the local dimensions of the variable // we // READ and // its offsets in the global spaces std::unique_ptr<adios::Selection> bbsel = adios.SelectionBoundingBox( {ldim}, {offs}); // local dims and offsets; both as list bpReader->Read<double>("Nice", bbsel, NiceArray.data()); // Base class Engine own the // Read<T> that will call // overloaded Read from Derived /* Ragged */ // inquiry about a variable, whose name we know std::shared_ptr<adios::Variable<void>> varRagged = bpReader.InquiryVariable("Ragged"); if (varRagged->m_GlobalDimensions[1] != adios::VARYING_DIMENSION) { throw std::ios_base::failure( "Unexpected condition: Ragged array's fast dimension " "is supposed to be VARYING_DIMENSION\n"); } // We have here varRagged->sum_nblocks, nsteps, nblocks[], global if (rank < varRagged->nblocks[0]) // same as rank < Nwriters in this example { // get per-writer size information varRagged->InquiryBlocks(); // now we have the dimensions per block unsigned long long int ldim = varRagged->blockinfo[rank].m_Dimensions[0]; RaggedArray.resize(ldim); std::unique_ptr<adios::Selection> wbsel = adios.SelectionWriteblock(rank); bpReader->Read<float>("Ragged", wbsel, RaggedArray.data()); // We can use bounding box selection as well std::unique_ptr<adios::Selection> rbbsel = adios.SelectionBoundingBox({1, ldim}, {rank, 0}); bpReader->Read<float>("Ragged", rbbsel, RaggedArray.data()); } /* Extra help to process Ragged */ int maxRaggedDim = varRagged->GetMaxGlobalDimensions(1); // contains the largest std::vector<int> raggedDims = varRagged->GetVaryingGlobalDimensions( 1); // contains all individual sizes in that dimension // Close file/stream bpReader->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"; } } MPI_Finalize(); return 0; }