diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt index 43b9e6a4bc0f6d23aef3571dc119cb7a67579a1e..2850407da804fce34afa2c23bdfce603865e4795 100644 --- a/examples/hello/CMakeLists.txt +++ b/examples/hello/CMakeLists.txt @@ -19,3 +19,12 @@ endif() if(ADIOS2_HAVE_HDF5) add_subdirectory(hdf5Writer) endif() + +if(ADIOS2_HAVE_BZip2) + add_subdirectory(bpBZip2Wrapper) +endif() + +if(ADIOS2_HAVE_ZFP) + add_subdirectory(bpZfpWrapper) +endif() + diff --git a/examples/hello/bpBZip2Wrapper/CMakeLists.txt b/examples/hello/bpBZip2Wrapper/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3803a998a7103673cdee602633c71a03a049da24 --- /dev/null +++ b/examples/hello/bpBZip2Wrapper/CMakeLists.txt @@ -0,0 +1,18 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +if(ADIOS2_HAVE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + + add_executable(hello_bpBZip2Wrapper helloBPBZip2Wrapper.cpp) + target_include_directories(hello_bpBZip2Wrapper PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(hello_bpBZip2Wrapper ${MPI_C_LIBRARIES}) + +else() + add_executable(hello_bpBZip2Wrapper helloBPBZip2Wrapper_nompi.cpp) + +endif() + +target_link_libraries(hello_bpBZip2Wrapper adios2) diff --git a/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper.cpp b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb425051ccd39c7bfdbb56f1925f1d014476be42 --- /dev/null +++ b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper.cpp @@ -0,0 +1,120 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPBZip2Wrapper.cpp: Simple self-descriptive example of how to write a + * variable to a BP File that lives in several MPI processes and is compressed + * with BZip2 http://www.bzip.org/ + * + * Created on: Jul 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ +#include <mpi.h> + +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <numeric> //std::iota +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable uints from 0 to 1000 */ + std::vector<unsigned int> myUInts(1000); + std::iota(myUInts.begin(), myUInts.end(), 0.f); + const std::size_t Nx = myUInts.size(); + const std::size_t inputBytes = Nx * sizeof(unsigned int); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + // Get a Transform of type BZip2 + adios2::Transform &adiosBZip2 = adios.GetTransform("bzip2"); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_BZip2"); + + /** global array : name, { shape (total) }, { start (local) }, { count + * (local) }, all are constant dimensions */ + adios2::Variable<unsigned int> &bpUInts = + bpIO.DefineVariable<unsigned int>("bpUInts", {size * Nx}, + {rank * Nx}, {Nx}, + adios2::ConstantDims); + + // 1st way: adding transform metadata to variable to Engine can decide: + // &adiosBZip2 gets mapped to bpUInts.TransformInfo[bzip2ID].Operator + const unsigned int bzip2ID = + bpUInts.AddTransform(adiosBZip2, {{"BlockSize100K", "9"}}); + + // 2nd way: treat Transforms as wrappers to underlying library. + // you can redefine parameters + const std::size_t estimatedSize = + adiosBZip2.BufferMaxSize(Nx * bpUInts.m_ElementSize); + std::vector<char> compressedBuffer(estimatedSize); + size_t compressedSize = adiosBZip2.Compress( + myUInts.data(), bpUInts.m_Count, bpUInts.m_ElementSize, + bpUInts.m_Type, compressedBuffer.data(), {{"BlockSize100K", "1"}}); + + compressedBuffer.resize(compressedSize); + + std::cout << "Rank " << rank << "\n"; + std::cout << "Compression summary:\n"; + std::cout << "Input data size: " << inputBytes << " bytes\n"; + std::cout << "BZip2 estimated output size: " << estimatedSize + << " bytes\n"; + std::cout << "BZip2 final output size: " << compressedSize + << " bytes\n\n"; + + // Allocate original data size + std::vector<unsigned int> decompressedBuffer(Nx); + size_t decompressedSize = adiosBZip2.Decompress( + compressedBuffer.data(), compressedSize, decompressedBuffer.data(), + decompressedBuffer.size() * sizeof(unsigned int)); + + std::cout << "Decompression summary:\n"; + std::cout << "Decompressed size: " << decompressedSize << " bytes\n"; + std::cout << "Data:\n"; + + for (const auto number : decompressedBuffer) + { + if (number % 25 == 0) + { + std::cout << "\n"; + } + std::cout << number << " "; + } + std::cout << "\n"; + } + 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/hello/bpBZip2Wrapper/helloBPBZip2Wrapper_nompi.cpp b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper_nompi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe7e2b7b027a031f5b63c3d61f94b2788763c6d9 --- /dev/null +++ b/examples/hello/bpBZip2Wrapper/helloBPBZip2Wrapper_nompi.cpp @@ -0,0 +1,103 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPBZip2Writer_nompi.cpp sequential non-mpi version of helloBPBZip2Writer + * using BZip2 http://www.bzip.org/ + * + * Created on: Jul 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <numeric> //std::iota +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + /** Application variable uints from 0 to 1000 */ + std::vector<unsigned int> myUInts(1000); + std::iota(myUInts.begin(), myUInts.end(), 0.f); + const std::size_t Nx = myUInts.size(); + const std::size_t inputBytes = Nx * sizeof(unsigned int); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(adios2::DebugON); + + // Get a Transform of type BZip2 + adios2::Transform &adiosBZip2 = adios.GetTransform("bzip2"); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_BZip2"); + + /** global array : name, { shape (total) }, { start (local) }, { count + * (local) }, all are constant dimensions */ + adios2::Variable<unsigned int> &bpUInts = + bpIO.DefineVariable<unsigned int>("bpUInts", {}, {}, {Nx}, + adios2::ConstantDims); + + // 1st way: adding transform metadata to variable to Engine can decide: + bpUInts.AddTransform(adiosBZip2, {{"BlockSize100K", "10"}}); + + // 2nd way: treat Transforms as wrappers to underlying library: + const std::size_t estimatedSize = + adiosBZip2.BufferMaxSize(Nx * bpUInts.m_ElementSize); + std::vector<char> compressedBuffer(estimatedSize); + size_t compressedSize = adiosBZip2.Compress( + myUInts.data(), bpUInts.m_Count, bpUInts.m_ElementSize, + bpUInts.m_Type, compressedBuffer.data(), {{"BlockSize100K", "9"}}); + + compressedBuffer.resize(compressedSize); + + std::cout << "Compression summary:\n"; + std::cout << "Input data size: " << inputBytes << " bytes\n"; + std::cout << "BZip2 estimated output size: " << estimatedSize + << " bytes\n"; + std::cout << "BZip2 final output size: " << compressedSize + << " bytes\n\n"; + + // Allocate original data size + std::vector<unsigned int> decompressedBuffer(Nx); + size_t decompressedSize = adiosBZip2.Decompress( + compressedBuffer.data(), compressedSize, decompressedBuffer.data(), + decompressedBuffer.size() * sizeof(unsigned int)); + + std::cout << "Decompression summary:\n"; + std::cout << "Decompressed size: " << decompressedSize << " bytes\n"; + std::cout << "Data:\n"; + + for (const auto number : decompressedBuffer) + { + if (number % 25 == 0) + { + std::cout << "\n"; + } + std::cout << number << " "; + } + std::cout << "\n"; + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + + return 0; +} diff --git a/examples/hello/bpZfpWrapper/CMakeLists.txt b/examples/hello/bpZfpWrapper/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c5cb52b74f20dc3bdced1ea0e63a5a5373a33329 --- /dev/null +++ b/examples/hello/bpZfpWrapper/CMakeLists.txt @@ -0,0 +1,18 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +if(ADIOS2_HAVE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + + add_executable(hello_bpZfpWrapper helloBPZfpWrapper.cpp) + target_include_directories(hello_bpZfpWrapper PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(hello_bpZfpWrapper ${MPI_C_LIBRARIES}) + +else() + add_executable(hello_bpZfpWrapper helloBPZfpWrapper_nompi.cpp) + +endif() + +target_link_libraries(hello_bpZfpWrapper adios2) diff --git a/examples/hello/bpZfpWrapper/helloBPZfpWrapper.cpp b/examples/hello/bpZfpWrapper/helloBPZfpWrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9227e20c7c266d94f61e64eb71bbac290e48476 --- /dev/null +++ b/examples/hello/bpZfpWrapper/helloBPZfpWrapper.cpp @@ -0,0 +1,122 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPZfpWrapper.cpp: Simple self-descriptive example of how to write a + * variable to a BP File that lives in several MPI processes and is compressed + * with Zfp https://computation.llnl.gov/projects/floating-point-compression + * + * Created on: Jul 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ +#include <mpi.h> + +#include <cstdint> //std::int32_t +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <numeric> //std::iota +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable uints from 0 to 100 */ + std::vector<float> myFloats(100); + std::iota(myFloats.begin(), myFloats.end(), 0.f); + const std::size_t Nx = myFloats.size(); + const std::size_t inputBytes = Nx * sizeof(float); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + // Get a Transform of type BZip2 + adios2::Transform &adiosZfp = adios.GetTransform("zfp"); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_Zfp"); + + /** global array : name, { shape (total) }, { start (local) }, { count + * (local) }, all are constant dimensions */ + adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + // 1st way: adding transform metadata to variable to Engine can decide: + const unsigned int zfpID = + bpFloats.AddTransform(adiosZfp, {{"Rate", "8"}}); + + // 2nd way: treat Transforms as wrappers to underlying library: + const std::size_t estimatedSize = + adiosZfp.BufferMaxSize(myFloats.data(), bpFloats.m_Count, + bpFloats.m_TransformsInfo[zfpID].Parameters); + + // Compress + std::vector<char> compressedBuffer(estimatedSize); + + size_t compressedSize = adiosZfp.Compress( + myFloats.data(), bpFloats.m_Count, bpFloats.m_ElementSize, + bpFloats.m_Type, compressedBuffer.data(), + bpFloats.m_TransformsInfo[zfpID].Parameters); + + compressedBuffer.resize(compressedSize); + + std::cout << "Compression summary:\n"; + std::cout << "Input data size: " << inputBytes << " bytes\n"; + std::cout << "Zfp estimated output size: " << estimatedSize + << " bytes\n"; + std::cout << "Zfp final output size: " << compressedSize + << " bytes\n\n"; + + // Allocate original data size + std::vector<float> decompressedBuffer(Nx); + size_t decompressedSize = adiosZfp.Decompress( + compressedBuffer.data(), compressedBuffer.size(), + decompressedBuffer.data(), bpFloats.m_Count, bpFloats.m_Type, + bpFloats.m_TransformsInfo[zfpID].Parameters); + + std::cout << "Decompression summary:\n"; + std::cout << "Decompressed size: " << decompressedSize << " bytes\n "; + std::cout << "Data:\n"; + + for (const auto number : decompressedBuffer) + { + if (static_cast<int>(number) % 25 == 0 && number != 0) + { + std::cout << "\n"; + } + std::cout << number << " "; + } + std::cout << "\n"; + } + 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/hello/bpZfpWrapper/helloBPZfpWrapper_nompi.cpp b/examples/hello/bpZfpWrapper/helloBPZfpWrapper_nompi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e84feee7b8c75401da3ee360ac22b29a291ce70f --- /dev/null +++ b/examples/hello/bpZfpWrapper/helloBPZfpWrapper_nompi.cpp @@ -0,0 +1,114 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPZfpWriter_nompi.cpp sequential non-mpi version of helloBPZfpWrapper + * using Zfp https://computation.llnl.gov/projects/floating-point-compression + * + * Created on: Jul 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <cstdint> //std::int32_t +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <numeric> //std::iota +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + /** Application variable uints from 0 to 100 */ + std::vector<float> myFloats(100); + std::iota(myFloats.begin(), myFloats.end(), 0.f); + const std::size_t Nx = myFloats.size(); + const std::size_t inputBytes = Nx * sizeof(float); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(adios2::DebugON); + + // Get a Transform of type BZip2 + adios2::Transform &adiosZfp = adios.GetTransform("zfp"); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPVariable_Zfp"); + + /** global array : name, { shape (total) }, { start (local) }, { count + * (local) }, all are constant dimensions */ + adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>( + "bpUInts", {}, {}, {Nx}, adios2::ConstantDims); + + // Adding transform metadata to variable: + // Options: + // Rate double + // Tolerance + // Precision + const unsigned int zfpID = + bpFloats.AddTransform(adiosZfp, {{"Rate", "8"}}); + + // Treat Transforms as wrappers to underlying library (zfp): + const std::size_t estimatedSize = + adiosZfp.BufferMaxSize(myFloats.data(), bpFloats.m_Count, + bpFloats.m_TransformsInfo[zfpID].Parameters); + + // Compress + std::vector<char> compressedBuffer(estimatedSize); + + size_t compressedSize = adiosZfp.Compress( + myFloats.data(), bpFloats.m_Count, bpFloats.m_ElementSize, + bpFloats.m_Type, compressedBuffer.data(), + bpFloats.m_TransformsInfo[zfpID].Parameters); + + compressedBuffer.resize(compressedSize); + + std::cout << "Compression summary:\n"; + std::cout << "Input data size: " << inputBytes << " bytes\n"; + std::cout << "Zfp estimated output size: " << estimatedSize + << " bytes\n"; + std::cout << "Zfp final output size: " << compressedSize + << " bytes\n\n"; + + // Decompress, allocate original data size + std::vector<float> decompressedBuffer(Nx); + size_t decompressedSize = adiosZfp.Decompress( + compressedBuffer.data(), compressedBuffer.size(), + decompressedBuffer.data(), bpFloats.m_Count, bpFloats.m_Type, + bpFloats.m_TransformsInfo[zfpID].Parameters); + + std::cout << "Decompression summary:\n"; + std::cout << "Decompressed size: " << decompressedSize << " bytes\n "; + std::cout << "Data:\n"; + + for (const auto number : decompressedBuffer) + { + if (static_cast<int>(number) % 25 == 0 && number != 0) + { + std::cout << "\n"; + } + std::cout << number << " "; + } + std::cout << "\n"; + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + + return 0; +} diff --git a/source/adios2/ADIOSConfig.h.in b/source/adios2/ADIOSConfig.h.in index c917b81a8b1a06b2b43b4844cd1715e70ebff69e..2ed35a170040bebcd83e0466c29a9127e9e8fc97 100644 --- a/source/adios2/ADIOSConfig.h.in +++ b/source/adios2/ADIOSConfig.h.in @@ -27,10 +27,10 @@ /* CMake Option: ADIOS_USE_MPI=OFF */ #cmakedefine ADIOS2_HAVE_MPI -/* CMake Option: ADIOS_USE_ZFP=OFF */ +/* CMake Option: ADIOS_USE_ZFP=ON */ #cmakedefine ADIOS2_HAVE_ZFP -/* CMake Option: ADIOS_USE_BZip2=OFF */ +/* CMake Option: ADIOS_USE_BZip2=ON */ #cmakedefine ADIOS2_HAVE_BZIP2 /* CMake Option: ADIOS_USE_ADIOS1=ON */ diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h index 8f1471a4a7067ea274f5620ba439320856679df0..f3043732b588cbde469d3b5f9e06adcc85afa03b 100644 --- a/source/adios2/ADIOSMacros.h +++ b/source/adios2/ADIOSMacros.h @@ -56,4 +56,10 @@ MACRO(float) \ MACRO(double) +#define ADIOS2_FOREACH_ZFP_TYPE_1ARG(MACRO) \ + MACRO(int32_t) \ + MACRO(int64_t) \ + MACRO(float) \ + MACRO(double) + #endif /* ADIOS2_ADIOSMACROS_H */ diff --git a/source/adios2/CMakeLists.txt b/source/adios2/CMakeLists.txt index ce6a31efdf961afe5dce50bbb256c2d5f53ee7de..3bd8861811fcdb0cf4812ccd591e53c957331c4e 100644 --- a/source/adios2/CMakeLists.txt +++ b/source/adios2/CMakeLists.txt @@ -10,7 +10,7 @@ add_library(adios2 core/Selection.cpp core/SelectionBoundingBox.cpp core/SelectionPoints.cpp - core/Transform.cpp + core/Transform.cpp core/Transform.tcc core/Variable.cpp core/Variable.tcc core/VariableBase.cpp core/VariableCompound.cpp core/VariableCompound.tcc @@ -71,15 +71,14 @@ endif() if(ADIOS2_HAVE_BZip2) find_package(BZip2 REQUIRED) - target_sources(adios2 PRIVATE transform/compression/BZip2.cpp) + target_sources(adios2 PRIVATE transform/compress/CompressBZip2.cpp) target_link_libraries(adios2 PRIVATE BZip2::BZip2) endif() if(ADIOS2_HAVE_ZFP) find_package(ZFP REQUIRED) - message("ADIOS ZFP support not yet implemented") -# target_sources(adios2 PRIVATE transform/compression/ZFP.cpp) -# target_link_libraries(adios2 PRIVATE zfp::zfp) + target_sources(adios2 PRIVATE transform/compress/CompressZfp.cpp) + target_link_libraries(adios2 PRIVATE zfp::zfp) endif() if(ADIOS2_HAVE_MPI) diff --git a/source/adios2/core/ADIOS.cpp b/source/adios2/core/ADIOS.cpp index af7020254e84fd396c9e4c8be71c984deef9b8f0..d4853c603d064962abc543a8caa94dfc36a01643 100644 --- a/source/adios2/core/ADIOS.cpp +++ b/source/adios2/core/ADIOS.cpp @@ -21,6 +21,15 @@ #include "adios2/ADIOSMPI.h" #include "adios2/helper/adiosFunctions.h" +// transforms +#ifdef ADIOS2_HAVE_BZIP2 +#include "adios2/transform/compress/CompressBZip2.h" +#endif + +#ifdef ADIOS2_HAVE_ZFP +#include "adios2/transform/compress/CompressZfp.h" +#endif + namespace adios2 { @@ -86,11 +95,59 @@ IO &ADIOS::GetIO(const std::string name) { throw std::invalid_argument( "ERROR: Unable to find previously defined IO object with name \"" + - name + "\" in call to GetIO."); + name + "\", in call to GetIO."); } return itIO->second; } +Transform &ADIOS::GetTransform(const std::string transform) +{ + auto itTransform = m_Transforms.find(transform); + + if (itTransform != m_Transforms.end()) + { + return *itTransform->second.get(); + } + + if (transform == "bzip2" || transform == "BZip2") + { +#ifdef ADIOS2_HAVE_BZIP2 + auto itPair = m_Transforms.emplace( + "bzip2", + std::make_shared<adios2::transform::CompressBZip2>(m_DebugMode)); + return *itPair.first->second; +#else + throw std::invalid_argument( + "ERROR: this version of ADIOS2 didn't compile with " + "bzip2 library, in call to GetTransport\n"); +#endif + } + else if (transform == "zfp" || transform == "Zfp") + { +#ifdef ADIOS2_HAVE_ZFP + auto itPair = m_Transforms.emplace( + "zfp", + std::make_shared<adios2::transform::CompressZfp>(m_DebugMode)); + return *itPair.first->second; +#else + throw std::invalid_argument( + "ERROR: this version of ADIOS2 didn't compile with " + "zfp library, in call to GetTransport\n"); +#endif + } + else + { + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: transform " + transform + + " not supported by ADIOS2, in call to GetTransport\n"); + } + } + + return *itTransform->second.get(); +} + // PRIVATE FUNCTIONS void ADIOS::CheckMPI() const { diff --git a/source/adios2/core/ADIOS.h b/source/adios2/core/ADIOS.h index 618a33232bf29cc7d931dc36d3b0932166d85818..2a019274b0478c1608a108fe171706ab85919c63 100644 --- a/source/adios2/core/ADIOS.h +++ b/source/adios2/core/ADIOS.h @@ -96,6 +96,8 @@ public: */ IO &GetIO(const std::string name); + Transform &GetTransform(const std::string transform); + private: /** XML File to be read containing configuration information */ const std::string m_ConfigFile; @@ -104,7 +106,7 @@ private: const bool m_DebugMode = false; /** transforms associated with ADIOS run */ - std::vector<std::shared_ptr<Transform>> m_Transforms; + std::map<std::string, std::shared_ptr<Transform>> m_Transforms; /** * @brief List of IO class objects defined from either ADIOS diff --git a/source/adios2/core/Transform.cpp b/source/adios2/core/Transform.cpp index dc4079aed7aa725493c67f6eab8cda3c1f4617de..02973f2460c664fc9f214a9b6692728ed4c91229 100644 --- a/source/adios2/core/Transform.cpp +++ b/source/adios2/core/Transform.cpp @@ -9,20 +9,90 @@ */ #include "Transform.h" +#include "Transform.tcc" namespace adios2 { -Transform::Transform(const std::string method) : m_Method(method) {} +Transform::Transform(const std::string library, const bool debugMode) +: m_Library(library), m_DebugMode(debugMode) +{ +} + +size_t Transform::BufferMaxSize(const size_t sizeIn) const +{ + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: signature (const size_t) not supported " + "by derived class implemented with " + + m_Library + ", in call to BufferMaxSize\n"); + } + return 0; +} + +size_t Transform::Compress(const void * /*dataIn*/, const Dims & /*dimensions*/, + const size_t /*elementSize*/, + const std::string /*type*/, void * /*bufferOut*/, + const Params & /*params*/) const +{ + if (m_DebugMode) + { + throw std::invalid_argument("ERROR: signature (const void*, const " + "Dims, const size_t, const std::string, " + "void*, const Params&) not supported " + "by derived class implemented with " + + m_Library + ", in call to Compress\n"); + } + return 0; +} -void Transform::Compress(const std::vector<char> & /*bufferIn*/, - std::vector<char> & /*bufferOut*/) +size_t Transform::Decompress(const void *bufferIn, const size_t sizeIn, + void *dataOut, const size_t sizeOut) const { + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: signature (const void*, const size_t, void) not supported " + "by derived class implemented with " + + m_Library + ", in call to Decompress\n"); + } + + return 0; } -void Transform::Decompress(const std::vector<char> & /*bufferIn*/, - std::vector<char> & /*bufferOut*/) +size_t Transform::Decompress(const void * /*bufferIn*/, const size_t /*sizeIn*/, + void * /*dataOut*/, const Dims & /*dimensions*/, + const std::string /*type*/, + const Params & /*parameters*/) const { + if (m_DebugMode) + { + throw std::invalid_argument("ERROR: signature (const void*, const " + "size_t, void*, const Dims&, const " + "std::string ) not supported " + "by derived class implemented with " + + m_Library + ", in call to Decompress\n"); + } + + return 0; +} + +// PROTECTED +size_t Transform::DoBufferMaxSize(const void *dataIn, const Dims &dimensions, + const std::string type, + const Params ¶meters) const +{ + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: signature (const void*, const Dims& " + "std::string ) not supported " + "by derived class implemented with " + + m_Library + ", in call to BufferMaxSize\n"); + } + + return 0; } -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/core/Transform.h b/source/adios2/core/Transform.h index 32c857293ef9d7ee29ecb02abda652c81d9d261b..19d617432da299dfd62ac0e2f279946c1b8e31ff 100644 --- a/source/adios2/core/Transform.h +++ b/source/adios2/core/Transform.h @@ -16,33 +16,96 @@ #include <vector> /// \endcond -#include "adios2/ADIOSConfig.h" +#include "adios2/ADIOSTypes.h" namespace adios2 { -/** Base class that defines data variable transformations */ +/** Base class that defines data variable transformations implemented under + * adios2/transform */ class Transform { public: - /** From derived class to identify the transform */ - const std::string m_Method; + /** From derived class */ + const std::string m_Library; /** - * Initialize parent method - * @param method zlib, bzip2, szip + * Unique base class constructor + * @param method bzip2, zfp + * @param debugMode true: extra exceptions checks */ - Transform(const std::string method); + Transform(const std::string library, const bool debugMode); virtual ~Transform() = default; - virtual void Compress(const std::vector<char> &bufferIn, - std::vector<char> &bufferOut); + /** + * Returns a conservative buffer size to hold input data for classes + * @param sizeIn size of input data to be compressed in bytes + * @return recommended allocation for output buffer + */ + virtual size_t BufferMaxSize(const size_t sizeIn) const; + + /** + * Used by Zfp + * Returns a conservative buffer size to hold input data for classes + * @param dataIn + * @param dimensions + * @return recommended allocation for output buffer in bytes + */ + template <class T> + size_t BufferMaxSize(const T *dataIn, const Dims &dimensions, + const Params ¶ms) const; + + /** + * BZip2 and Zfp common call + * @param dataIn + * @param dimensions + * @param elementSize + * @param type + * @param bufferOut + * @param parameters + * @return size of compressed buffer + */ + virtual size_t Compress(const void *dataIn, const Dims &dimensions, + const size_t elementSize, const std::string type, + void *bufferOut, + const Params ¶meters = Params()) const; - virtual void Decompress(const std::vector<char> &bufferIn, - std::vector<char> &bufferOut); + virtual size_t Decompress(const void *bufferIn, const size_t sizeIn, + void *dataOut, const size_t sizeOut) const; + + /** + * Zfp signature + * @param bufferIn + * @param sizeIn + * @param dataOut + * @param dimensions + * @param type + * @return + */ + virtual size_t Decompress(const void *bufferIn, const size_t sizeIn, + void *dataOut, const Dims &dimensions, + const std::string type, + const Params ¶meters) const; + +protected: + /** true: extra exception checks, false: skip exception checks */ + const bool m_DebugMode = false; + + /** + * Used by CompressZfp + * Returns a conservative buffer size to hold input data for classes + * @param dataIn + * @param dimensions + * @param type + * @return conservative buffer size for allocation + */ + virtual size_t DoBufferMaxSize(const void *dataIn, const Dims &dimensions, + const std::string type, + const Params ¶meters) const; }; -} // end namespace adios +} // end namespace adios2 + #endif /* ADIOS2_CORE_TRANSFORM_H_ */ diff --git a/source/adios2/core/Transform.tcc b/source/adios2/core/Transform.tcc new file mode 100644 index 0000000000000000000000000000000000000000..3fac195fda0603970a939ab6f817c9c553c5079f --- /dev/null +++ b/source/adios2/core/Transform.tcc @@ -0,0 +1,35 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Transform.tcc : specialization of template functions + * + * Created on: Jul 25, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_CORE_TRANSFORM_TCC_ +#define ADIOS2_CORE_TRANSFORM_TCC_ + +#include "Transform.h" + +#include "adios2/ADIOSMacros.h" +#include "adios2/helper/adiosFunctions.h" + +namespace adios2 +{ + +#define declare_type(T) \ + template <> \ + size_t Transform::BufferMaxSize<T>( \ + const T *dataIn, const Dims &dimensions, const Params ¶meters) \ + const \ + { \ + return DoBufferMaxSize(dataIn, dimensions, GetType<T>(), parameters); \ + } +ADIOS2_FOREACH_ZFP_TYPE_1ARG(declare_type) +#undef declare_type + +} // end namespace adios2 + +#endif // ADIOS2_CORE_TRANSFORM_TCC_ diff --git a/source/adios2/core/VariableBase.cpp b/source/adios2/core/VariableBase.cpp index 3a13c739ad5ea212d8f00815c85d6170f01e95ed..07759db41f82a76badab8a28635159d417befadf 100644 --- a/source/adios2/core/VariableBase.cpp +++ b/source/adios2/core/VariableBase.cpp @@ -125,18 +125,31 @@ void VariableBase::SetStepSelection(const unsigned int startStep, m_ReadNSteps = countStep; } -void VariableBase::AddTransform( - Transform &transform, const std::vector<std::string> ¶metersVector) +// transforms related functions +unsigned int VariableBase::AddTransform(Transform &transform, + const Params ¶meters) noexcept { + m_TransformsInfo.push_back(TransformInfo{transform, parameters}); + return static_cast<unsigned int>(m_TransformsInfo.size() - 1); } -void VariableBase::AddTransform(Transform &transform, - const Params ¶metersVector) +void VariableBase::ResetTransformParameters(const unsigned int transformIndex, + const Params ¶meters) { + if (m_DebugMode) + { + if (transformIndex < m_TransformsInfo.size()) + { + m_TransformsInfo[transformIndex].Parameters = parameters; + } + } + else + { + m_TransformsInfo[transformIndex].Parameters = parameters; + } } -// transforms related functions -void VariableBase::ClearTransforms() { m_TransformsInfo.clear(); } +void VariableBase::ClearTransforms() noexcept { m_TransformsInfo.clear(); } // PRIVATE void VariableBase::InitShapeType() diff --git a/source/adios2/core/VariableBase.h b/source/adios2/core/VariableBase.h index 424a93892bd4142e1db38622909afc7c99a1f5c6..39c4367a00654c6cd9ceaecfb0388ffb2e49e4e2 100644 --- a/source/adios2/core/VariableBase.h +++ b/source/adios2/core/VariableBase.h @@ -105,44 +105,46 @@ public: void SetStepSelection(const unsigned int startStep, const unsigned int countStep); - void AddTransform(Transform &transform, - const std::vector<std::string> ¶metersVector); + /** + * Pushed a new transform to a sequence of transports + * @param transform reference to an object derived from the Transform class + * @param parameters transform specific parameters + * @return transformID handler + */ + unsigned int AddTransform(Transform &transform, + const Params ¶meters = Params()) noexcept; - void AddTransform(Transform &transform, - const Params ¶metersVector = Params()); - - /** Apply current sequence of transforms defined by AddTransform */ - virtual void ApplyTransforms() = 0; + void ResetTransformParameters(const unsigned int transformIndex, + const Params ¶meters = Params()); /** Clears out the transform sequence defined by AddTransform */ - void ClearTransforms(); + void ClearTransforms() noexcept; - /** Self-check dims according to type, called from Engine before Write - * @param hint extra debugging info for the exception */ - void CheckDims(const std::string hint) const; - -private: - const bool m_DebugMode = false; - - void InitShapeType(); + /** Apply current sequence of transforms defined by AddTransform */ + virtual void ApplyTransforms() = 0; /** Transforms metadata info */ struct TransformInfo { /** reference to object derived from Transform class */ - Transform &Object; + Transform &Operator; /** parameters from AddTransform */ Params Parameters; /** resulting sizes from transformation */ Dims Sizes; }; - /** - * Sequence determines application order, e.g. - * first Transforms[0] then Transforms[1]. Pointer used as - * reference (no memory management). - */ + /** Registered transforms */ std::vector<TransformInfo> m_TransformsInfo; + + /** Self-check dims according to type, called from Engine before Write + * @param hint extra debugging info for the exception */ + void CheckDims(const std::string hint) const; + +private: + const bool m_DebugMode = false; + + void InitShapeType(); }; } // end namespace diff --git a/source/adios2/helper/adiosString.cpp b/source/adios2/helper/adiosString.cpp index 7ef54bdde13deaf22b16f2ee9b4ba2570c1d07c7..1f0c85d0cad367ce2ae88c1c7be4e59653d4dee6 100644 --- a/source/adios2/helper/adiosString.cpp +++ b/source/adios2/helper/adiosString.cpp @@ -129,4 +129,83 @@ void SetParameterValue(const std::string key, const Params ¶meters, } } +void SetParameterValueInt(const std::string key, const Params ¶meters, + int &value, const bool debugMode, + const std::string hint) +{ + auto itKey = parameters.find(key); + + if (itKey == parameters.end()) + { + return; + } + + if (debugMode) + { + try + { + value = std::stoi(itKey->second); + } + catch (...) + { + std::throw_with_nested(std::invalid_argument( + "ERROR: could not cast " + itKey->second + + " to int from key parameter: " + itKey->first + ", " + hint)); + } + } + else + { + value = std::stoi(itKey->second); + } +} + +double StringToDouble(const std::string value, const bool debugMode, + const std::string hint) +{ + double valueDouble = -1.; + + if (debugMode) + { + try + { + valueDouble = std::stod(value); + } + catch (...) + { + std::throw_with_nested(std::invalid_argument( + "ERROR: could not cast " + value + " to double, " + hint)); + } + } + else + { + valueDouble = std::stod(value); + } + return valueDouble; +} + +unsigned int StringToUInt(const std::string value, const bool debugMode, + const std::string hint) +{ + unsigned int valueUInt = 0; + + if (debugMode) + { + try + { + valueUInt = static_cast<unsigned int>(std::stoul(value)); + } + catch (...) + { + std::throw_with_nested( + std::invalid_argument("ERROR: could not cast " + value + + " to unsigned int, " + hint)); + } + } + else + { + valueUInt = static_cast<unsigned int>(std::stoul(value)); + } + return valueUInt; +} + } // end namespace adios diff --git a/source/adios2/helper/adiosString.h b/source/adios2/helper/adiosString.h index c89c87e5bfaf0f0c2b6eb5f4af5bb02653703aff..5f795bc4e918b9dddff49245427ad621f44acee3 100644 --- a/source/adios2/helper/adiosString.h +++ b/source/adios2/helper/adiosString.h @@ -67,6 +67,40 @@ GetParametersValues(const std::string &key, */ void SetParameterValue(const std::string key, const Params ¶meters, std::string &value) noexcept; + +/** + * Sets int value if found in parameters for input key + * @param key input + * @param parameters map with key: field, value: value + * @param value to be modified if key is found in parameters + * @param debugMode check for string conversion + * @param hint passed for extra debugging info if exception is thrown + */ +void SetParameterValueInt(const std::string key, const Params ¶meters, + int &value, const bool debugMode, + const std::string hint); + +/** + * function that cast a string to a double verifying validity of the cast with + * exceptions in debugMode + * @param value string to be casted + * @param debugMode check for string conversion + * @param hint passed for extra debugging info if exception is thrown + * @return value as a double + */ +double StringToDouble(const std::string value, const bool debugMode, + const std::string hint); + +/** + * function that cast a string to unsigned int verifying validity of the cast + * with exceptions in debugMode + * @param value string to be casted + * @param debugMode check for string conversion + * @param hint passed for extra debugging info if exception is thrown + * @return value as unsigned int + */ +unsigned int StringToUInt(const std::string value, const bool debugMode, + const std::string hint); } #endif /* ADIOS2_HELPER_ADIOSSTRING_H_ */ diff --git a/source/adios2/helper/adiosXML.cpp b/source/adios2/helper/adiosXML.cpp index 65d1cdd4c9fd2577687275a2542fdb8c0b5af8f7..25bae1343c05e09b5776f9ca7af4ecf07f3ae6ae 100644 --- a/source/adios2/helper/adiosXML.cpp +++ b/source/adios2/helper/adiosXML.cpp @@ -62,9 +62,9 @@ Params InitParametersXML(const pugi::xml_node &node, const bool debugMode) return params; } -void InitIOXML(const pugi::xml_node &ioNode, const MPI_Comm mpiComm, +void InitIOXML(const pugi::xml_node &ioNode, MPI_Comm mpiComm, const bool debugMode, - std::vector<std::shared_ptr<Transform>> &transforms, + std::map<std::string, std::shared_ptr<Transform>> &transforms, std::map<std::string, IO> &ios) { // Extract <io name=""> attribute @@ -147,9 +147,9 @@ void InitIOXML(const pugi::xml_node &ioNode, const MPI_Comm mpiComm, } } -void InitXML(const std::string configXML, const MPI_Comm mpiComm, +void InitXML(const std::string configXML, MPI_Comm mpiComm, const bool debugMode, - std::vector<std::shared_ptr<Transform>> &transforms, + std::map<std::string, std::shared_ptr<Transform>> &transforms, std::map<std::string, IO> &ios) { int mpiRank; diff --git a/source/adios2/helper/adiosXML.h b/source/adios2/helper/adiosXML.h index 055c14605f43259a71783c4727c015ea4a34d476..0746eb47708041c3b19aef93a1aa3ee3c11b98fd 100644 --- a/source/adios2/helper/adiosXML.h +++ b/source/adios2/helper/adiosXML.h @@ -16,7 +16,6 @@ #include <memory> //std::shared_ptr #include <string> #include <utility> //std::pair -#include <vector> /// \endcond #include "adios2/core/IO.h" @@ -34,9 +33,9 @@ namespace adios2 * @param transforms * @param ios */ -void InitXML(const std::string configXML, const MPI_Comm mpiComm, +void InitXML(const std::string configXML, MPI_Comm mpiComm, const bool debugMode, - std::vector<std::shared_ptr<Transform>> &transforms, + std::map<std::string, std::shared_ptr<Transform>> &transforms, std::map<std::string, IO> &ios); } diff --git a/source/adios2/transform/compress/CompressBZip2.cpp b/source/adios2/transform/compress/CompressBZip2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59c378422c42f25edf77e0dd4d99f30da3c180b0 --- /dev/null +++ b/source/adios2/transform/compress/CompressBZip2.cpp @@ -0,0 +1,170 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * CompressBZip2.cpp + * + * Created on: Jul 24, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "CompressBZip2.h" + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <cmath> //std::ceil +#include <ios> //std::ios_base::failure +#include <stdexcept> //std::invalid_argument +/// \endcond + +#include <bzlib.h> + +#include "adios2/helper/adiosFunctions.h" + +namespace adios2 +{ +namespace transform +{ + +CompressBZip2::CompressBZip2(const bool debugMode) +: Transform("bzip2", debugMode) +{ +} + +size_t CompressBZip2::BufferMaxSize(const size_t sizeIn) const +{ + return static_cast<size_t>(std::ceil(1.1 * sizeIn) + 600); +} + +size_t CompressBZip2::Compress(const void *dataIn, const Dims &dimensions, + const size_t elementSize, const std::string type, + void *bufferOut, const Params ¶meters) const +{ + // defaults + int blockSize100k = 1; + int verbosity = 0; + int workFactor = 0; + + if (!parameters.empty()) + { + const std::string hint(" in call to CompressBZip2 Compress " + type + + "\n"); + SetParameterValueInt("BlockSize100K", parameters, blockSize100k, + m_DebugMode, hint); + SetParameterValueInt("Verbosity", parameters, verbosity, m_DebugMode, + hint); + SetParameterValueInt("WorkFactor", parameters, workFactor, m_DebugMode, + hint); + if (m_DebugMode == true) + { + + if (blockSize100k < 1 || blockSize100k > 9) + { + throw std::invalid_argument( + "ERROR: BlockSize100K must be an " + "integer between 1 (less " + "compression, less memory) and 9 " + "(more compression, more memory) inclusive, " + + hint); + } + } + } + + const size_t sizeIn = + static_cast<const size_t>(GetTotalSize(dimensions) * elementSize); + // Build inputs to BZip2 compression function + char *dest = const_cast<char *>(reinterpret_cast<const char *>(bufferOut)); + unsigned int destLen = static_cast<unsigned int>(BufferMaxSize(sizeIn)); + + char *source = const_cast<char *>(reinterpret_cast<const char *>(dataIn)); + unsigned int sourceLen = static_cast<unsigned int>(sizeIn); + + int status = BZ2_bzBuffToBuffCompress(dest, &destLen, source, sourceLen, + blockSize100k, verbosity, workFactor); + + if (m_DebugMode) + { + CheckStatus(status, "in call to CompressBZip2 Compress\n"); + } + + return static_cast<size_t>(destLen); +} + +size_t CompressBZip2::Decompress(const void *bufferIn, const size_t sizeIn, + void *dataOut, const size_t sizeOut) const +{ + // TODO: leave defaults at zero? + int small = 0; + int verbosity = 0; + + char *dest = reinterpret_cast<char *>(dataOut); + unsigned int destLen = static_cast<unsigned int>(sizeOut); + + char *source = const_cast<char *>(reinterpret_cast<const char *>(bufferIn)); + unsigned int sourceLen = static_cast<unsigned int>(sizeIn); + + int status = BZ2_bzBuffToBuffDecompress(dest, &destLen, source, sourceLen, + small, verbosity); + + if (m_DebugMode) + { + CheckStatus(status, "in call to CompressBZip2 Decompress\n"); + } + + return static_cast<size_t>(destLen); +} + +void CompressBZip2::CheckStatus(const int status, const std::string hint) const +{ + switch (status) + { + + case (BZ_CONFIG_ERROR): + throw std::invalid_argument( + "ERROR: BZ_CONFIG_ERROR, bzip2 library is not configured " + "correctly" + + hint); + break; + + case (BZ_PARAM_ERROR): + throw std::invalid_argument( + "ERROR: BZ_PARAM_ERROR bufferOut stream might be null" + hint); + break; + + case (BZ_MEM_ERROR): + throw std::ios_base::failure( + "ERROR: BZ_MEM_ERROR bzip2 detected insufficient memory " + hint); + break; + + case (BZ_OUTBUFF_FULL): + throw std::ios_base::failure("ERROR: BZ_OUTBUFF_FULL bzip2 detected " + "size of compressed data is larger than " + "destination length " + + hint); + break; + + // decompression + case (BZ_DATA_ERROR): + throw std::invalid_argument("ERROR: BZ_DATA_ERROR, bzip2 library " + "detected integrity errors in compressed " + "data " + + hint); + break; + + case (BZ_DATA_ERROR_MAGIC): + throw std::invalid_argument("ERROR: BZ_DATA_ERROR_MAGIC, bzip2 library " + "detected wrong magic numbers in " + "compressed data " + + hint); + break; + + case (BZ_UNEXPECTED_EOF): + throw std::invalid_argument("ERROR: BZ_UNEXPECTED_EOF, bzip2 library " + "detected unexpected end of " + "compressed data " + + hint); + break; + } +} + +} // end namespace transform +} // end namespace adios2 diff --git a/source/adios2/transform/compress/CompressBZip2.h b/source/adios2/transform/compress/CompressBZip2.h new file mode 100644 index 0000000000000000000000000000000000000000..81cd28759a041a0feca1408c80a2e1ab784cb194 --- /dev/null +++ b/source/adios2/transform/compress/CompressBZip2.h @@ -0,0 +1,74 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * CompressBZip2.h : wrapper to BZip2 compression library + * + * Created on: Jul 24, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_TRANSFORM_COMPRESSION_COMPRESSBZIP2_H_ +#define ADIOS2_TRANSFORM_COMPRESSION_COMPRESSBZIP2_H_ + +#include "adios2/core/Transform.h" + +namespace adios2 +{ +namespace transform +{ + +class CompressBZip2 : public Transform +{ + +public: + /** + * Unique constructor + * @param debugMode + */ + CompressBZip2(const bool debugMode); + + ~CompressBZip2() = default; + + size_t BufferMaxSize(const size_t sizeIn) const final; + + /** + * Compression signature for legacy libraries that use void* + * @param dataIn + * @param dimensions + * @param type + * @param bufferOut + * @param parameters + * @return size of compressed buffer in bytes + */ + size_t Compress(const void *dataIn, const Dims &dimensions, + const size_t elementSize, const std::string type, + void *bufferOut, + const Params ¶meters = Params()) const final; + + /** + * Decompression signature for legacy libraries that use void* + * @param bufferIn + * @param sizeIn + * @param dataOut + * @param dimensions + * @param type + * @return size of decompressed buffer in bytes + */ + size_t Decompress(const void *bufferIn, const size_t sizeIn, void *dataOut, + const size_t sizeOut) const final; + +private: + /** + * In debug mode, check status from BZip compression and decompression + * functions + * @param status returned by BZip2 library + * @param hint extra exception information + */ + void CheckStatus(const int status, const std::string hint) const; +}; + +} // end namespace transform +} // end namespace adios2 + +#endif /* ADIOS2_TRANSFORM_COMPRESSION_COMPRESSBZIP2_H_ */ diff --git a/source/adios2/transform/compress/CompressZfp.cpp b/source/adios2/transform/compress/CompressZfp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b53f18c4f82e55281fb69e1cf210b3f5df8b6428 --- /dev/null +++ b/source/adios2/transform/compress/CompressZfp.cpp @@ -0,0 +1,278 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * CompressZfp.cpp + * + * Created on: Jul 25, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "CompressZfp.h" + +#include "adios2/helper/adiosFunctions.h" + +namespace adios2 +{ +namespace transform +{ + +CompressZfp::CompressZfp(const bool debugMode) : Transform("zfp", debugMode) {} + +size_t CompressZfp::DoBufferMaxSize(const void *dataIn, const Dims &dimensions, + const std::string type, + const Params ¶meters) const +{ + zfp_field *field = GetZFPField(dataIn, dimensions, type); + zfp_stream *stream = GetZFPStream(dimensions, type, parameters); + const size_t maxSize = zfp_stream_maximum_size(stream, field); + zfp_field_free(field); + zfp_stream_close(stream); + return maxSize; +} + +size_t CompressZfp::Compress(const void *dataIn, const Dims &dimensions, + const size_t elementSize, const std::string type, + void *bufferOut, const Params ¶meters) const +{ + + zfp_field *field = GetZFPField(dataIn, dimensions, type); + zfp_stream *stream = GetZFPStream(dimensions, type, parameters); + size_t maxSize = zfp_stream_maximum_size(stream, field); + // associate bitstream + bitstream *bitstream = stream_open(bufferOut, maxSize); + zfp_stream_set_bit_stream(stream, bitstream); + zfp_stream_rewind(stream); + + size_t sizeOut = zfp_compress(stream, field); + + if (m_DebugMode == true) + { + if (sizeOut == 0) + { + throw std::invalid_argument("ERROR: zfp failed, compressed buffer " + "size is 0, in call to Compress"); + } + } + + zfp_field_free(field); + zfp_stream_close(stream); + return sizeOut; +} + +size_t CompressZfp::Decompress(const void *bufferIn, const size_t sizeIn, + void *dataOut, const Dims &dimensions, + const std::string type, + const Params ¶meters) const +{ + auto lf_GetTypeSize = [](const zfp_type zfpType) -> size_t { + + size_t size = 0; + if (zfpType == zfp_type_int32 || zfpType == zfp_type_float) + { + size = 4; + } + else if (zfpType == zfp_type_int64 || zfpType == zfp_type_double) + { + size = 8; + } + return size; + }; + + zfp_field *field = GetZFPField(dataOut, dimensions, type); + zfp_stream *stream = GetZFPStream(dimensions, type, parameters); + + // associate bitstream + bitstream *bitstream = stream_open(const_cast<void *>(bufferIn), sizeIn); + zfp_stream_set_bit_stream(stream, bitstream); + zfp_stream_rewind(stream); + + int status = zfp_decompress(stream, field); + + if (m_DebugMode) + { + if (!status) + { + throw std::invalid_argument( + "ERROR: zfp failed with status " + std::to_string(status) + + ", in call to CompressZfp Decompress\n"); + } + } + + zfp_field_free(field); + zfp_stream_close(stream); + stream_close(bitstream); + + const size_t typeSizeBytes = lf_GetTypeSize(GetZfpType(type)); + const size_t dataSizeBytes = GetTotalSize(dimensions) * typeSizeBytes; + + return dataSizeBytes; +} + +// PRIVATE +zfp_type CompressZfp::GetZfpType(const std::string type) const +{ + zfp_type zfpType = zfp_type_none; + + if (type == GetType<double>()) + { + zfpType = zfp_type_double; + } + else if (type == GetType<float>()) + { + zfpType = zfp_type_float; + } + else if (type == GetType<int64_t>()) + { + zfpType = zfp_type_int64; + } + else if (type == GetType<int32_t>()) + { + zfpType = zfp_type_int32; + } + else + { + if (m_DebugMode) + { + + throw std::invalid_argument( + "ERROR: type " + type + + " not supported by zfp, only " + "signed int32_t, signed int64_t, float, and " + "double types are acceptable, from class " + "CompressZfp Transform\n"); + } + } + + return zfpType; +} + +zfp_field *CompressZfp::GetZFPField(const void *data, const Dims &dimensions, + const std::string type) const +{ + auto lf_CheckField = [](const zfp_field *field, + const std::string zfpFieldFunction, + const std::string type) { + + if (field == nullptr || field == NULL) + { + throw std::invalid_argument( + "ERROR: " + zfpFieldFunction + " failed for data of type " + + type + ", data pointer might be corrupted, from " + "class CompressZfp Transform\n"); + } + }; + + zfp_type zfpType = GetZfpType(type); + zfp_field *field = nullptr; + + if (dimensions.size() == 1) + { + field = zfp_field_1d(const_cast<void *>(data), zfpType, dimensions[0]); + if (m_DebugMode) + { + lf_CheckField(field, "zfp_field_1d", type); + } + } + else if (dimensions.size() == 2) + { + field = zfp_field_2d(const_cast<void *>(data), zfpType, dimensions[0], + dimensions[1]); + if (m_DebugMode) + { + lf_CheckField(field, "zfp_field_2d", type); + } + } + else if (dimensions.size() == 3) + { + field = zfp_field_3d(const_cast<void *>(data), zfpType, dimensions[0], + dimensions[1], dimensions[2]); + if (m_DebugMode) + { + lf_CheckField(field, "zfp_field_3d", type); + } + } + else + { + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: zfp_field* failed for data of type " + type + + ", only 1D, 2D and 3D dimensions are supported, from " + "class CompressZfp Transform\n"); + } + } + + return field; +} + +zfp_stream *CompressZfp::GetZFPStream(const Dims &dimensions, + const std::string type, + const Params ¶meters) const +{ + auto lf_HasKey = [](Params::const_iterator itKey, + const Params ¶meters) -> bool { + + bool hasKey = false; + if (itKey != parameters.end()) + { + hasKey = true; + } + return hasKey; + }; + + zfp_stream *stream = zfp_stream_open(NULL); + + auto itTolerance = parameters.find("Tolerance"); + const bool hasTolerance = lf_HasKey(itTolerance, parameters); + + auto itRate = parameters.find("Rate"); + const bool hasRate = lf_HasKey(itRate, parameters); + + auto itPrecision = parameters.find("Precision"); + const bool hasPrecision = lf_HasKey(itPrecision, parameters); + + if (m_DebugMode) + { + if ((hasTolerance && hasRate) || (hasTolerance && hasPrecision) || + (hasRate && hasPrecision) || + !(hasTolerance || hasRate || hasPrecision)) + { + throw std::invalid_argument("ERROR: zfp parameters Tolerance, " + "Rate, Precision are mutually " + "exclusive, only one of them is " + "mandatory, from " + "class CompressZfp Transform\n"); + } + } + + if (hasTolerance) + { + const double tolerance = StringToDouble( + itTolerance->second, m_DebugMode, + "setting Tolerance in call to CompressZfp class Transform\n"); + + zfp_stream_set_accuracy(stream, tolerance); + } + else if (hasRate) + { + const double rate = StringToDouble( + itRate->second, m_DebugMode, + "setting Rate in call to CompressZfp class Transform\n"); + // TODO support last argument write random access? + zfp_stream_set_rate(stream, rate, GetZfpType(type), + static_cast<unsigned int>(dimensions.size()), 0); + } + else if (hasPrecision) + { + const unsigned int precision = StringToUInt( + itPrecision->second, m_DebugMode, + "setting Precision in call to CompressZfp class Transform\n"); + zfp_stream_set_precision(stream, precision); + } + + return stream; +} + +} // end namespace transform +} // end namespace adios2 diff --git a/source/adios2/transform/compress/CompressZfp.h b/source/adios2/transform/compress/CompressZfp.h new file mode 100644 index 0000000000000000000000000000000000000000..251d14b455a86b8d7dd86b8bf4cc756e912cd312 --- /dev/null +++ b/source/adios2/transform/compress/CompressZfp.h @@ -0,0 +1,101 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * CompressZfp.h : wrapper to Zfp compression library + * + * Created on: Jul 25, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_TRANSFORM_COMPRESS_COMPRESSZFP_H_ +#define ADIOS2_TRANSFORM_COMPRESS_COMPRESSZFP_H_ + +#include <zfp.h> + +#include "adios2/core/Transform.h" + +namespace adios2 +{ + +namespace transform +{ + +class CompressZfp : public Transform +{ + +public: + /** + * Unique constructor + * @param debugMode + */ + CompressZfp(const bool debugMode); + + ~CompressZfp() = default; + + /** + * Wrapper around zfp compression + * @param dataIn + * @param dimensions + * @param type + * @param bufferOut + * @param parameters + * @return size of compressed buffer in bytes + */ + size_t Compress(const void *dataIn, const Dims &dimensions, + const size_t elementSize, const std::string type, + void *bufferOut, const Params ¶meters) const final; + + /** + * Wrapper around zfp decompression + * @param bufferIn + * @param sizeIn + * @param dataOut + * @param dimensions + * @param type + * @return size of decompressed data in dataOut + */ + size_t Decompress(const void *bufferIn, const size_t sizeIn, void *dataOut, + const Dims &dimensions, const std::string type, + const Params ¶meters) const final; + +private: + /** + * Returns Zfp supported zfp_type based on adios string type + * @param type adios type as string, see GetType<T> in + * helper/adiosType.inl + * @return zfp_type + */ + zfp_type GetZfpType(const std::string type) const; + + /** + * Constructor Zfp zfp_field based on input information around the data + * pointer + * @param data + * @param shape + * @param type + * @return zfp_field* + */ + zfp_field *GetZFPField(const void *data, const Dims &shape, + const std::string type) const; + + zfp_stream *GetZFPStream(const Dims &dimensions, const std::string type, + const Params ¶meters) const; + + size_t DoBufferMaxSize(const void *dataIn, const Dims &dimensions, + const std::string type, + const Params ¶meters) const final; + + /** + * In debug mode, check status from BZip compression and decompression + * functions + * @param status returned by BZip2 library + * @param hint extra exception information + */ + void CheckStatus(const int status, const std::string hint) const; +}; + +} // end namespace transform +} // end namespace adios2 + +#endif /* ADIOS2_TRANSFORM_COMPRESS_COMPRESSZFP_H_ */ diff --git a/source/adios2/transform/compression/BZip2.cpp b/source/adios2/transform/compression/BZip2.cpp deleted file mode 100644 index 89a61737a93408a1d44660cd32bda558be6443cb..0000000000000000000000000000000000000000 --- a/source/adios2/transform/compression/BZip2.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * BZIP2.cpp - * - * Created on: Oct 19, 2016 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include "BZip2.h" - -namespace adios2 -{ -namespace transform -{ - -BZip2::BZip2() : Transform("bzip2") {} - -void BZip2::Compress(const std::vector<char> & /*bufferIn*/, - std::vector<char> & /*bufferOut*/) -{ -} - -void BZip2::Decompress(const std::vector<char> & /*bufferIn*/, - std::vector<char> & /*bufferOut*/) -{ -} - -} // end namespace transform -} // end namespace adios diff --git a/source/adios2/transform/compression/BZip2.h b/source/adios2/transform/compression/BZip2.h deleted file mode 100644 index 1da04ed6d1656e954f5f99f966eca63300a407bc..0000000000000000000000000000000000000000 --- a/source/adios2/transform/compression/BZip2.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * BZip2.h not yet implemented - * - * Created on: Oct 17, 2016 - * Author: William F Godoy godoywf@ornl.gov - */ - -#ifndef ADIOS2_TRANSFORM_COMPRESSION_BZIP2_H_ -#define ADIOS2_TRANSFORM_COMPRESSION_BZIP2_H_ - -#include "adios2/ADIOSConfig.h" -#include "adios2/core/Transform.h" - -namespace adios2 -{ -namespace transform -{ - -class BZip2 : public Transform -{ - -public: - /** - * Initialize parent method - * @param compressionLevel - * @param variable - */ - BZip2(); - - virtual ~BZip2() = default; - - void Compress(const std::vector<char> &bufferIn, - std::vector<char> &bufferOut); - - void Decompress(const std::vector<char> &bufferIn, - std::vector<char> &bufferOut); -}; - -} // end namespace transform -} // end namespace adios - -#endif /* ADIOS2_TRANSFORM_BZIP2_H_ */ diff --git a/testing/adios2/CMakeLists.txt b/testing/adios2/CMakeLists.txt index 544e4099f8a6d3d309e8d97dbbf80c3deff1c91c..2115e42d9a8d60498548be59448f610ec898ff22 100644 --- a/testing/adios2/CMakeLists.txt +++ b/testing/adios2/CMakeLists.txt @@ -7,3 +7,4 @@ add_subdirectory(interface) add_subdirectory(engine) add_subdirectory(bindings) add_subdirectory(xml) +add_subdirectory(transform) diff --git a/testing/adios2/transform/CMakeLists.txt b/testing/adios2/transform/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c99f2964056c867be880f00c70fde1b219b9668e --- /dev/null +++ b/testing/adios2/transform/CMakeLists.txt @@ -0,0 +1,19 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + + +if(ADIOS2_HAVE_BZip2) + add_executable(TestBZip2Wrapper TestBZip2Wrapper.cpp) + target_link_libraries(TestBZip2Wrapper adios2 gtest gtest_main ${BZIP2_LIBRARIES}) + + gtest_add_tests(TARGET TestBZip2Wrapper ${BZIP2_LIBRARIES}) +endif() + +if(ADIOS2_HAVE_ZFP) + add_executable(TestZfpWrapper TestZfpWrapper.cpp) + target_link_libraries(TestZfpWrapper adios2 gtest gtest_main zfp::zfp) + + gtest_add_tests(TARGET TestZfpWrapper zfp::zfp) +endif() \ No newline at end of file diff --git a/testing/adios2/transform/TestBZip2Wrapper.cpp b/testing/adios2/transform/TestBZip2Wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57f506ded62083af2155cf8588df67d454d4db7b --- /dev/null +++ b/testing/adios2/transform/TestBZip2Wrapper.cpp @@ -0,0 +1,125 @@ +#include <cstdint> +#include <iostream> +#include <numeric> //std::iota +#include <stdexcept> + +#include <adios2.h> + +#include <gtest/gtest.h> + +class ADIOSBZip2Wrapper : public ::testing::Test +{ +public: + ADIOSBZip2Wrapper() : adios(true), io(adios.DeclareIO("TestADIOSBZip2")) {} + +protected: + adios2::ADIOS adios; + adios2::IO &io; +}; + +TEST_F(ADIOSBZip2Wrapper, UInt100) +{ + /** Application variable uints from 0 to 1000 */ + std::vector<unsigned int> myUInts(100); + std::iota(myUInts.begin(), myUInts.end(), 0.f); + const std::size_t Nx = myUInts.size(); + const std::size_t inputBytes = Nx * sizeof(unsigned int); + + // Define ADIOS variable + auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx}, + adios2::ConstantDims); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(var_UInt), + adios2::Variable<unsigned int> &>(); + + // Define bzip2 transform + adios2::Transform &adiosBZip2 = adios.GetTransform("BZip2"); + + const unsigned int bzip2ID = + var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "2"}}); + + const std::size_t estimatedSize = + adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize); + std::vector<char> compressedBuffer(estimatedSize); + size_t compressedSize = adiosBZip2.Compress( + myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize, + var_UInt.m_Type, compressedBuffer.data(), + var_UInt.m_TransformsInfo[bzip2ID].Parameters); + + EXPECT_LE(compressedSize, estimatedSize); + + compressedBuffer.resize(compressedSize); + + // Allocate original data size + std::vector<unsigned int> decompressedBuffer(Nx); + size_t decompressedSize = adiosBZip2.Decompress( + compressedBuffer.data(), compressedSize, decompressedBuffer.data(), + decompressedBuffer.size() * sizeof(unsigned int)); + + // testing data recovery + for (size_t i = 0; i < Nx; ++i) + { + ASSERT_EQ(decompressedBuffer[i], myUInts[i]); + } +} + +TEST_F(ADIOSBZip2Wrapper, WrongParameterValue) +{ + /** Application variable uints from 0 to 1000 */ + std::vector<unsigned int> myUInts(100); + std::iota(myUInts.begin(), myUInts.end(), 0.f); + const std::size_t Nx = myUInts.size(); + const std::size_t inputBytes = Nx * sizeof(unsigned int); + + // Define ADIOS variable + auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx}, + adios2::ConstantDims); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(var_UInt), + adios2::Variable<unsigned int> &>(); + + // Define bzip2 transform + adios2::Transform &adiosBZip2 = adios.GetTransform("BZip2"); + + const unsigned int bzip2ID = + var_UInt.AddTransform(adiosBZip2, {{"BlockSize100K", "10"}}); + + const std::size_t estimatedSize = + adiosBZip2.BufferMaxSize(Nx * var_UInt.m_ElementSize); + std::vector<char> compressedBuffer(estimatedSize); + + EXPECT_THROW(size_t compressedSize = adiosBZip2.Compress( + myUInts.data(), var_UInt.m_Count, var_UInt.m_ElementSize, + var_UInt.m_Type, compressedBuffer.data(), + var_UInt.m_TransformsInfo[bzip2ID].Parameters), + std::invalid_argument); +} + +TEST_F(ADIOSBZip2Wrapper, WrongBZip2Name) +{ + /** Application variable uints from 0 to 1000 */ + std::vector<unsigned int> myUInts(100); + std::iota(myUInts.begin(), myUInts.end(), 0.f); + const std::size_t Nx = myUInts.size(); + const std::size_t inputBytes = Nx * sizeof(unsigned int); + + // Define ADIOS variable + auto &var_UInt = io.DefineVariable<unsigned int>("myUInts", {}, {}, {Nx}, + adios2::ConstantDims); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(var_UInt), + adios2::Variable<unsigned int> &>(); + + // Check bzip2 lower case and camel case + EXPECT_NO_THROW(adios2::Transform &adiosBZip2 = + adios.GetTransform("bzip2")); + EXPECT_NO_THROW(adios2::Transform &adiosBZip2 = + adios.GetTransform("BZip2")); + EXPECT_THROW(adios2::Transform &adiosBZip2 = adios.GetTransform("bzip"), + std::invalid_argument); + EXPECT_THROW(adios2::Transform &adiosBZip2 = adios.GetTransform("BZIP2"), + std::invalid_argument); +} diff --git a/testing/adios2/transform/TestZfpWrapper.cpp b/testing/adios2/transform/TestZfpWrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db2a2d2b09a00e91939feb977253952003348c91 --- /dev/null +++ b/testing/adios2/transform/TestZfpWrapper.cpp @@ -0,0 +1,123 @@ +#include <cmath> //std::abs +#include <iostream> +#include <numeric> //std::iota +#include <stdexcept> + +#include <adios2.h> + +#include <gtest/gtest.h> + +class ADIOSZfpWrapper : public ::testing::Test +{ +public: + ADIOSZfpWrapper() : adios(true), io(adios.DeclareIO("TestADIOSZfp")) {} + +protected: + adios2::ADIOS adios; + adios2::IO &io; +}; + +TEST_F(ADIOSZfpWrapper, Float100) +{ + /** Application variable uints from 0 to 1000 */ + std::vector<float> myFloats(100); + std::iota(myFloats.begin(), myFloats.end(), 0.f); + const std::size_t Nx = myFloats.size(); + const std::size_t inputBytes = Nx * sizeof(float); + + // Define ADIOS variable + auto &var_Floats = io.DefineVariable<float>("myFloats", {}, {}, {Nx}, + adios2::ConstantDims); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(var_Floats), + adios2::Variable<float> &>(); + + // Define bzip2 transform + adios2::Transform &adiosZfp = adios.GetTransform("Zfp"); + + const unsigned int zfpID = + var_Floats.AddTransform(adiosZfp, {{"Rate", "8"}}); + + const std::size_t estimatedSize = + adiosZfp.BufferMaxSize(myFloats.data(), var_Floats.m_Count, + var_Floats.m_TransformsInfo[zfpID].Parameters); + + std::vector<char> compressedBuffer(estimatedSize); + + size_t compressedSize = adiosZfp.Compress( + myFloats.data(), var_Floats.m_Count, var_Floats.m_ElementSize, + var_Floats.m_Type, compressedBuffer.data(), + var_Floats.m_TransformsInfo[zfpID].Parameters); + + compressedBuffer.resize(compressedSize); + + // Allocate original data size + std::vector<float> decompressedBuffer(Nx); + + size_t decompressedSize = adiosZfp.Decompress( + compressedBuffer.data(), compressedBuffer.size(), + decompressedBuffer.data(), var_Floats.m_Count, var_Floats.m_Type, + var_Floats.m_TransformsInfo[zfpID].Parameters); + + // testing data recovery for rate = 8 + for (size_t i = 0; i < Nx; ++i) + { + ASSERT_LT(std::abs(decompressedBuffer[i] - myFloats[i]), 1E-6); + } +} + +TEST_F(ADIOSZfpWrapper, UnsupportedCall) +{ + /** Application variable uints from 0 to 1000 */ + std::vector<float> myFloats(100); + std::iota(myFloats.begin(), myFloats.end(), 0.f); + const std::size_t Nx = myFloats.size(); + const std::size_t inputBytes = Nx * sizeof(float); + + // Define ADIOS variable + auto &var_Floats = io.DefineVariable<float>("myFloats", {}, {}, {Nx}, + adios2::ConstantDims); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(var_Floats), + adios2::Variable<float> &>(); + + // Define bzip2 transform + adios2::Transform &adiosZfp = adios.GetTransform("zfp"); + + const unsigned int zfpID = + var_Floats.AddTransform(adiosZfp, {{"Rate", "8"}}); + + // Wrong signature for Zfp + EXPECT_THROW(const std::size_t estimatedSize = + adiosZfp.BufferMaxSize(Nx * var_Floats.m_ElementSize), + std::invalid_argument); +} + +TEST_F(ADIOSZfpWrapper, MissingMandatoryParameter) +{ + /** Application variable uints from 0 to 1000 */ + std::vector<float> myFloats(100); + std::iota(myFloats.begin(), myFloats.end(), 0.f); + const std::size_t Nx = myFloats.size(); + const std::size_t inputBytes = Nx * sizeof(float); + + // Define ADIOS variable + auto &var_Floats = io.DefineVariable<float>("myFloats", {}, {}, {Nx}, + adios2::ConstantDims); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(var_Floats), + adios2::Variable<float> &>(); + + // Define bzip2 transform + adios2::Transform &adiosZfp = adios.GetTransform("zfp"); + + const unsigned int zfpID = var_Floats.AddTransform(adiosZfp); + + EXPECT_THROW(const std::size_t estimatedSize = adiosZfp.BufferMaxSize( + myFloats.data(), var_Floats.m_Count, + var_Floats.m_TransformsInfo[zfpID].Parameters), + std::invalid_argument); +}