/*========================================================================= Program: Visualization Toolkit Module: ADIOSReader.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include #include "ADIOSReader.h" namespace ADIOS { //---------------------------------------------------------------------------- struct Reader::InitContext { static int RefCount; static MPI_Comm GlobalComm; static ADIOS_READ_METHOD Method; static std::string MethodArgs; MPI_Comm Comm; int Rank; int CommSize; InitContext() : Comm(GlobalComm) { if(this->RefCount == 0) { int init = 0; MPI_Initialized(&init); ReadError::TestEq(1, init, "InitContext: MPI is not yet initialized"); int err = adios_read_init_method(Method, this->Comm, MethodArgs.c_str()); ReadError::TestEq(0, err); } ++this->RefCount; MPI_Comm_size(this->Comm, &this->CommSize); MPI_Comm_rank(this->Comm, &this->Rank); } ~InitContext() { --this->RefCount; if(this->RefCount == 0) { // If we've gotten this far then we know that MPI has been initialized //already MPI_Barrier(this->Comm); adios_read_finalize_method(Method); } } }; // Default communicator is invalid //MPI_Comm Reader::InitContext::GlobalComm = MPI_COMM_NULL; MPI_Comm Reader::InitContext::GlobalComm = MPI_COMM_WORLD; ADIOS_READ_METHOD Reader::InitContext::Method = ADIOS_READ_METHOD_BP; std::string Reader::InitContext::MethodArgs = ""; int Reader::InitContext::RefCount = 0; //---------------------------------------------------------------------------- struct Reader::ReaderImpl { ReaderImpl() : File(nullptr), StepBegin(0), StepEnd(0) { } ~ReaderImpl() { for(std::vector::iterator a = this->Attributes.begin(); a != this->Attributes.end(); ++a) { delete *a; } for(std::vector::iterator s = this->Scalars.begin(); s != this->Scalars.end(); ++s) { delete *s; } for(std::vector::iterator v = this->Arrays.begin(); v != this->Arrays.end(); ++v) { delete *v; } } ADIOS_FILE *File; size_t StepBegin; size_t StepEnd; std::vector Attributes; std::vector Scalars; std::vector Arrays; }; //-------------------:--------------------------------------------------------- bool Reader::SetCommunicator(MPI_Comm comm) { // The communicator can only be set if ADIOS has not yet been initialized if(Reader::InitContext::RefCount == 0) { Reader::InitContext::GlobalComm = comm; return true; } return false; } //-------------------:--------------------------------------------------------- bool Reader::SetReadMethod(ReadMethod method, const std::string& methodArgs) { // The communicator can only be set if ADIOS has not yet been initialized if(Reader::InitContext::RefCount == 0) { Reader::InitContext::Method = static_cast(method); Reader::InitContext::MethodArgs = methodArgs; return true; } return false; } //---------------------------------------------------------------------------- Reader::Reader() : Ctx(new InitContext), Impl(new ReaderImpl) { } //---------------------------------------------------------------------------- Reader::~Reader() { this->Close(); delete this->Impl; delete this->Ctx; } //---------------------------------------------------------------------------- bool Reader::IsOpen() const { return this->Impl->File != nullptr; } //---------------------------------------------------------------------------- const std::vector& Reader::GetAttributes() const { return this->Impl->Attributes; } //---------------------------------------------------------------------------- const std::vector& Reader::GetScalars() const { return this->Impl->Scalars; } //---------------------------------------------------------------------------- const std::vector& Reader::GetArrays() const { return this->Impl->Arrays; } //---------------------------------------------------------------------------- void Reader::Open(const std::string &fileName) { ReadError::TestEq(nullptr, this->Impl->File, "Open: An existing file is already open"); // Open the file this->Impl->File = adios_read_open_file(fileName.c_str(), this->Ctx->Method, this->Ctx->Comm); ReadError::TestNe(nullptr, this->Impl->File); // Poplulate step information this->Impl->StepBegin = this->Impl->File->current_step; this->Impl->StepEnd = this->Impl->File->last_step; // Polulate attributes for(int i = 0; i < this->Impl->File->nattrs; ++i) { this->Impl->Attributes.push_back(new Attribute(this->Impl->File, i)); } // Preload the scalar data and cache the array metadata for(int i = 0; i < this->Impl->File->nvars; ++i) { ADIOS_VARINFO *v = adios_inq_var_byid(this->Impl->File, i); ReadError::TestNe(nullptr, v); if(v->ndim == 0) { this->Impl->Scalars.push_back(new Scalar(this->Impl->File, v)); } else { this->Impl->Arrays.push_back(new VarInfo(this->Impl->File, v)); } adios_free_varinfo(v); } } //---------------------------------------------------------------------------- void Reader::Close() { if(this->Impl->File) { adios_read_close(this->Impl->File); this->Impl->File = nullptr; } } //---------------------------------------------------------------------------- void Reader::GetStepRange(int &tStart, int &tEnd) const { ReadError::TestNe(nullptr, this->Impl->File, "GetStepRange: File not open"); tStart = this->Impl->StepBegin; tEnd = this->Impl->StepEnd; } //---------------------------------------------------------------------------- void Reader::ScheduleReadArray(int id, void *data, int step, int block) { ADIOS_SELECTION *sel = adios_selection_writeblock(block); ReadError::TestNe(nullptr, sel); int err = adios_schedule_read_byid(this->Impl->File, sel, id, step, 1, data); ReadError::TestEq(0, err); adios_selection_delete(sel); } //---------------------------------------------------------------------------- void Reader::ReadArrays(void) { int err = adios_perform_reads(this->Impl->File, 1); ReadError::TestEq(0, err); } } // End namespace ADIOS