diff --git a/bindings/CXX11/CMakeLists.txt b/bindings/CXX11/CMakeLists.txt index e000967f08..01b667e83a 100644 --- a/bindings/CXX11/CMakeLists.txt +++ b/bindings/CXX11/CMakeLists.txt @@ -11,6 +11,8 @@ target_sources(adios2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cxx11/IO.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cxx11/IO.tcc ${CMAKE_CURRENT_SOURCE_DIR}/cxx11/Operator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cxx11/Types.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cxx11/Types.tcc ${CMAKE_CURRENT_SOURCE_DIR}/cxx11/Variable.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cxx11/fstream/ADIOS2fstream.cpp ) @@ -38,5 +40,6 @@ install( cxx11/Attribute.h cxx11/Engine.h cxx11/Operator.h + cxx11/Types.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cxx11 ) diff --git a/bindings/CXX11/cxx11/Engine.tcc b/bindings/CXX11/cxx11/Engine.tcc index cb4a96f1f3..a5ab4236c4 100644 --- a/bindings/CXX11/cxx11/Engine.tcc +++ b/bindings/CXX11/cxx11/Engine.tcc @@ -60,8 +60,8 @@ void Engine::Put(Variable variable, const T *data, const Mode launch) { using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr(m_Engine, "in call to Engine::Put"); - adios2::helper::CheckForNullptr( - variable.m_Variable, "for variable in call to Engine::Put"); + adios2::helper::CheckForNullptr(variable.m_Variable, + "for variable in call to Engine::Put"); m_Engine->Put(*variable.m_Variable, reinterpret_cast(data), launch); } @@ -80,8 +80,8 @@ void Engine::Put(Variable variable, const T &datum, const Mode /*launch*/) { using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr(m_Engine, "in call to Engine::Put"); - adios2::helper::CheckForNullptr( - variable.m_Variable, "for variable in call to Engine::Put"); + adios2::helper::CheckForNullptr(variable.m_Variable, + "for variable in call to Engine::Put"); m_Engine->Put(*variable.m_Variable, reinterpret_cast(datum)); } @@ -100,8 +100,8 @@ void Engine::Get(Variable variable, T *data, const Mode launch) { using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr(m_Engine, "in call to Engine::Get"); - adios2::helper::CheckForNullptr( - variable.m_Variable, "for variable in call to Engine::Get"); + adios2::helper::CheckForNullptr(variable.m_Variable, + "for variable in call to Engine::Get"); m_Engine->Get(*variable.m_Variable, reinterpret_cast(data), launch); } @@ -119,8 +119,8 @@ void Engine::Get(Variable variable, T &datum, const Mode /*launch*/) { using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr(m_Engine, "in call to Engine::Get"); - adios2::helper::CheckForNullptr( - variable.m_Variable, "for variable in call to Engine::Get"); + adios2::helper::CheckForNullptr(variable.m_Variable, + "for variable in call to Engine::Get"); m_Engine->Get(*variable.m_Variable, reinterpret_cast(datum)); } @@ -139,8 +139,8 @@ void Engine::Get(Variable variable, std::vector &dataV, const Mode launch) using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr( m_Engine, "in call to Engine::Get with std::vector argument"); - adios2::helper::CheckForNullptr( - variable.m_Variable, "for variable in call to Engine::Get"); + adios2::helper::CheckForNullptr(variable.m_Variable, + "for variable in call to Engine::Get"); m_Engine->Get(*variable.m_Variable, reinterpret_cast &>(dataV), launch); } @@ -152,25 +152,30 @@ void Engine::Get(const std::string &variableName, std::vector &dataV, using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr( m_Engine, "in call to Engine::Get with std::vector argument"); - m_Engine->Get(variableName, reinterpret_cast &>(dataV), launch); + m_Engine->Get(variableName, reinterpret_cast &>(dataV), + launch); } template -void Engine::Get(Variable variable, typename Variable::Info& info, const Mode launch) +void Engine::Get(Variable variable, typename Variable::Info &info, + const Mode launch) { using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr(m_Engine, "in call to Engine::Get"); - adios2::helper::CheckForNullptr( - variable.m_Variable, "for variable in call to Engine::Get"); - info.m_Info = m_Engine->Get(*variable.m_Variable, launch); + adios2::helper::CheckForNullptr(variable.m_Variable, + "for variable in call to Engine::Get"); + info.m_Info = reinterpret_cast::Info::CoreInfo *>( + m_Engine->Get(*variable.m_Variable, launch)); } template -void Engine::Get(const std::string &variableName, typename Variable::Info& info, const Mode launch) +void Engine::Get(const std::string &variableName, + typename Variable::Info &info, const Mode launch) { using IOType = typename TypeInfo::IOType; adios2::helper::CheckForNullptr(m_Engine, "in call to Engine::Get"); - info.m_Info = m_Engine->Get(variableName, launch); + info.m_Info = reinterpret_cast::Info::CoreInfo *>( + m_Engine->Get(variableName, launch)); } template @@ -205,7 +210,8 @@ Engine::AllStepsBlocksInfo(const Variable variable) const // Design Node: All Info structs are copied. This prevents Engine::Get() from // connecting the Core Info struct to Binding Info struct when this method is -// called. Instead of returning a vector, BlocksInfo could populate a vector member +// called. Instead of returning a vector, BlocksInfo could populate a vector +// member // of the Variable, and those could contain pointers to the Core Info structs, // enabling users of the Inline engine to do Info.Data() template diff --git a/bindings/CXX11/cxx11/Types.cpp b/bindings/CXX11/cxx11/Types.cpp new file mode 100644 index 0000000000..9303e8a6a6 --- /dev/null +++ b/bindings/CXX11/cxx11/Types.cpp @@ -0,0 +1,22 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Types.cpp : implementation of Types.h + * + * Created on: Feb 12, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ +#include "Types.h" +#include "Types.tcc" + +namespace adios2 +{ + +#define declare_template_instantiation(T) \ + template std::string GetType() noexcept; + +ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + +} // end namespace adios2 diff --git a/bindings/CXX11/cxx11/Types.h b/bindings/CXX11/cxx11/Types.h index 7ff11b3cb7..fb8278bc91 100644 --- a/bindings/CXX11/cxx11/Types.h +++ b/bindings/CXX11/cxx11/Types.h @@ -6,23 +6,29 @@ * * Created on: Feb 11, 2019 * Author: Kai Germaschewski + * William F Godoy */ #ifndef ADIOS2_BINDINGS_CXX11_TYPES_H_ #define ADIOS2_BINDINGS_CXX11_TYPES_H_ -#include "adios2/helper/adiosType.h" +#include "Variable.h" + +#include namespace adios2 { template -inline std::string GetType() noexcept -{ - using IOType = typename TypeInfo::IOType; - return helper::GetType(); -} +std::string GetType() noexcept; -} // end namespace adios2 +// LIMIT TEMPLATE TYPES FOR adios2::GetType +#define declare_template_instantiation(T) \ + \ + extern template std::string GetType() noexcept; +ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + +} // end namespace adios2 #endif /* ADIOS2_BINDINGS_CXX11_TYPES_H_ */ diff --git a/bindings/CXX11/cxx11/Types.tcc b/bindings/CXX11/cxx11/Types.tcc new file mode 100644 index 0000000000..ff90edd72f --- /dev/null +++ b/bindings/CXX11/cxx11/Types.tcc @@ -0,0 +1,29 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Types.tcc : implement template functions + * + * Created on: Feb 11, 2019 + * Author: William F Godoy + */ + +#ifndef ADIOS2_BINDINGS_CXX11_TYPES_TCC_ +#define ADIOS2_BINDINGS_CXX11_TYPES_TCC_ + +#include "Types.h" + +#include "adios2/helper/adiosFunctions.h" + +namespace adios2 +{ + +template +std::string GetType() noexcept +{ + return helper::GetType::IOType>(); +} + +} // end namespace adios2 + +#endif /* ADIOS2_BINDINGS_CXX11_TYPES_TCC_ */ diff --git a/bindings/CXX11/cxx11/Variable.cpp b/bindings/CXX11/cxx11/Variable.cpp index 92524222bd..bfebb9c0ac 100644 --- a/bindings/CXX11/cxx11/Variable.cpp +++ b/bindings/CXX11/cxx11/Variable.cpp @@ -8,6 +8,7 @@ * Author: William F Godoy godoywf@ornl.gov */ #include "Variable.h" +#include "Variable.tcc" #include "adios2/ADIOSMacros.h" #include "adios2/core/Variable.h" @@ -200,6 +201,24 @@ namespace adios2 { \ helper::CheckForNullptr(m_Variable, "in call to Variable::Max"); \ return m_Variable->Max(step); \ + } \ + \ + template <> \ + std::vector::Info>> \ + Variable::AllStepsBlocksInfo() \ + { \ + return DoAllStepsBlocksInfo(); \ + } \ + \ + template <> \ + const T *Variable::Info::Data() const \ + { \ + const core::Variable::Info *coreInfo = \ + reinterpret_cast::Info *>(m_Info); \ + \ + return m_Info ? (coreInfo->BufferP ? coreInfo->BufferP \ + : coreInfo->BufferV.data()) \ + : nullptr; \ } ADIOS2_FOREACH_TYPE_1ARG(declare_type) diff --git a/bindings/CXX11/cxx11/Variable.h b/bindings/CXX11/cxx11/Variable.h index 4f0922ff64..4c7064cda2 100644 --- a/bindings/CXX11/cxx11/Variable.h +++ b/bindings/CXX11/cxx11/Variable.h @@ -14,7 +14,6 @@ #include "Operator.h" #include "adios2/ADIOSTypes.h" -#include "adios2/core/Variable.h" namespace adios2 { @@ -238,29 +237,39 @@ class Variable /** Contains sub-block information for a particular Variable */ struct Info { - adios2::Dims Start; ///< block start - adios2::Dims Count; ///< block count + adios2::Dims Start; ///< block start + adios2::Dims Count; ///< block count IOType Min = IOType(); ///< block Min, if IsValue is false IOType Max = IOType(); ///< block Max, if IsValue is false IOType Value = IOType(); ///< block Value, if IsValue is true - bool IsValue = false; ///< true: value, false: array - size_t BlockID = -1; ///< block ID for block selections - const T *Data() const - { - return m_Info ? (m_Info->BufferP ? m_Info->BufferP - : m_Info->BufferV.data()) - : nullptr; - }; ///< block data for block selections. Provided by core Info. + bool IsValue = false; ///< true: value, false: array + size_t BlockID = -1; ///< block ID for block selections + size_t Step = 0; + const T *Data() const; + // allow Engine to set m_Info friend class Engine; private: - const typename core::Variable::Info *m_Info; + class CoreInfo; + const CoreInfo *m_Info; }; + /** + * Read mode only and random-access (no BeginStep/EndStep) with file engines + * only. Allows inspection of variable info on a per relative step (returned + * vector index) + * basis + * @return first vector: relative steps, second vector: blocks info within a + * step + */ + std::vector::Info>> AllStepsBlocksInfo(); + private: Variable(core::Variable *variable); core::Variable *m_Variable = nullptr; + + std::vector::Info>> DoAllStepsBlocksInfo(); }; } // end namespace adios2 diff --git a/bindings/CXX11/cxx11/Variable.tcc b/bindings/CXX11/cxx11/Variable.tcc new file mode 100644 index 0000000000..a6319a55f4 --- /dev/null +++ b/bindings/CXX11/cxx11/Variable.tcc @@ -0,0 +1,85 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Variable.tcc : implementation of private template functions + * + * Created on: Feb 12, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_BINDINGS_CXX11_CXX11_VARIABLE_TCC_ +#define ADIOS2_BINDINGS_CXX11_CXX11_VARIABLE_TCC_ + +#include "Variable.h" + +#include "adios2/helper/adiosFunctions.h" + +namespace adios2 +{ + +namespace +{ + +template +std::vector::Info> +ToBlocksInfo(const std::vector::IOType>::Info> &coreBlocksInfo) +{ + using IOType = typename TypeInfo::IOType; + + std::vector::Info> blocksInfo; + blocksInfo.reserve(coreBlocksInfo.size()); + + for (const typename core::Variable::Info &coreBlockInfo : + coreBlocksInfo) + { + typename Variable::Info blockInfo; + blockInfo.Start = coreBlockInfo.Start; + blockInfo.Count = coreBlockInfo.Count; + blockInfo.IsValue = coreBlockInfo.IsValue; + if (blockInfo.IsValue) + { + blockInfo.Value = coreBlockInfo.Value; + } + else + { + blockInfo.Min = coreBlockInfo.Min; + blockInfo.Max = coreBlockInfo.Max; + } + blockInfo.BlockID = coreBlockInfo.BlockID; + blockInfo.Step = coreBlockInfo.Step; + blocksInfo.push_back(blockInfo); + } + + return blocksInfo; +} +} // end empty namespace + +template +std::vector::Info>> +Variable::DoAllStepsBlocksInfo() +{ + helper::CheckForNullptr(m_Variable, + "in call to Variable::AllStepsBlocksInfo"); + + // PRIVATE INPUT + const std::vector::Info>> + coreAllStepsBlocksInfo = m_Variable->AllStepsBlocksInfo(); + + // PUBLIC OUTPUT + std::vector::Info>> allStepsBlocksInfo( + coreAllStepsBlocksInfo.size()); + + size_t relativeStep = 0; + for (const auto &coreBlocksInfo : coreAllStepsBlocksInfo) + { + allStepsBlocksInfo[relativeStep] = ToBlocksInfo(coreBlocksInfo); + ++relativeStep; + } + return allStepsBlocksInfo; +} + +} // end namespace adios2 + +#endif /* ADIOS2_BINDINGS_CXX11_CXX11_VARIABLE_TCC_ */ diff --git a/source/adios2/core/Engine.cpp b/source/adios2/core/Engine.cpp index fa7d86dc4b..04de303806 100644 --- a/source/adios2/core/Engine.cpp +++ b/source/adios2/core/Engine.cpp @@ -116,6 +116,13 @@ ADIOS2_FOREACH_TYPE_1ARG(declare_type) return std::map::Info>>(); \ } \ \ + std::vector::Info>> \ + Engine::DoAllRelativeStepsBlocksInfo(const Variable &variable) const \ + { \ + ThrowUp("DoAllRelativeStepsBlocksInfo"); \ + return std::vector::Info>>(); \ + } \ + \ std::vector::Info> Engine::DoBlocksInfo( \ const Variable &variable, const size_t step) const \ { \ @@ -172,10 +179,13 @@ void Engine::CheckOpenModes(const std::set &modes, const std::string &variableName, const std::string hint); \ \ template std::map::Info>> \ - Engine::AllStepsBlocksInfo(const Variable &variable) const; \ + Engine::AllStepsBlocksInfo(const Variable &) const; \ + \ + template std::vector::Info>> \ + Engine::AllRelativeStepsBlocksInfo(const Variable &) const; \ \ template std::vector::Info> Engine::BlocksInfo( \ - const Variable &variable, const size_t step) const; + const Variable &, const size_t) const; ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) #undef declare_template_instantiation diff --git a/source/adios2/core/Engine.h b/source/adios2/core/Engine.h index 938e1990d3..f68ca7372e 100644 --- a/source/adios2/core/Engine.h +++ b/source/adios2/core/Engine.h @@ -385,6 +385,16 @@ class Engine std::map::Info>> AllStepsBlocksInfo(const Variable &variable) const; + /** + * This function is internal, for public interface use + * Variable::AllStepsBlocksInfo + * @param variable + * @return + */ + template + std::vector::Info>> + AllRelativeStepsBlocksInfo(const Variable &variable) const; + /** * Extracts all available blocks information for a particular * variable and step. @@ -455,6 +465,9 @@ class Engine virtual std::map::Info>> \ DoAllStepsBlocksInfo(const Variable &variable) const; \ \ + virtual std::vector::Info>> \ + DoAllRelativeStepsBlocksInfo(const Variable &variable) const; \ + \ virtual std::vector::Info> DoBlocksInfo( \ const Variable &variable, const size_t step) const; @@ -518,10 +531,13 @@ class Engine const std::string &variableName, const std::string hint); \ \ extern template std::map::Info>> \ - Engine::AllStepsBlocksInfo(const Variable &variable) const; \ + Engine::AllStepsBlocksInfo(const Variable &) const; \ + \ + extern template std::vector::Info>> \ + Engine::AllRelativeStepsBlocksInfo(const Variable &) const; \ \ extern template std::vector::Info> \ - Engine::BlocksInfo(const Variable &variable, const size_t step) const; + Engine::BlocksInfo(const Variable &, const size_t) const; ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) #undef declare_template_instantiation diff --git a/source/adios2/core/Engine.tcc b/source/adios2/core/Engine.tcc index 96a72497fc..9266eeaff9 100644 --- a/source/adios2/core/Engine.tcc +++ b/source/adios2/core/Engine.tcc @@ -136,7 +136,8 @@ void Engine::Get(const std::string &variableName, std::vector &dataV, // Get template -typename Variable::Info* Engine::Get(Variable &variable, const Mode launch) +typename Variable::Info *Engine::Get(Variable &variable, + const Mode launch) { if (m_DebugMode) { @@ -166,7 +167,8 @@ typename Variable::Info* Engine::Get(Variable &variable, const Mode launch } template -typename Variable::Info* Engine::Get(const std::string &variableName, const Mode launch) +typename Variable::Info *Engine::Get(const std::string &variableName, + const Mode launch) { return Get(FindVariable(variableName, "in call to Get"), launch); } @@ -178,6 +180,13 @@ Engine::AllStepsBlocksInfo(const Variable &variable) const return DoAllStepsBlocksInfo(variable); } +template +std::vector::Info>> +Engine::AllRelativeStepsBlocksInfo(const Variable &variable) const +{ + return DoAllRelativeStepsBlocksInfo(variable); +} + template std::vector::Info> Engine::BlocksInfo(const Variable &variable, const size_t step) const diff --git a/source/adios2/core/Variable.cpp b/source/adios2/core/Variable.cpp index 6ab3a6e277..6551dce2bc 100644 --- a/source/adios2/core/Variable.cpp +++ b/source/adios2/core/Variable.cpp @@ -88,6 +88,13 @@ namespace core T Variable::Max(const size_t step) const \ { \ return MinMax(step).second; \ + } \ + \ + template <> \ + std::vector::Info>> \ + Variable::AllStepsBlocksInfo() const \ + { \ + return DoAllStepsBlocksInfo(); \ } ADIOS2_FOREACH_TYPE_1ARG(declare_type) diff --git a/source/adios2/core/Variable.h b/source/adios2/core/Variable.h index 72b62d4961..a95d146df8 100644 --- a/source/adios2/core/Variable.h +++ b/source/adios2/core/Variable.h @@ -63,6 +63,7 @@ class Variable : public VariableBase Dims MemoryStart; Dims MemoryCount; std::vector Operations; + size_t Step = 0; size_t StepsStart = 0; size_t StepsCount = 0; size_t BlockID = 0; @@ -102,10 +103,16 @@ class Variable : public VariableBase T Max(const size_t step) const; + std::vector::Info>> + AllStepsBlocksInfo() const; + private: Dims DoShape(const size_t step) const; std::pair DoMinMax(const size_t step) const; + + std::vector::Info>> + DoAllStepsBlocksInfo() const; }; } // end namespace core diff --git a/source/adios2/core/Variable.tcc b/source/adios2/core/Variable.tcc index 16486f14ba..3b286a8721 100644 --- a/source/adios2/core/Variable.tcc +++ b/source/adios2/core/Variable.tcc @@ -145,6 +145,33 @@ std::pair Variable::DoMinMax(const size_t step) const return minMax; } +template +std::vector::Info>> +Variable::DoAllStepsBlocksInfo() const +{ + if (m_DebugMode && m_Engine == nullptr) + { + if (m_Engine == nullptr) + { + throw std::invalid_argument( + "ERROR: from variable " + m_Name + + " function is only valid in read mode, in " + "call to Variable::AllBlocksInfo\n"); + } + + if (!m_FirstStreamingStep) + { + throw std::invalid_argument("ERROR: from variable " + m_Name + + " function is not valid in " + "random-access read mode " + "(BeginStep/EndStep), in " + "call to Variable::AllBlocksInfo\n"); + } + } + + return m_Engine->AllRelativeStepsBlocksInfo(*this); +} + } // end namespace core } // end namespace adios2 diff --git a/source/adios2/engine/bp3/BP3Reader.cpp b/source/adios2/engine/bp3/BP3Reader.cpp index 048a2796b9..aab9f0837e 100644 --- a/source/adios2/engine/bp3/BP3Reader.cpp +++ b/source/adios2/engine/bp3/BP3Reader.cpp @@ -196,6 +196,12 @@ void BP3Reader::DoClose(const int transportIndex) return m_BP3Deserializer.AllStepsBlocksInfo(variable); \ } \ \ + std::vector::Info>> \ + BP3Reader::DoAllRelativeStepsBlocksInfo(const Variable &variable) const \ + { \ + return m_BP3Deserializer.AllRelativeStepsBlocksInfo(variable); \ + } \ + \ std::vector::Info> BP3Reader::DoBlocksInfo( \ const Variable &variable, const size_t step) const \ { \ diff --git a/source/adios2/engine/bp3/BP3Reader.h b/source/adios2/engine/bp3/BP3Reader.h index 11cf5a2dcf..0cff7e1eb1 100644 --- a/source/adios2/engine/bp3/BP3Reader.h +++ b/source/adios2/engine/bp3/BP3Reader.h @@ -80,7 +80,10 @@ class BP3Reader : public Engine #define declare_type(T) \ std::map::Info>> \ - DoAllStepsBlocksInfo(const Variable &variable) const final; \ + DoAllStepsBlocksInfo(const Variable &) const final; \ + \ + std::vector::Info>> \ + DoAllRelativeStepsBlocksInfo(const Variable &) const final; \ \ std::vector::Info> DoBlocksInfo( \ const Variable &variable, const size_t step) const final; diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp index a54ae230db..d978f0d294 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp @@ -552,6 +552,10 @@ ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) template std::map::Info>> \ BP3Deserializer::AllStepsBlocksInfo(const core::Variable &) const; \ \ + template std::vector::Info>> \ + BP3Deserializer::AllRelativeStepsBlocksInfo(const core::Variable &) \ + const; \ + \ template std::vector::Info> \ BP3Deserializer::BlocksInfo(const core::Variable &, const size_t) \ const; \ diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.h b/source/adios2/toolkit/format/bp3/BP3Deserializer.h index f6de0f5226..c96877468a 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.h +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.h @@ -130,6 +130,10 @@ class BP3Deserializer : public BP3Base std::map::Info>> AllStepsBlocksInfo(const core::Variable &variable) const; + template + std::vector::Info>> + AllRelativeStepsBlocksInfo(const core::Variable &variable) const; + template std::vector::Info> BlocksInfo(const core::Variable &variable, const size_t step) const; @@ -247,6 +251,10 @@ ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) std::vector::Info>> \ BP3Deserializer::AllStepsBlocksInfo(const core::Variable &) const; \ \ + extern template std::vector::Info>> \ + BP3Deserializer::AllRelativeStepsBlocksInfo(const core::Variable &) \ + const; \ + \ extern template std::vector::Info> \ BP3Deserializer::BlocksInfo(const core::Variable &, const size_t) \ const; \ diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc index 7177674ed1..dffe0fd317 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc @@ -579,6 +579,26 @@ BP3Deserializer::AllStepsBlocksInfo(const core::Variable &variable) const return allStepsBlocksInfo; } +template +std::vector::Info>> +BP3Deserializer::AllRelativeStepsBlocksInfo( + const core::Variable &variable) const +{ + std::vector::Info>> + allRelativeStepsBlocksInfo( + variable.m_AvailableStepBlockIndexOffsets.size()); + + size_t relativeStep = 0; + for (const auto &pair : variable.m_AvailableStepBlockIndexOffsets) + { + const std::vector &blockPositions = pair.second; + allRelativeStepsBlocksInfo[relativeStep] = + BlocksInfoCommon(variable, blockPositions); + ++relativeStep; + } + return allRelativeStepsBlocksInfo; +} + template std::vector::Info> BP3Deserializer::BlocksInfo(const core::Variable &variable, @@ -1057,9 +1077,15 @@ std::vector::Info> BP3Deserializer::BlocksInfoCommon( blockInfo.Start = Dims{n}; blockInfo.Min = blockCharacteristics.Statistics.Value; blockInfo.Max = blockCharacteristics.Statistics.Value; - ++n; } + // bp index starts at 1 + blockInfo.Step = + static_cast(blockCharacteristics.Statistics.Step - 1); + blockInfo.BlockID = n; + blocksInfo.push_back(blockInfo); + + ++n; } return blocksInfo; diff --git a/testing/adios2/engine/bp/CMakeLists.txt b/testing/adios2/engine/bp/CMakeLists.txt index 98e11f2759..8e5001bf9a 100644 --- a/testing/adios2/engine/bp/CMakeLists.txt +++ b/testing/adios2/engine/bp/CMakeLists.txt @@ -67,6 +67,9 @@ target_link_libraries(TestBPWriteReadLocalVariablesSel adios2 gtest) add_executable(TestBPChangingShape TestBPChangingShape.cpp) target_link_libraries(TestBPChangingShape adios2 gtest) +add_executable(TestBPWriteReadBlockInfo TestBPWriteReadBlockInfo.cpp) +target_link_libraries(TestBPWriteReadBlockInfo adios2 gtest) + if(ADIOS2_HAVE_MPI) target_link_libraries(TestBPWriteReadADIOS2 MPI::MPI_C) @@ -86,6 +89,7 @@ if(ADIOS2_HAVE_MPI) target_link_libraries(TestBPWriteReadLocalVariables MPI::MPI_C) target_link_libraries(TestBPWriteReadLocalVariablesSel MPI::MPI_C) target_link_libraries(TestBPChangingShape MPI::MPI_C) + target_link_libraries(TestBPWriteReadBlockInfo MPI::MPI_C) add_executable(TestBPWriteAggregateRead TestBPWriteAggregateRead.cpp) target_link_libraries(TestBPWriteAggregateRead @@ -133,3 +137,5 @@ gtest_add_tests(TARGET TestBPWriteMemorySelectionRead ${extra_test_args} WORKING gtest_add_tests(TARGET TestBPWriteReadLocalVariables ${extra_test_args} WORKING_DIRECTORY ${BP4_DIR} EXTRA_ARGS "BP4" TEST_SUFFIX _BP4) gtest_add_tests(TARGET TestBPWriteReadLocalVariablesSel ${extra_test_args} WORKING_DIRECTORY ${BP4_DIR} EXTRA_ARGS "BP4" TEST_SUFFIX _BP4) gtest_add_tests(TARGET TestBPChangingShape ${extra_test_args} WORKING_DIRECTORY ${BP4_DIR} EXTRA_ARGS "BP4" TEST_SUFFIX _BP4) + +gtest_add_tests(TARGET TestBPWriteReadBlockInfo ${extra_test_args}) diff --git a/testing/adios2/engine/bp/TestBPWriteReadBlockInfo.cpp b/testing/adios2/engine/bp/TestBPWriteReadBlockInfo.cpp new file mode 100644 index 0000000000..9cf986988e --- /dev/null +++ b/testing/adios2/engine/bp/TestBPWriteReadBlockInfo.cpp @@ -0,0 +1,582 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ +#include +#include + +#include +#include //std::iota +#include + +#include + +#include + +#include "../SmallTestData.h" + +class BPWriteReadBlockInfo : public ::testing::Test +{ +public: + BPWriteReadBlockInfo() = default; + + SmallTestData m_TestData; +}; + +namespace +{ + +template +void CheckAllStepsBlockInfo1D( + const std::vector::Info>> + &allStepsBlocksInfo, + const size_t NSteps, const size_t Nx) +{ + EXPECT_EQ(allStepsBlocksInfo.size(), NSteps); + + for (size_t s = 0; s < allStepsBlocksInfo.size(); ++s) + { + for (size_t b = 0; b < allStepsBlocksInfo[s].size(); ++b) + { + EXPECT_EQ(allStepsBlocksInfo[s][b].BlockID, b); + EXPECT_EQ(allStepsBlocksInfo[s][b].Start[0], b * Nx); + EXPECT_EQ(allStepsBlocksInfo[s][b].Count[0], Nx); + EXPECT_EQ(allStepsBlocksInfo[s][b].Step, s); + } + } +} + +template +void CheckAllStepsBlockInfo2D( + const std::vector::Info>> + &allStepsBlocksInfo, + const size_t NSteps, const size_t Nx, const size_t Ny) +{ + EXPECT_EQ(allStepsBlocksInfo.size(), NSteps); + + for (size_t s = 0; s < allStepsBlocksInfo.size(); ++s) + { + for (size_t b = 0; b < allStepsBlocksInfo[s].size(); ++b) + { + EXPECT_EQ(allStepsBlocksInfo[s][b].BlockID, b); + EXPECT_EQ(allStepsBlocksInfo[s][b].Start[0], 0); + EXPECT_EQ(allStepsBlocksInfo[s][b].Start[1], b * Nx); + EXPECT_EQ(allStepsBlocksInfo[s][b].Count[0], Ny); + EXPECT_EQ(allStepsBlocksInfo[s][b].Count[1], Nx); + EXPECT_EQ(allStepsBlocksInfo[s][b].Step, s); + } + } +} +} + +TEST_F(BPWriteReadBlockInfo, BPWriteReadBlockInfo1D8) +{ + // Each process would write a 1x8 array and all processes would + // form a mpiSize * Nx 1D array + const std::string fname("BPWriteReadblockInfo1D8.bp"); + + int mpiRank = 0, mpiSize = 1; + // Number of rows + const size_t Nx = 8; + + // Number of steps + const size_t NSteps = 3; + +#ifdef ADIOS2_HAVE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + +// Write test data using BP + +#ifdef ADIOS2_HAVE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); +#else + adios2::ADIOS adios(true); +#endif + { + adios2::IO io = adios.DeclareIO("TestIO"); + + const adios2::Dims shape{static_cast(Nx * mpiSize)}; + const adios2::Dims start{static_cast(Nx * mpiRank)}; + const adios2::Dims count{Nx}; + + auto var_iString = io.DefineVariable("iString"); + auto var_i8 = io.DefineVariable("i8", shape, start, count); + auto var_i16 = io.DefineVariable("i16", shape, start, count); + auto var_i32 = io.DefineVariable("i32", shape, start, count); + auto var_i64 = io.DefineVariable("i64", shape, start, count); + auto var_u8 = io.DefineVariable("u8", shape, start, count); + auto var_u16 = io.DefineVariable("u16", shape, start, count); + auto var_u32 = io.DefineVariable("u32", shape, start, count); + auto var_u64 = io.DefineVariable("u64", shape, start, count); + auto var_r32 = io.DefineVariable("r32", shape, start, count); + auto var_r64 = io.DefineVariable("r64", shape, start, count); + auto var_cr32 = + io.DefineVariable>("cr32", shape, start, count); + auto var_cr64 = io.DefineVariable>("cr64", shape, + start, count); + + adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write); + + for (size_t step = 0; step < NSteps; ++step) + { + // Generate test data for each process uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast(step), mpiRank, mpiSize); + + bpWriter.BeginStep(); + + bpWriter.Put(var_iString, currentTestData.S1); + bpWriter.Put(var_i8, currentTestData.I8.data()); + bpWriter.Put(var_i16, currentTestData.I16.data()); + bpWriter.Put(var_i32, currentTestData.I32.data()); + bpWriter.Put(var_i64, currentTestData.I64.data()); + bpWriter.Put(var_u8, currentTestData.U8.data()); + bpWriter.Put(var_u16, currentTestData.U16.data()); + bpWriter.Put(var_u32, currentTestData.U32.data()); + bpWriter.Put(var_u64, currentTestData.U64.data()); + bpWriter.Put(var_r32, currentTestData.R32.data()); + bpWriter.Put(var_r64, currentTestData.R64.data()); + bpWriter.Put(var_cr32, currentTestData.CR32.data()); + bpWriter.Put(var_cr64, currentTestData.CR64.data()); + bpWriter.EndStep(); + } + + bpWriter.Close(); + } + + { + adios2::IO io = adios.DeclareIO("ReadIO"); + + adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read); + + auto var_iString = io.InquireVariable("iString"); + auto var_i8 = io.InquireVariable("i8"); + auto var_i16 = io.InquireVariable("i16"); + auto var_i32 = io.InquireVariable("i32"); + auto var_i64 = io.InquireVariable("i64"); + auto var_u8 = io.InquireVariable("u8"); + auto var_u16 = io.InquireVariable("u16"); + auto var_u32 = io.InquireVariable("u32"); + auto var_u64 = io.InquireVariable("u64"); + auto var_r32 = io.InquireVariable("r32"); + auto var_r64 = io.InquireVariable("r64"); + auto var_cr32 = io.InquireVariable>("cr32"); + auto var_cr64 = io.InquireVariable>("cr64"); + + const std::vector::Info>> + allStepsBlocksInfoI8 = var_i8.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoI16 = var_i16.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoI32 = var_i32.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoI64 = var_i64.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU8 = var_u8.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU16 = var_u16.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU32 = var_u32.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU64 = var_u64.AllStepsBlocksInfo(); + + const std::vector::Info>> + allStepsBlocksInfoR32 = var_r32.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoR64 = var_r64.AllStepsBlocksInfo(); + + const std::vector< + std::vector>::Info>> + allStepsBlocksInfoCR32 = var_cr32.AllStepsBlocksInfo(); + const std::vector< + std::vector>::Info>> + allStepsBlocksInfoCR64 = var_cr64.AllStepsBlocksInfo(); + + EXPECT_EQ(allStepsBlocksInfoI8.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoI16.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoI32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoI64.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU8.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU16.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU64.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoR32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoR64.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoCR32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoCR64.size(), NSteps); + + CheckAllStepsBlockInfo1D(allStepsBlocksInfoI8, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoI16, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoI32, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoI64, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoU8, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoU16, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoU32, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoU64, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoR32, NSteps, Nx); + CheckAllStepsBlockInfo1D(allStepsBlocksInfoR64, NSteps, Nx); + CheckAllStepsBlockInfo1D>(allStepsBlocksInfoCR32, + NSteps, Nx); + CheckAllStepsBlockInfo1D>(allStepsBlocksInfoCR64, + NSteps, Nx); + + // TODO: other types + + SmallTestData testData; + + std::string IString; + std::array I8; + std::array I16; + std::array I32; + std::array I64; + std::array U8; + std::array U16; + std::array U32; + std::array U64; + std::array R32; + std::array R64; + + const adios2::Dims start{mpiRank * Nx}; + const adios2::Dims count{Nx}; + + const adios2::Box sel(start, count); + + var_i8.SetSelection(sel); + var_i16.SetSelection(sel); + var_i32.SetSelection(sel); + var_i64.SetSelection(sel); + + var_u8.SetSelection(sel); + var_u16.SetSelection(sel); + var_u32.SetSelection(sel); + var_u64.SetSelection(sel); + + var_r32.SetSelection(sel); + var_r64.SetSelection(sel); + + for (size_t t = 0; t < NSteps; ++t) + { + var_i8.SetStepSelection({t, 1}); + var_i16.SetStepSelection({t, 1}); + var_i32.SetStepSelection({t, 1}); + var_i64.SetStepSelection({t, 1}); + + var_u8.SetStepSelection({t, 1}); + var_u16.SetStepSelection({t, 1}); + var_u32.SetStepSelection({t, 1}); + var_u64.SetStepSelection({t, 1}); + + var_r32.SetStepSelection({t, 1}); + var_r64.SetStepSelection({t, 1}); + + // Generate test data for each rank uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast(t), mpiRank, mpiSize); + + bpReader.Get(var_iString, IString); + + bpReader.Get(var_i8, I8.data()); + bpReader.Get(var_i16, I16.data()); + bpReader.Get(var_i32, I32.data()); + bpReader.Get(var_i64, I64.data()); + + bpReader.Get(var_u8, U8.data()); + bpReader.Get(var_u16, U16.data()); + bpReader.Get(var_u32, U32.data()); + bpReader.Get(var_u64, U64.data()); + + bpReader.Get(var_r32, R32.data()); + bpReader.Get(var_r64, R64.data()); + + bpReader.PerformGets(); + + EXPECT_EQ(IString, currentTestData.S1); + + for (size_t i = 0; i < Nx; ++i) + { + std::stringstream ss; + ss << "t=" << t << " i=" << i << " rank=" << mpiRank; + std::string msg = ss.str(); + + EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg; + EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg; + EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg; + EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg; + EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg; + EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg; + EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg; + EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg; + EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg; + EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg; + } + } + bpReader.Close(); + } +} + +TEST_F(BPWriteReadBlockInfo, BPWriteReadBlockInfo2D2x4) +{ + const std::string fname("BPWriteReadBlockInfo2D2x4.bp"); + + int mpiRank = 0, mpiSize = 1; + // Number of rows + const std::size_t Nx = 4; + + // Number of rows + const std::size_t Ny = 2; + + // Number of steps + const std::size_t NSteps = 3; + +#ifdef ADIOS2_HAVE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + +// Write test data using ADIOS2 + +#ifdef ADIOS2_HAVE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); +#else + adios2::ADIOS adios(true); +#endif + { + adios2::IO io = adios.DeclareIO("TestIO"); + + const adios2::Dims shape{Ny, static_cast(Nx * mpiSize)}; + const adios2::Dims start{0, static_cast(mpiRank * Nx)}; + const adios2::Dims count{Ny, Nx}; + + auto var_iString = io.DefineVariable("iString"); + auto var_i8 = io.DefineVariable("i8", shape, start, count); + auto var_i16 = io.DefineVariable("i16", shape, start, count); + auto var_i32 = io.DefineVariable("i32", shape, start, count); + auto var_i64 = io.DefineVariable("i64", shape, start, count); + auto var_u8 = io.DefineVariable("u8", shape, start, count); + auto var_u16 = io.DefineVariable("u16", shape, start, count); + auto var_u32 = io.DefineVariable("u32", shape, start, count); + auto var_u64 = io.DefineVariable("u64", shape, start, count); + auto var_r32 = io.DefineVariable("r32", shape, start, count); + auto var_r64 = io.DefineVariable("r64", shape, start, count); + auto var_cr32 = + io.DefineVariable>("cr32", shape, start, count); + auto var_cr64 = io.DefineVariable>("cr64", shape, + start, count); + + adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write); + + for (size_t step = 0; step < NSteps; ++step) + { + // Generate test data for each process uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast(step), mpiRank, mpiSize); + + bpWriter.BeginStep(); + bpWriter.Put(var_iString, currentTestData.S1); + bpWriter.Put(var_i8, currentTestData.I8.data()); + bpWriter.Put(var_i16, currentTestData.I16.data()); + bpWriter.Put(var_i32, currentTestData.I32.data()); + bpWriter.Put(var_i64, currentTestData.I64.data()); + bpWriter.Put(var_u8, currentTestData.U8.data()); + bpWriter.Put(var_u16, currentTestData.U16.data()); + bpWriter.Put(var_u32, currentTestData.U32.data()); + bpWriter.Put(var_u64, currentTestData.U64.data()); + bpWriter.Put(var_r32, currentTestData.R32.data()); + bpWriter.Put(var_r64, currentTestData.R64.data()); + bpWriter.Put(var_cr32, currentTestData.CR32.data()); + bpWriter.Put(var_cr64, currentTestData.CR64.data()); + bpWriter.EndStep(); + } + + // Close the file + bpWriter.Close(); + } + + { + adios2::IO io = adios.DeclareIO("ReadIO"); + + adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read); + + auto var_iString = io.InquireVariable("iString"); + auto var_i8 = io.InquireVariable("i8"); + auto var_i16 = io.InquireVariable("i16"); + auto var_i32 = io.InquireVariable("i32"); + auto var_i64 = io.InquireVariable("i64"); + auto var_u8 = io.InquireVariable("u8"); + auto var_u16 = io.InquireVariable("u16"); + auto var_u32 = io.InquireVariable("u32"); + auto var_u64 = io.InquireVariable("u64"); + auto var_r32 = io.InquireVariable("r32"); + auto var_r64 = io.InquireVariable("r64"); + auto var_cr32 = io.InquireVariable>("cr32"); + auto var_cr64 = io.InquireVariable>("cr64"); + + const std::vector::Info>> + allStepsBlocksInfoI8 = var_i8.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoI16 = var_i16.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoI32 = var_i32.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoI64 = var_i64.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU8 = var_u8.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU16 = var_u16.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU32 = var_u32.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoU64 = var_u64.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoR32 = var_r32.AllStepsBlocksInfo(); + const std::vector::Info>> + allStepsBlocksInfoR64 = var_r64.AllStepsBlocksInfo(); + const std::vector< + std::vector>::Info>> + allStepsBlocksInfoCR32 = var_cr32.AllStepsBlocksInfo(); + const std::vector< + std::vector>::Info>> + allStepsBlocksInfoCR64 = var_cr64.AllStepsBlocksInfo(); + + EXPECT_EQ(allStepsBlocksInfoI8.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoI16.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoI32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoI64.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU8.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU16.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoU64.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoR32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoR64.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoCR32.size(), NSteps); + EXPECT_EQ(allStepsBlocksInfoCR64.size(), NSteps); + + CheckAllStepsBlockInfo2D(allStepsBlocksInfoI8, NSteps, Nx, Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoI16, NSteps, Nx, + Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoI32, NSteps, Nx, + Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoI64, NSteps, Nx, + Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoU8, NSteps, Nx, Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoU16, NSteps, Nx, + Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoU32, NSteps, Nx, + Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoU64, NSteps, Nx, + Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoR32, NSteps, Nx, Ny); + CheckAllStepsBlockInfo2D(allStepsBlocksInfoR64, NSteps, Nx, Ny); + CheckAllStepsBlockInfo2D>(allStepsBlocksInfoCR32, + NSteps, Nx, Ny); + CheckAllStepsBlockInfo2D>(allStepsBlocksInfoCR64, + NSteps, Nx, Ny); + + std::string IString; + std::array I8; + std::array I16; + std::array I32; + std::array I64; + std::array U8; + std::array U16; + std::array U32; + std::array U64; + std::array R32; + std::array R64; + + const adios2::Dims start{0, static_cast(mpiRank * Nx)}; + const adios2::Dims count{Ny, Nx}; + + const adios2::Box sel(start, count); + + var_i8.SetSelection(sel); + var_i16.SetSelection(sel); + var_i32.SetSelection(sel); + var_i64.SetSelection(sel); + + var_u8.SetSelection(sel); + var_u16.SetSelection(sel); + var_u32.SetSelection(sel); + var_u64.SetSelection(sel); + + var_r32.SetSelection(sel); + var_r64.SetSelection(sel); + + for (size_t t = 0; t < NSteps; ++t) + { + var_i8.SetStepSelection({t, 1}); + var_i16.SetStepSelection({t, 1}); + var_i32.SetStepSelection({t, 1}); + var_i64.SetStepSelection({t, 1}); + + var_u8.SetStepSelection({t, 1}); + var_u16.SetStepSelection({t, 1}); + var_u32.SetStepSelection({t, 1}); + var_u64.SetStepSelection({t, 1}); + + var_r32.SetStepSelection({t, 1}); + var_r64.SetStepSelection({t, 1}); + + bpReader.Get(var_iString, IString); + + bpReader.Get(var_i8, I8.data()); + bpReader.Get(var_i16, I16.data()); + bpReader.Get(var_i32, I32.data()); + bpReader.Get(var_i64, I64.data()); + + bpReader.Get(var_u8, U8.data()); + bpReader.Get(var_u16, U16.data()); + bpReader.Get(var_u32, U32.data()); + bpReader.Get(var_u64, U64.data()); + + bpReader.Get(var_r32, R32.data()); + bpReader.Get(var_r64, R64.data()); + + bpReader.PerformGets(); + + // Generate test data for each rank uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast(t), mpiRank, mpiSize); + + EXPECT_EQ(IString, currentTestData.S1); + + for (size_t i = 0; i < Nx * Ny; ++i) + { + std::stringstream ss; + ss << "t=" << t << " i=" << i << " rank=" << mpiRank; + std::string msg = ss.str(); + + EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg; + EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg; + EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg; + EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg; + EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg; + EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg; + EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg; + EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg; + EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg; + EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg; + } + } + bpReader.Close(); + } +} + +int main(int argc, char **argv) +{ +#ifdef ADIOS2_HAVE_MPI + MPI_Init(nullptr, nullptr); +#endif + + int result; + ::testing::InitGoogleTest(&argc, argv); + result = RUN_ALL_TESTS(); + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return result; +}