diff --git a/examples/heatTransfer/read/CMakeLists.txt b/examples/heatTransfer/read/CMakeLists.txt index f14e54596ca5891401524289f561ed709e6afe55..2a4ff60f7820bffb18a092572058dc7e9f0b75de 100644 --- a/examples/heatTransfer/read/CMakeLists.txt +++ b/examples/heatTransfer/read/CMakeLists.txt @@ -7,6 +7,11 @@ if(ADIOS2_HAVE_MPI) add_executable(heatTransfer_read_adios2 heatRead_adios2.cpp PrintData.h) target_link_libraries(heatTransfer_read_adios2 adios2 MPI::MPI_C) + if(ADIOS2_HAVE_HDF5) + add_executable(heatTransfer_read_a2h5 heatRead_a2h5.cpp PrintData.h) + target_link_libraries(heatTransfer_read_a2h5 adios2 MPI::MPI_C) + endif() + if(ADIOS2_HAVE_ADIOS1) add_executable(heatTransfer_read_adios1 heatRead_adios1.cpp PrintData.h) target_link_libraries(heatTransfer_read_adios1 adios1::adios MPI::MPI_C) diff --git a/examples/heatTransfer/read/heatRead_a2h5.cpp b/examples/heatTransfer/read/heatRead_a2h5.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7820fb89d32d9778a5f18cf5760814489aa6450c --- /dev/null +++ b/examples/heatTransfer/read/heatRead_a2h5.cpp @@ -0,0 +1,161 @@ + +#include <mpi.h> + +#include "adios2.h" + +#include <cstdint> +#include <iomanip> +#include <iostream> +#include <math.h> +#include <memory> +#include <stdexcept> +#include <string> +#include <vector> + +#include "PrintData.h" + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + + if (argc < 2) + { + std::cout << "Not enough arguments: need an input file\n"; + return 1; + } + const char *inputfile = argv[1]; + + /* World comm spans all applications started with the same aprun command + on a Cray XK6. So we have to split and create the local + 'world' communicator for the reader only. + In normal start-up, the communicator will just equal the MPI_COMM_WORLD. + */ + + int wrank, wnproc; + MPI_Comm_rank(MPI_COMM_WORLD, &wrank); + MPI_Comm_size(MPI_COMM_WORLD, &wnproc); + MPI_Barrier(MPI_COMM_WORLD); + + const unsigned int color = 2; + MPI_Comm mpiReaderComm; + MPI_Comm_split(MPI_COMM_WORLD, color, wrank, &mpiReaderComm); + + int rank, nproc; + MPI_Comm_rank(mpiReaderComm, &rank); + MPI_Comm_size(mpiReaderComm, &nproc); + + try + { + adios2::ADIOS ad("adios2.xml", mpiReaderComm, adios2::DebugOFF); + + // Define method for engine creation + // 1. Get method def from config file or define new one + + adios2::IO &h5ReaderIO = ad.DeclareIO("input"); + if (!h5ReaderIO.InConfigFile()) + { + // if not defined by user, we can change the default settings + // BPFileWriter is the default engine + // h5ReaderIO.SetEngine("ADIOS1Reader"); + h5ReaderIO.SetEngine("HDF5Reader"); + // h5ReaderIO.SetParameters({{"num_threads", "2"}}); + + // ISO-POSIX file is the default transport + // Passing parameters to the transport + h5ReaderIO.AddTransport("File", {{"verbose", "4"}}); + } + + adios2::Engine &h5Reader = + h5ReaderIO.Open(inputfile, adios2::Mode::Read, mpiReaderComm); + + unsigned int gndx; + unsigned int gndy; + // h5Reader->Read<unsigned int>("gndx", &gndx); + // h5Reader->Read<unsigned int>("gndy", &gndy); + + adios2::Variable<unsigned int> *vgndx = + h5ReaderIO.InquireVariable<unsigned int>("gndx"); + + // gndx = vgndx->GetData()[0]; + adios2::Variable<unsigned int> *vgndy = + h5ReaderIO.InquireVariable<unsigned int>("gndy"); + // gndy = vgndy->GetData()[0]; + adios2::Variable<double> *vT = h5ReaderIO.InquireVariable<double>("T"); + + if ((vgndx == NULL) || (vgndy == NULL) || (vT == NULL)) + { + std::cout << "Unable to find expected variables: gndx, gndy and T" + << std::endl; + return 1; + } + + h5Reader.GetSync<unsigned int>(*vgndx, gndx); + h5Reader.GetSync<unsigned int>(*vgndy, gndy); + + if (rank == 0) + { + std::cout << "gndx = " << gndx << std::endl; + std::cout << "gndy = " << gndy << std::endl; + std::cout << "# of steps = " << vgndy->GetAvailableStepsCount() + << std::endl; + } + + // 1D decomposition of the columns, which is inefficient for reading! + adios2::Dims readsize({gndx, gndy / nproc}); + adios2::Dims offset({0LL, rank * readsize[1]}); + if (rank == nproc - 1) + { + // last process should read all the rest of columns + readsize[1] = gndy - readsize[1] * (nproc - 1); + } + + std::cout << "rank " << rank << " reads " << readsize[1] + << " columns from offset " << offset[1] << std::endl; + + if (readsize[1] == 0) + { + std::cout << "Nothing to read. exiting" << std::endl; + return 0; + } + + double *T = new double[vT->GetAvailableStepsCount() * readsize[0] * + readsize[1]]; + + // Create a 2D selection for the subset + vT->SetSelection(adios2::Box<adios2::Dims>(offset, readsize)); + vT->SetStepSelection( + adios2::Box<std::size_t>(0, vT->GetAvailableStepsCount())); + + h5Reader.GetSync<double>(*vT, T); + // Arrays are read by scheduling one or more of them + // and performing the reads at once + // h5Reader->ScheduleRead<double>(*vT, T); + // h5Reader->PerformReads(adios2::ReadMode::Blocking); + + printData(T, readsize.data(), offset.data(), rank, + vT->GetAvailableStepsCount()); + h5Reader.Close(); + delete[] T; + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + return 0; +} diff --git a/examples/heatTransfer/write/IO_h5mixer.cpp b/examples/heatTransfer/write/IO_h5mixer.cpp index a6365cff3dabe320f493580208ace70ad4f5a46f..1e6e4d99a7a6d1592786d2815dd94450624b1080 100644 --- a/examples/heatTransfer/write/IO_h5mixer.cpp +++ b/examples/heatTransfer/write/IO_h5mixer.cpp @@ -24,7 +24,8 @@ static int rank_saved; adios2::ADIOS *ad = nullptr; -std::shared_ptr<adios2::Engine> h5mixerWriter; +// std::shared_ptr<adios2::Engine> h5mixerWriter; +adios2::Engine *h5mixerWriter = nullptr; adios2::Variable<double> *varT = nullptr; adios2::Variable<unsigned int> *varGndx = nullptr; @@ -70,7 +71,7 @@ IO::IO(const Settings &s, MPI_Comm comm) // varT.AddTransform( tr, "" ); // varT.AddTransform( tr,"accuracy=0.001" ); // for ZFP - h5mixerWriter = h5io.Open(m_outputfilename, adios2::OpenMode::Write, comm); + h5mixerWriter = &h5io.Open(m_outputfilename, adios2::Mode::Write, comm); if (!h5mixerWriter) { @@ -88,6 +89,35 @@ IO::~IO() void IO::write(int step, const HeatTransfer &ht, const Settings &s, MPI_Comm comm) { + + h5mixerWriter->BeginStep(); + /* 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() + varT->SetSelection( + adios2::Box<adios2::Dims>({s.offsx, s.offsy}, {s.ndx, s.ndy})); + + /* 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. + */ + varT->SetMemorySelection(adios2::Box<adios2::Dims>({1, 1}, {s.ndx, s.ndy})); + + h5mixerWriter->PutSync<unsigned int>(*varGndx, s.gndx); + h5mixerWriter->PutSync<unsigned int>("gndy", s.gndy); + h5mixerWriter->PutSync<double>(*varT, ht.data_noghost().data()); + + h5mixerWriter->EndStep(); + +#ifdef NEVER #if 1 /* This selection is redundant and not required, since we defined @@ -120,9 +150,8 @@ void IO::write(int step, const HeatTransfer &ht, const Settings &s, h5mixerWriter->Advance(); #else - h5mixerWriter->Write<double>(*varT, ht.data_noghost().data()); h5mixerWriter->Advance(); - +#endif #endif } diff --git a/source/adios2/engine/hdf5/HDF5ReaderP.cpp b/source/adios2/engine/hdf5/HDF5ReaderP.cpp index a10a3e7b1b476d80c1960e2089236638108b8546..2d99551393100d93ea07acde3f58ce3fd30d5990 100644 --- a/source/adios2/engine/hdf5/HDF5ReaderP.cpp +++ b/source/adios2/engine/hdf5/HDF5ReaderP.cpp @@ -9,15 +9,16 @@ */ #include "HDF5ReaderP.h" +#include "HDF5ReaderP.tcc" #include "adios2/ADIOSMPI.h" namespace adios2 { -HDF5ReaderP::HDF5ReaderP(IO &io, const std::string &name, const Mode mode, +HDF5ReaderP::HDF5ReaderP(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm) -: Engine("HDF5Reader", io, name, mode, mpiComm), m_H5File(io.m_DebugMode) +: Engine("HDF5Reader", io, name, openMode, mpiComm), m_H5File(io.m_DebugMode) { m_EndMessage = ", in call to IO HDF5Reader Open " + m_Name + "\n"; Init(); @@ -39,6 +40,7 @@ bool HDF5ReaderP::IsValid() } return isValid; } + void HDF5ReaderP::Init() { if (m_OpenMode != Mode::Read) @@ -49,81 +51,196 @@ void HDF5ReaderP::Init() } m_H5File.Init(m_Name, m_MPIComm, false); - m_H5File.GetNumTimeSteps(); -} - -template <class T> -void HDF5ReaderP::UseHDFRead(const std::string &variableName, T *values, - hid_t h5Type) -{ - int rank, size; - MPI_Comm_rank(m_MPIComm, &rank); - MPI_Comm_size(m_MPIComm, &size); - - hid_t dataSetId = - H5Dopen(m_H5File.m_GroupId, variableName.c_str(), H5P_DEFAULT); - - if (dataSetId < 0) - { - return; - } - hid_t fileSpace = H5Dget_space(dataSetId); - - if (fileSpace < 0) - { - return; - } - int ndims = H5Sget_simple_extent_ndims(fileSpace); - hsize_t dims[ndims]; - herr_t status_n = H5Sget_simple_extent_dims(fileSpace, dims, NULL); - - // hsize_t start[ndims] = {0}, count[ndims] = {0}, stride[ndims] = {1}; - hsize_t start[ndims], count[ndims], stride[ndims]; - - int totalElements = 1; - for (int i = 0; i < ndims; i++) + int ts = m_H5File.GetNumTimeSteps(); + if (ts == 0) { - count[i] = dims[i]; - totalElements *= dims[i]; - start[i] = 0; - count[i] = 0; - stride[i] = 1; + throw std::runtime_error("This h5 file is NOT written by ADIOS2"); } - start[0] = rank * dims[0] / size; - count[0] = dims[0] / size; - if (rank == size - 1) + /* + */ + if (!m_InStreamMode) { - count[0] = dims[0] - count[0] * (size - 1); + m_H5File.ReadAllVariables(m_IO); } - - hid_t ret = H5Sselect_hyperslab(fileSpace, H5S_SELECT_SET, start, stride, - count, NULL); - if (ret < 0) + else { - return; + m_H5File.ReadAllVariables(m_IO); } +} - hid_t memDataSpace = H5Screate_simple(ndims, count, NULL); - - int elementsRead = 1; - for (int i = 0; i < ndims; i++) +template <class T> +void HDF5ReaderP::UseHDFRead(Variable<T> &variable, T *data, hid_t h5Type) +{ + int ts = 0; + T *values = data; + while (ts < variable.m_StepsCount) { - elementsRead *= count[i]; - } - - T data_array[elementsRead]; - ret = H5Dread(dataSetId, h5Type, memDataSpace, fileSpace, H5P_DEFAULT, - data_array); - - H5Sclose(memDataSpace); + m_H5File.SetTimeStep(variable.m_StepsStart + ts); + + hid_t dataSetId = + H5Dopen(m_H5File.m_GroupId, variable.m_Name.c_str(), H5P_DEFAULT); + if (dataSetId < 0) + { + return; + } + + hid_t fileSpace = H5Dget_space(dataSetId); + if (fileSpace < 0) + { + return; + } + + size_t slabsize = 1; + + int ndims = std::max(variable.m_Shape.size(), variable.m_Count.size()); + if (0 == ndims) + { // is scalar + hid_t ret = H5Dread(dataSetId, h5Type, H5S_ALL, H5S_ALL, + H5P_DEFAULT, values); + } + else + { + hsize_t start[ndims], count[ndims], stride[ndims]; + + for (int i = 0; i < ndims; i++) + { + count[i] = variable.m_Count[i]; + start[i] = variable.m_Start[i]; + slabsize *= count[i]; + stride[i] = 1; + } + hid_t ret = H5Sselect_hyperslab(fileSpace, H5S_SELECT_SET, start, + stride, count, NULL); + if (ret < 0) + return; + + hid_t memDataSpace = H5Screate_simple(ndims, count, NULL); + int elementsRead = 1; + for (int i = 0; i < ndims; i++) + { + elementsRead *= count[i]; + } + + ret = H5Dread(dataSetId, h5Type, memDataSpace, fileSpace, + H5P_DEFAULT, values); + H5Sclose(memDataSpace); + } + + H5Sclose(fileSpace); + H5Dclose(dataSetId); + + ts++; + values += slabsize; + } // while +} - H5Sclose(fileSpace); - H5Dclose(dataSetId); +/* +template <class T> +void HDF5ReaderP::UseHDFRead(const std::string &variableName, T *values, + hid_t h5Type) +{ + int rank, size; + MPI_Comm_rank(m_MPIComm, &rank); + MPI_Comm_size(m_MPIComm, &size); + + hid_t dataSetId = + H5Dopen(m_H5File.m_GroupId, variableName.c_str(), H5P_DEFAULT); + + if (dataSetId < 0) + { + return; + } + + hid_t fileSpace = H5Dget_space(dataSetId); + + if (fileSpace < 0) + { + return; + } + int ndims = H5Sget_simple_extent_ndims(fileSpace); + + if (ndims == 0) { // SCALAR + hid_t ret = H5Dread(dataSetId, h5Type, H5S_ALL, H5S_ALL, H5P_DEFAULT, +values); return; + } + + hsize_t dims[ndims]; + herr_t status_n = H5Sget_simple_extent_dims(fileSpace, dims, NULL); + + // hsize_t start[ndims] = {0}, count[ndims] = {0}, stride[ndims] = {1}; + hsize_t start[ndims], count[ndims], stride[ndims]; + + int totalElements = 1; + for (int i = 0; i < ndims; i++) + { + count[i] = dims[i]; + totalElements *= dims[i]; + start[i] = 0; + //count[i] = 0; + stride[i] = 1; + } + + start[0] = rank * dims[0] / size; + count[0] = dims[0] / size; + if (rank == size - 1) + { + count[0] = dims[0] - count[0] * (size - 1); + } + + hid_t ret = H5Sselect_hyperslab(fileSpace, H5S_SELECT_SET, start, stride, + count, NULL); + if (ret < 0) + { + return; + } + + hid_t memDataSpace = H5Screate_simple(ndims, count, NULL); + + int elementsRead = 1; + for (int i = 0; i < ndims; i++) + { + elementsRead *= count[i]; + } + +#ifdef NEVER + //T data_array[elementsRead]; + + std::vector<T> data_vector; + data_vector.reserve(elementsRead); + T* data_array = data_vector.data(); + ret = H5Dread(dataSetId, h5Type, memDataSpace, fileSpace, H5P_DEFAULT, + data_array); +#else + ret = H5Dread(dataSetId, h5Type, memDataSpace, fileSpace, H5P_DEFAULT, +values); #endif + + + H5Sclose(memDataSpace); + + H5Sclose(fileSpace); + H5Dclose(dataSetId); } +*/ void HDF5ReaderP::EndStep() { m_H5File.Advance(); } void HDF5ReaderP::Close(const int transportIndex) { m_H5File.Close(); } +#define declare_type(T) \ + void HDF5ReaderP::DoGetSync(Variable<T> &variable, T *data) \ + { \ + GetSyncCommon(variable, data); \ + } \ + void HDF5ReaderP::DoGetDeferred(Variable<T> &variable, T *data) \ + { \ + GetDeferredCommon(variable, data); \ + } \ + void HDF5ReaderP::DoGetDeferred(Variable<T> &variable, T &data) \ + { \ + GetDeferredCommon(variable, &data); \ + } +ADIOS2_FOREACH_TYPE_1ARG(declare_type) +#undef declare_type + } // end namespace adios diff --git a/source/adios2/engine/hdf5/HDF5ReaderP.h b/source/adios2/engine/hdf5/HDF5ReaderP.h index 786dbbfb39e426aa01493fd5ab9497980842b86e..695e632c2186eeba87973ecff760d049820d0fdc 100644 --- a/source/adios2/engine/hdf5/HDF5ReaderP.h +++ b/source/adios2/engine/hdf5/HDF5ReaderP.h @@ -29,7 +29,7 @@ public: * @param mpiComm * @param method */ - HDF5ReaderP(IO &adios, const std::string &name, const Mode mode, + HDF5ReaderP(IO &adios, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~HDF5ReaderP(); @@ -40,12 +40,28 @@ public: void Close(const int transportIndex = -1) final; - template <class T> - void UseHDFRead(const std::string &variableName, T *values, hid_t h5Type); - private: interop::HDF5Common m_H5File; void Init() final; + + bool m_InStreamMode = false; // default is not streaming +#define declare_type(T) \ + void DoGetSync(Variable<T> &, T *) final; \ + void DoGetDeferred(Variable<T> &, T *) final; \ + void DoGetDeferred(Variable<T> &, T &) final; + ADIOS2_FOREACH_TYPE_1ARG(declare_type) +#undef declare_type + + template <class T> + void GetSyncCommon(Variable<T> &variable, T *data); + + template <class T> + void GetDeferredCommon(Variable<T> &variable, T *data); + + template <class T> + // void UseHDFRead(const std::string &variableName, T *values, hid_t + // h5Type); + void UseHDFRead(Variable<T> &variable, T *values, hid_t h5Type); }; }; #endif /* ADIOS2_ENGINE_HDF5_HDF5READERP_H_ */ diff --git a/source/adios2/engine/hdf5/HDF5ReaderP.tcc b/source/adios2/engine/hdf5/HDF5ReaderP.tcc new file mode 100644 index 0000000000000000000000000000000000000000..20eeb3c6baea434fec30c43b45d9362731df7a5d --- /dev/null +++ b/source/adios2/engine/hdf5/HDF5ReaderP.tcc @@ -0,0 +1,44 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * HDF5ReaderP.tcc + * + * Created on: Oct 30, 2017 + * Author: jgu@lbl.gov + */ + +#ifndef ADIOS2_ENGINE_HDF5_HDF5FILEREADER_TCC_ +#define ADIOS2_ENGINE_HDF5_HDF5FILEREADER_TCC_ + +#include "HDF5ReaderP.h" + +namespace adios2 +{ + +template <class T> +void HDF5ReaderP::GetSyncCommon(Variable<T> &variable, T *data) +{ + // subfile info + /* no good way to check it is not reference to null + if (&variable == nullptr) { + return; + } + */ + hid_t h5Type = m_H5File.GetHDF5Type<T>(); + // UseHDFRead(variable.m_Name, data, h5Type); + UseHDFRead(variable, data, h5Type); +} + +template <class T> +void HDF5ReaderP::GetDeferredCommon(Variable<T> &variable, T *data) +{ + // returns immediately + // m_HDF53Deserializer.GetDeferredVariable(variable, data); + + throw std::runtime_error("Todo: GetDefCommon"); +} + +} // end namespace adios2 + +#endif /* ADIOS2_ENGINE_HDF5_HDF5FILEREADER_TCC_ */ diff --git a/source/adios2/engine/mixer/HDFMixer.cpp b/source/adios2/engine/mixer/HDFMixer.cpp index 8c86fdc7e77eac108d55578407b3a58e5935b98d..bfd1d59cb83b1b8a608cad3444b5fe31075e5624 100644 --- a/source/adios2/engine/mixer/HDFMixer.cpp +++ b/source/adios2/engine/mixer/HDFMixer.cpp @@ -14,12 +14,12 @@ #include "adios2/ADIOSMPI.h" #include "adios2/core/IO.h" #include "adios2/helper/adiosFunctions.h" //CheckIndexRange -#include "adios2/toolkit/transport/file/FileStream.h" +#include "adios2/toolkit/transport/file/FileFStream.h" namespace adios2 { -HDFMixer::HDFMixer(IO &io, const std::string &name, const Mode mode, +HDFMixer::HDFMixer(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm) : Engine("HDFMixer", io, name, openMode, mpiComm), m_HDFVDSWriter(mpiComm, m_DebugMode), @@ -40,14 +40,21 @@ void HDFMixer::Init() } #define declare_type(T) \ - void HDFMixer::DoWrite(Variable<T> &variable, const T *values) \ + void HDFMixer::DoPutSync(Variable<T> &variable, const T *values) \ { \ - DoWriteCommon(variable, values); \ + DoPutSyncCommon(variable, values); \ } ADIOS2_FOREACH_TYPE_1ARG(declare_type) #undef declare_type -void HDFMixer::Advance(const float /*timeout_sec*/) +StepStatus HDFMixer::BeginStep(StepMode mode, const float timeout_sec) +{ + return StepStatus::OK; +} + +// void HDFMixer::Advance(const float /*timeout_sec*/) +// void HDFMixer::EndStep(const float /*timeout_sec*/) +void HDFMixer::EndStep() { m_HDFSerialWriter.Advance(); m_HDFVDSWriter.Advance(); @@ -55,18 +62,18 @@ void HDFMixer::Advance(const float /*timeout_sec*/) void HDFMixer::Close(const int transportIndex) { - if (m_DebugMode) - { - if (!m_TransportsManager.CheckTransportIndex(transportIndex)) - { - auto transportsSize = m_TransportsManager.m_Transports.size(); - throw std::invalid_argument( - "ERROR: transport index " + std::to_string(transportIndex) + - " outside range, -1 (default) to " + - std::to_string(transportsSize - 1) + ", in call to Close\n"); - } - } - + /*if (m_DebugMode) + { + if (!m_TransportsManager.CheckTransportIndex(transportIndex)) + { + auto transportsSize = m_TransportsManager.m_Transports.size(); + throw std::invalid_argument( + "ERROR: transport index " + std::to_string(transportIndex) + + " outside range, -1 (default) to " + + std::to_string(transportsSize - 1) + ", in call to Close\n"); + } + } + */ // close bp buffer by flattening data and metadata m_HDFSerialWriter.Close(); m_HDFVDSWriter.Close(); diff --git a/source/adios2/engine/mixer/HDFMixer.h b/source/adios2/engine/mixer/HDFMixer.h index e4616f6fc298b31b89218e9290267cba03d98ab5..64a8947d7d84f5a1220e9511a8830330513ffdcc 100644 --- a/source/adios2/engine/mixer/HDFMixer.h +++ b/source/adios2/engine/mixer/HDFMixer.h @@ -27,7 +27,7 @@ #include "adios2/ADIOSTypes.h" #include "adios2/core/Variable.h" #include "adios2/helper/adiosFunctions.h" -#include "adios2/toolkit/capsule/heap/STLVector.h" +//#include "adios2/toolkit/capsule/heap/STLVector.h" #include "adios2/toolkit/transportman/TransportMan.h" //transport::TransportsMan #include <iostream> @@ -45,13 +45,15 @@ public: * @param openMode w (supported), r, a from OpenMode in ADIOSTypes.h * @param mpiComm MPI communicator */ - HDFMixer(IO &io, const std::string &name, const Mode mode, + HDFMixer(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~HDFMixer(); - void Advance(const float timeoutSeconds = 0.f) final; - + // void Advance(const float timeoutSeconds = 0.0) final; + StepStatus BeginStep(StepMode mode, const float timeout_sec); + // void EndStep(const float /*timeout_sec*/); + void EndStep() final; /** * Closes a single transport or all transports * @param transportIndex, if -1 (default) closes all transports, otherwise @@ -87,7 +89,7 @@ private: void InitBuffer(); #define declare_type(T) \ - void DoWrite(Variable<T> &variable, const T *values) final; + void DoPutSync(Variable<T> &variable, const T *values) /*final */; ADIOS2_FOREACH_TYPE_1ARG(declare_type) #undef declare_type @@ -97,13 +99,13 @@ private: * @param values */ template <class T> - void DoWriteCommon(Variable<T> &variable, const T *values); + void DoPutSyncCommon(Variable<T> &variable, const T *values); /** Write a profiling.json file from m_H51Writer and m_TransportsManager * profilers*/ void WriteProfilingJSONFile(); }; -} // end namespace adios2 +} // end namespace adios #endif /* ADIOS2_ENGINE_H5_HDFMIXER_H_ */ diff --git a/source/adios2/engine/mixer/HDFMixer.tcc b/source/adios2/engine/mixer/HDFMixer.tcc index d3d92bcac52cc202c3643a17cbe70194d3a1fadc..0618e9d46cbaa1abd031540001c26bb58e3b8e5f 100644 --- a/source/adios2/engine/mixer/HDFMixer.tcc +++ b/source/adios2/engine/mixer/HDFMixer.tcc @@ -14,12 +14,13 @@ namespace adios2 { template <class T> -void HDFMixer::DoWriteCommon(Variable<T> &variable, const T *values) +void HDFMixer::DoPutSyncCommon(Variable<T> &variable, const T *values) { - variable.m_AppValues = values; - m_WrittenVariables.insert(variable.m_Name); + //set values + variable.SetData(values); + //m_WrittenVariables.insert(variable.m_Name); Variable<T> local(variable.m_Name, {}, {}, variable.m_Count, - variable.m_Count.size(), false); + variable.m_Count.size(), NULL, false); // m_HDFSerialWriter.m_H5File.Write(variable, values); // writes only the m_Count() part @@ -43,4 +44,4 @@ void HDFMixer::DoWriteCommon(Variable<T> &variable, const T *values) } } -} // end namespace adios2 +} // end namespace adios diff --git a/source/adios2/toolkit/interop/hdf5/HDF5Common.cpp b/source/adios2/toolkit/interop/hdf5/HDF5Common.cpp index 53222bbc26a3a512d6ac9dafce304b3cb802b8a1..09d80d810f660f4d580f51d80fb57011ade3062e 100644 --- a/source/adios2/toolkit/interop/hdf5/HDF5Common.cpp +++ b/source/adios2/toolkit/interop/hdf5/HDF5Common.cpp @@ -131,7 +131,7 @@ unsigned int HDF5Common::GetNumTimeSteps() { if (m_WriteMode) { - return 0; + return -1; } if (m_FileId < 0) @@ -154,6 +154,167 @@ unsigned int HDF5Common::GetNumTimeSteps() return m_NumTimeSteps; } +// read from all time steps +void HDF5Common::ReadAllVariables(IO &io) +{ + int i = 0; + std::string timestepStr; + hsize_t numObj; + for (i = 0; i < m_NumTimeSteps; i++) + { + ReadVariables(i, io); + } +} + +// read variables from the input timestep +void HDF5Common::ReadVariables(unsigned int ts, IO &io) +{ + int i = 0; + std::string timestepStr; + hsize_t numObj; + + StaticGetTimeStepString(timestepStr, ts); + hid_t gid = H5Gopen2(m_FileId, timestepStr.c_str(), H5P_DEFAULT); + HDF5TypeGuard g(gid, E_H5_GROUP); + /// if (gid > 0) { + herr_t ret = H5Gget_num_objs(gid, &numObj); + if (ret >= 0) + { + int k = 0; + char name[50]; + for (k = 0; k < numObj; k++) + { + ret = H5Gget_objname_by_idx(gid, (hsize_t)k, name, sizeof(name)); + if (ret >= 0) + { + hid_t datasetId = H5Dopen(gid, name, H5P_DEFAULT); + + HDF5TypeGuard d(datasetId, E_H5_DATASET); + CreateVar(io, datasetId, name); + } + } + } + /// H5Gclose(gid); + ///} +} + +template <class T> +void HDF5Common::AddVar(IO &io, std::string const &name, hid_t datasetId) +{ + Variable<T> *v = io.InquireVariable<T>(name); + if (NULL == v) + { + hid_t dspace = H5Dget_space(datasetId); + const int ndims = H5Sget_simple_extent_ndims(dspace); + hsize_t dims[ndims]; + H5Sget_simple_extent_dims(dspace, dims, NULL); + H5Sclose(dspace); + + Dims shape; + shape.resize(ndims); + if (ndims > 0) + { + // std::cout<<" ==> variable "<<name<<" is "<<ndims<<"D, + // "<<dims[0]<<", "<<dims[1]<<std::endl; + for (int i = 0; i < ndims; i++) + shape[i] = dims[i]; + } + + auto &foo = io.DefineVariable<T>(name, shape); + // default was set to 0 while m_AvailabelStepsStart is 1. + // correcting + if (0 == foo.m_AvailableStepsCount) + { + foo.m_AvailableStepsCount++; + } + } + else + { + /* if (0 == v->m_AvailableStepsCount) { // default was set to 0 while + m_AvailabelStepsStart is 1. v->m_AvailableStepsCount ++; + } + */ + v->m_AvailableStepsCount++; + } +} + +void HDF5Common::CreateVar(IO &io, hid_t datasetId, std::string const &name) +{ + hid_t h5Type = H5Dget_type(datasetId); + HDF5TypeGuard t(h5Type, E_H5_DATATYPE); + + if (H5Tequal(H5T_NATIVE_CHAR, h5Type)) + { + AddVar<char>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_SCHAR, h5Type)) + { + AddVar<signed char>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_UCHAR, h5Type)) + { + AddVar<unsigned char>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_SHORT, h5Type)) + { + AddVar<short>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_USHORT, h5Type)) + { + AddVar<unsigned short>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_INT, h5Type)) + { + AddVar<int>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_UINT, h5Type)) + { + AddVar<unsigned int>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_LONG, h5Type)) + { + AddVar<long>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_ULONG, h5Type)) + { + AddVar<unsigned long>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_LLONG, h5Type)) + { + AddVar<long long>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_ULLONG, h5Type)) + { + AddVar<unsigned long long>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_FLOAT, h5Type)) + { + AddVar<float>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_DOUBLE, h5Type)) + { + AddVar<double>(io, name, datasetId); + } + else if (H5Tequal(H5T_NATIVE_LDOUBLE, h5Type)) + { + AddVar<long double>(io, name, datasetId); + } + else if (H5Tequal(m_DefH5TypeComplexFloat, h5Type)) + { + AddVar<std::complex<float>>(io, name, datasetId); + } + else if (H5Tequal(m_DefH5TypeComplexDouble, h5Type)) + { + AddVar<std::complex<double>>(io, name, datasetId); + } + else if (H5Tequal(m_DefH5TypeComplexLongDouble, h5Type)) + { + AddVar<std::complex<long double>>(io, name, datasetId); + } + + // H5Tclose(h5Type); +} + void HDF5Common::Close() { if (m_FileId < 0) @@ -173,6 +334,39 @@ void HDF5Common::Close() m_GroupId = -1; } +void HDF5Common::SetTimeStep(int timeStep) +{ + if (m_WriteMode) + throw std::ios_base::failure( + "ERROR: unable to change timestep at Write MODE."); + + if (timeStep < 0) + throw std::ios_base::failure( + "ERROR: unable to change to negative timestep."); + + GetNumTimeSteps(); + + if (timeStep >= m_NumTimeSteps) + throw std::ios_base::failure( + "ERROR: given time step is more than actual known steps."); + + if (m_CurrentTimeStep == timeStep) + { + return; + } + + std::string timeStepName; + StaticGetTimeStepString(timeStepName, timeStep); + m_GroupId = H5Gopen(m_FileId, timeStepName.c_str(), H5P_DEFAULT); + if (m_GroupId < 0) + { + throw std::ios_base::failure("ERROR: unable to open HDF5 group " + + timeStepName + ", in call to Open\n"); + } + + m_CurrentTimeStep = timeStep; +} + void HDF5Common::Advance() { if (m_GroupId >= 0) diff --git a/source/adios2/toolkit/interop/hdf5/HDF5Common.h b/source/adios2/toolkit/interop/hdf5/HDF5Common.h index 56029726aa57cf018423452aa0d2b3d579ea1d40..212b089fbf625181f127a9afd2c40accd94a58d8 100644 --- a/source/adios2/toolkit/interop/hdf5/HDF5Common.h +++ b/source/adios2/toolkit/interop/hdf5/HDF5Common.h @@ -18,6 +18,7 @@ #include "adios2/ADIOSMPICommOnly.h" #include "adios2/ADIOSMacros.h" #include "adios2/ADIOSTypes.h" +#include "adios2/core/IO.h" // for CreateVar #include "adios2/core/Variable.h" #include <stdexcept> // for Intel Compiler @@ -27,6 +28,55 @@ namespace adios2 namespace interop { +typedef enum { + E_H5_DATASET = 0, + E_H5_DATATYPE = 1, + E_H5_GROUP = 2, + E_H5_SPACE = 3, +} ADIOS_ENUM_H5; + +class HDF5TypeGuard +{ +public: + HDF5TypeGuard(hid_t key, ADIOS_ENUM_H5 type) + { + m_Key = key; + m_Type = type; + if (key < 0) + { + throw std::ios_base::failure("ERROR: HDF5 failure detected."); + } + } + + ~HDF5TypeGuard() + { + if (m_Type == E_H5_DATASET) + { + H5Dclose(m_Key); + } + else if (m_Type == E_H5_GROUP) + { + H5Gclose(m_Key); + } + else if (m_Type == E_H5_SPACE) + { + H5Sclose(m_Key); + } + else if (m_Type == E_H5_DATATYPE) + { + H5Tclose(m_Key); + } + else + { + printf(" UNABLE to close \n"); + } + } + +private: + ADIOS_ENUM_H5 m_Type; + hid_t m_Key; +}; + class HDF5Common { @@ -45,9 +95,18 @@ public: void Close(); void Advance(); + void SetTimeStep(int ts); + unsigned int GetNumTimeSteps(); void WriteTimeSteps(); + void ReadVariables(unsigned int ts, IO &io); + void ReadAllVariables(IO &io); + void CreateVar(IO &io, hid_t h5Type, std::string const &name); + + template <class T> + void AddVar(IO &io, std::string const &name, hid_t datasetId); + static void StaticGetTimeStepString(std::string &timeStepName, int ts); hid_t m_PropertyListId = -1; @@ -65,6 +124,9 @@ public: template <class T> hid_t GetHDF5Type(); // should this be public? + template <class T> + T GetADIOSType(hid_t); + private: const bool m_DebugMode; bool m_WriteMode = false;