diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h index e482a8855a575f8ece7421562dc0ddb18f766f5e..2850171ef78e9cb36445144c3b1658d5eeb52349 100644 --- a/source/adios2/ADIOSMacros.h +++ b/source/adios2/ADIOSMacros.h @@ -8,6 +8,8 @@ #ifndef ADIOS2_ADIOSMACROS_H #define ADIOS2_ADIOSMACROS_H +#include <string> + #include "adios2/ADIOSTypes.h" // The ADIOS_FOREACH_TYPE_1ARG macro assumes the given argument is a macro which // takes a single argument that is a type and then inserts the given MACRO for @@ -51,6 +53,8 @@ MACRO(unsigned int) \ MACRO(long int) \ MACRO(unsigned long int) \ + MACRO(long long int) \ + MACRO(unsigned long long int) \ MACRO(float) \ MACRO(double) @@ -64,4 +68,20 @@ MACRO(float) \ MACRO(double) +#define ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(MACRO) \ + MACRO(std::string) \ + MACRO(char) \ + MACRO(unsigned char) \ + MACRO(short) \ + MACRO(unsigned short) \ + MACRO(int) \ + MACRO(unsigned int) \ + MACRO(long int) \ + MACRO(unsigned long int) \ + MACRO(long long int) \ + MACRO(unsigned long long int) \ + MACRO(float) \ + MACRO(double) \ + MACRO(long double) + #endif /* ADIOS2_ADIOSMACROS_H */ diff --git a/source/adios2/CMakeLists.txt b/source/adios2/CMakeLists.txt index 3bd8861811fcdb0cf4812ccd591e53c957331c4e..de3e5c2b4087496ae1696eba0eec46121e095a22 100644 --- a/source/adios2/CMakeLists.txt +++ b/source/adios2/CMakeLists.txt @@ -4,6 +4,8 @@ #------------------------------------------------------------------------------# add_library(adios2 + core/Attribute.cpp core/Attribute.tcc + core/AttributeBase.cpp core/ADIOS.cpp core/Engine.cpp core/IO.cpp core/IO.tcc diff --git a/source/adios2/core/Attribute.cpp b/source/adios2/core/Attribute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e473101dcaec65e405c397f8e6122526d19a8f3 --- /dev/null +++ b/source/adios2/core/Attribute.cpp @@ -0,0 +1,17 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Attribute.cpp : needed for template separation using Attribute.tcc + * + * Created on: Aug 3, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "Attribute.h" +#include "Attribute.tcc" + +namespace adios2 +{ + +} // end namespace adios2 diff --git a/source/adios2/core/Attribute.h b/source/adios2/core/Attribute.h new file mode 100644 index 0000000000000000000000000000000000000000..bddd3c8087a9a22fc86b6a283215c9e8cb4eea9e --- /dev/null +++ b/source/adios2/core/Attribute.h @@ -0,0 +1,48 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Attribute.h : template class that defines typed attributes + * + * Created on: Aug 1, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_CORE_ATTRIBUTE_H_ +#define ADIOS2_CORE_ATTRIBUTE_H_ + +#include "adios2/core/AttributeBase.h" + +namespace adios2 +{ +/** @brief Attributes provide complementary information to IO Variables*/ +template <class T> +class Attribute : public AttributeBase +{ + +public: + const T *m_DataArray = nullptr; + T m_DataValue; + + /** + * Data array constructor + * @param name + * @param data + * @param elements + */ + Attribute<T>(const std::string &name, const T *data, const size_t elements); + + /** + * Single value constructor + * @param name + * @param data + * @param elements + */ + Attribute<T>(const std::string &name, const T &data); + + ~Attribute<T>() = default; +}; + +} // end namespace adios2 + +#endif /* ADIOS2_CORE_ATTRIBUTE_H_ */ diff --git a/source/adios2/core/Attribute.tcc b/source/adios2/core/Attribute.tcc new file mode 100644 index 0000000000000000000000000000000000000000..6e771fc15591229787d44f7256aa9cef42419266 --- /dev/null +++ b/source/adios2/core/Attribute.tcc @@ -0,0 +1,43 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Attribute.tcc + * + * Created on: Aug 1, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_CORE_ATTRIBUTE_TCC_ +#define ADIOS2_CORE_ATTRIBUTE_TCC_ + +#include "Attribute.h" + +#include "adios2/ADIOSMacros.h" +#include "adios2/helper/adiosFunctions.h" //GetType<T> + +namespace adios2 +{ + +#define declare_type(T) \ + \ + template <> \ + Attribute<T>::Attribute(const std::string &name, const T *array, \ + const size_t elements) \ + : AttributeBase(name, GetType<T>(), elements), m_DataArray(array), \ + m_DataValue() \ + { \ + } \ + \ + template <> \ + Attribute<T>::Attribute(const std::string &name, const T &value) \ + : AttributeBase(name, GetType<T>(), 1), m_DataValue(value) \ + { \ + } + +ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_type) +#undef declare_type + +} // end namespace adios2 + +#endif /* ADIOS2_CORE_ATTRIBUTE_TCC_ */ diff --git a/source/adios2/core/AttributeBase.cpp b/source/adios2/core/AttributeBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..498e7fbfc75a05549780daeb590bfedae204d407 --- /dev/null +++ b/source/adios2/core/AttributeBase.cpp @@ -0,0 +1,22 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * AttributeBase.cpp + * + * Created on: Aug 1, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "AttributeBase.h" + +namespace adios2 +{ + +AttributeBase::AttributeBase(const std::string &name, const std::string type, + const size_t elements) +: m_Name(name), m_Type(type), m_Elements(elements) +{ +} + +} // end namespace adios2 diff --git a/source/adios2/core/AttributeBase.h b/source/adios2/core/AttributeBase.h new file mode 100644 index 0000000000000000000000000000000000000000..a1a6b7c5ad7e8ca1ccef596154e2c4af8c0a5030 --- /dev/null +++ b/source/adios2/core/AttributeBase.h @@ -0,0 +1,46 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * AttributeBase.h : base class for Attribute<T> class, allows RTTI at read time + * + * Created on: Aug 1, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_CORE_ATTRIBUTEBASE_H_ +#define ADIOS2_CORE_ATTRIBUTEBASE_H_ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <string> +/// \endcond + +#include "adios2/ADIOSConfig.h" +#include "adios2/ADIOSTypes.h" + +namespace adios2 +{ + +class AttributeBase +{ + +public: + const std::string m_Name; + const std::string m_Type; + const size_t m_Elements; + + /** + * Unique constructor used by Attribute<T> derived class + * @param name + * @param type + * @param elements + */ + AttributeBase(const std::string &name, const std::string type, + const size_t elements); + + virtual ~AttributeBase() = default; +}; + +} // end namespace adios2 + +#endif /* ADIOS2_CORE_ATTRIBUTEBASE_H_ */ diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index 492aa0d84277b1c3e44d4ac85f1e6dae5daf71e6..1dee549c8f6ae855d818460b11cb5773a24c68fe 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -108,7 +108,7 @@ IO::DefineVariableCompound(const std::string &name, const size_t sizeOfVariable, VariableCompound &IO::GetVariableCompound(const std::string &name) { - return m_Compound.at(GetVariableIndex(name)); + return m_Compound.at(GetMapIndex(name, m_Variables, "VariableCompound")); } std::string IO::GetVariableType(const std::string &name) const @@ -281,30 +281,42 @@ std::shared_ptr<Engine> IO::Open(const std::string &name, } // PRIVATE Functions -unsigned int IO::GetVariableIndex(const std::string &name) const +unsigned int IO::GetMapIndex(const std::string &name, const DataMap &dataMap, + const std::string hint) const { + auto itDataMap = dataMap.find(name); + if (m_DebugMode) { - if (!VariableExists(name)) + if (IsEnd(itDataMap, dataMap)) { - throw std::invalid_argument( - "ERROR: variable " + m_Name + - " wasn't created with DefineVariable, in call to IO object " + - m_Name + " GetVariable\n"); + throw std::invalid_argument("ERROR: " + hint + " " + m_Name + + " wasn't created with Define " + hint + + ", in call to IO object " + m_Name + + " Get" + hint + "\n"); } } - auto itVariable = m_Variables.find(name); - return itVariable->second.second; + return itDataMap->second.second; +} + +void IO::CheckAttributeCommon(const std::string &name) const +{ + auto itAttribute = m_Attributes.find(name); + if (!IsEnd(itAttribute, m_Attributes)) + { + throw std::invalid_argument("ERROR: attribute " + name + + " exists in IO object " + m_Name + + ", in call to DefineAttribute\n"); + } } -bool IO::VariableExists(const std::string &name) const +bool IO::IsEnd(DataMap::const_iterator itDataMap, const DataMap &dataMap) const { - bool exists = false; - if (m_Variables.count(name) == 1) + if (itDataMap == dataMap.end()) { - exists = true; + return true; } - return exists; + return false; } void IO::CheckTransportType(const std::string type) const @@ -321,11 +333,22 @@ void IO::CheckTransportType(const std::string type) const // Explicitly instantiate the necessary public template implementations #define define_template_instantiation(T) \ - template Variable<T> &IO::DefineVariable<T>( \ - const std::string &, const Dims, const Dims, const Dims, const bool); \ + template Variable<T> &IO::DefineVariable<T>(const std::string &, \ + const Dims &, const Dims &, \ + const Dims &, const bool); \ template Variable<T> &IO::GetVariable<T>(const std::string &); ADIOS2_FOREACH_TYPE_1ARG(define_template_instantiation) #undef define_template_instatiation +#define declare_template_instantiation(T) \ + template Attribute<T> &IO::DefineAttribute<T>(const std::string &, \ + const T *, const size_t); \ + template Attribute<T> &IO::DefineAttribute<T>(const std::string &, \ + const T &); \ + template Attribute<T> &IO::GetAttribute(const std::string &); + +ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + } // end namespace adios diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index fbd8bb91cf29971356de8a8d471a1c45d658c733..f0a7b453633131f6077cf03b79505c7112e1dd65 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -24,12 +24,16 @@ #include "adios2/ADIOSMPICommOnly.h" #include "adios2/ADIOSMacros.h" #include "adios2/ADIOSTypes.h" +#include "adios2/core/Attribute.h" #include "adios2/core/Variable.h" #include "adios2/core/VariableCompound.h" namespace adios2 { +/** used for Variables and Attributes */ +using DataMap = std::map<std::string, std::pair<std::string, unsigned int>>; + // forward declaration needed as IO is passed to Engine derived // classes class Engine; @@ -134,8 +138,8 @@ public: * @return reference to Variable object */ template <class T> - Variable<T> &DefineVariable(const std::string &name, const Dims shape = {}, - const Dims start = {}, const Dims count = {}, + Variable<T> &DefineVariable(const std::string &name, const Dims &shape = {}, + const Dims &start = {}, const Dims &count = {}, const bool constantShape = false); /** @@ -151,11 +155,12 @@ public: * @return reference to Variable object */ template <class T> - VariableCompound & - DefineVariableCompound(const std::string &name, const Dims shape = Dims{}, - const Dims start = Dims{}, const Dims count = Dims{}, - const bool constantDims = false); - + VariableCompound &DefineVariableCompound(const std::string &name, + const Dims &shape = Dims{}, + const Dims &start = Dims{}, + const Dims &count = Dims{}, + const bool constantShape = false); + VariableCompound &DefineVariableCompound(const std::string &name, const size_t sizeOfVariable, const Dims &shape = Dims{}, @@ -163,6 +168,26 @@ public: const Dims &count = Dims{}, const bool constantDims = false); + /** + * Define attribute from contiguous data array owned by an application + * @param name must be unique for the IO object + * @param array pointer to user data + * @param elements number of data elements + * @return reference to internal Attribute + */ + template <class T> + Attribute<T> &DefineAttribute(const std::string &name, const T *array, + const size_t elements); + + /** + * Define attribute from a single variable making a copy + * @param name must be unique for the IO object + * @param value single data value + * @return reference to internal Attribute + */ + template <class T> + Attribute<T> &DefineAttribute(const std::string &name, const T &value); + /** * Removes an existing Variable previously created with DefineVariable or * DefineVariableCompound @@ -189,6 +214,15 @@ public: */ VariableCompound &GetVariableCompound(const std::string &name); + /** + * Gets an existing attribute of primitive type by name + * @param name of attribute to be retrieved + * @return reference to an existing attribute created with DefineAttribute + * throws an exception if Attribute is not found + */ + template <class T> + Attribute<T> &GetAttribute(const std::string &name); + /** * Get the type if variable (by name id) exists * @param name input id @@ -248,7 +282,7 @@ private: * pair.second = index in fixed size map (e.g. m_Int8, m_Double) * </pre> */ - std::map<std::string, std::pair<std::string, unsigned int>> m_Variables; + DataMap m_Variables; /** Variable containers based on fixed-size type */ std::map<unsigned int, Variable<char>> m_Char; @@ -270,25 +304,63 @@ private: std::map<unsigned int, Variable<cldouble>> m_CLDouble; std::map<unsigned int, VariableCompound> m_Compound; - std::map<std::string, std::string> m_AttributesString; - std::map<std::string, double> m_AttributesNumeric; - - std::set<std::string> m_EngineNames; - /** Gets the internal reference to a variable map for type T * This function is specialized in IO.tcc */ template <class T> std::map<unsigned int, Variable<T>> &GetVariableMap(); - /** Gets the internal index in variable map for an existing variable */ - unsigned int GetVariableIndex(const std::string &name) const; + /** + * Map holding attribute identifiers + * <pre> + * key: unique attribute name, + * value: pair.first = type as string GetType<T> from + * helper/adiosTemplates.h + * pair.second = index in fixed size map (e.g. m_Int8, m_Double) + * </pre> + */ + DataMap m_Attributes; + + std::map<unsigned int, Attribute<std::string>> m_StringA; + std::map<unsigned int, Attribute<char>> m_CharA; + std::map<unsigned int, Attribute<unsigned char>> m_UCharA; + std::map<unsigned int, Attribute<short>> m_ShortA; + std::map<unsigned int, Attribute<unsigned short>> m_UShortA; + std::map<unsigned int, Attribute<int>> m_IntA; + std::map<unsigned int, Attribute<unsigned int>> m_UIntA; + std::map<unsigned int, Attribute<long int>> m_LIntA; + std::map<unsigned int, Attribute<unsigned long int>> m_ULIntA; + std::map<unsigned int, Attribute<long long int>> m_LLIntA; + std::map<unsigned int, Attribute<unsigned long long int>> m_ULLIntA; + std::map<unsigned int, Attribute<float>> m_FloatA; + std::map<unsigned int, Attribute<double>> m_DoubleA; + std::map<unsigned int, Attribute<long double>> m_LDoubleA; + + template <class T> + std::map<unsigned int, Attribute<T>> &GetAttributeMap(); /** - * Checks if variable exists by checking its name - * @param name unique variable name to be checked against existing variables - * @return true: variable name exists, false: variable name doesn't exist + * Gets map index for Variables or Attributes + * @param name + * @param dataMap m_Variables or m_Attributes + * @param hint "Variable", "Attribute", or "VariableCompound" + * @return index in type map */ - bool VariableExists(const std::string &name) const; + unsigned int GetMapIndex(const std::string &name, const DataMap &dataMap, + const std::string hint) const; + + /** Checks if attribute exists, called from DefineAttribute different + * signatures */ + void CheckAttributeCommon(const std::string &name) const; + + std::set<std::string> m_EngineNames; + + /** + * Checks if iterator points to end. Used for Variables and Attributes. + * @param itDataMap iterator to be tested + * @param dataMap map + * @return true: itDataMap == dataMap.end(), false otherwise + */ + bool IsEnd(DataMap::const_iterator itDataMap, const DataMap &dataMap) const; void CheckTransportType(const std::string type) const; }; @@ -296,14 +368,24 @@ private: // Explicit declaration of the public template methods #define declare_template_instantiation(T) \ extern template Variable<T> &IO::DefineVariable<T>( \ - const std::string &name, const Dims, const Dims, const Dims, \ - const bool constantShape); \ + const std::string &, const Dims &, const Dims &, const Dims &, \ + const bool); \ extern template Variable<T> &IO::GetVariable<T>(const std::string &name); ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) #undef declare_template_instantiation -} // end namespace adios +#define declare_template_instantiation(T) \ + extern template Attribute<T> &IO::DefineAttribute<T>( \ + const std::string &, const T *, const size_t); \ + extern template Attribute<T> &IO::DefineAttribute<T>(const std::string &, \ + const T &); \ + extern template Attribute<T> &IO::GetAttribute(const std::string &); + +ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + +} // end namespace adios2 #include "adios2/core/IO.inl" diff --git a/source/adios2/core/IO.inl b/source/adios2/core/IO.inl index 73c05a1b2a0e794720182a9e059297258e068f31..4a89c759c71952c545eb8f49184d37bc49880202 100644 --- a/source/adios2/core/IO.inl +++ b/source/adios2/core/IO.inl @@ -2,7 +2,8 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * IO.inl inline template functions implementation of IO class + * IO.inl inline template functions implementation of IO class. VariableCompound + * can take any type so must be inlined as type is not known a priori. * * Created on: May 15, 2017 * Author: William F Godoy godoywf@ornl.gov @@ -21,8 +22,8 @@ namespace adios2 template <class T> VariableCompound &IO::DefineVariableCompound(const std::string &name, - const Dims shape, const Dims start, - const Dims count, + const Dims &shape, const Dims &start, + const Dims &count, const bool constantDims) { return DefineVariableCompound(name, sizeof(T), shape, start, count, diff --git a/source/adios2/core/IO.tcc b/source/adios2/core/IO.tcc index 6f892ee6d1c38f9525029559514e96661ffd11b2..eb11fc87444b1b788368990f6da0faa35146b7d3 100644 --- a/source/adios2/core/IO.tcc +++ b/source/adios2/core/IO.tcc @@ -26,13 +26,14 @@ namespace adios2 { template <class T> -Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape, - const Dims start, const Dims count, - const bool constantDims) +Variable<T> &IO::DefineVariable(const std::string &name, const Dims &shape, + const Dims &start, const Dims &count, + const bool constantShape) { if (m_DebugMode) { - if (VariableExists(name)) + auto itVariable = m_Variables.find(name); + if (!IsEnd(itVariable, m_Variables)) { throw std::invalid_argument("ERROR: variable " + name + " exists in IO object " + m_Name + @@ -41,7 +42,8 @@ Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape, } auto &variableMap = GetVariableMap<T>(); - const unsigned int size = variableMap.size(); + const unsigned int size = + static_cast<const unsigned int>(variableMap.size()); auto itVariablePair = variableMap.emplace(size, Variable<T>(name, shape, start, count, constantDims, m_DebugMode)); @@ -53,7 +55,53 @@ Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape, template <class T> Variable<T> &IO::GetVariable(const std::string &name) { - return GetVariableMap<T>().at(GetVariableIndex(name)); + return GetVariableMap<T>().at(GetMapIndex(name, m_Variables, "Variable")); +} + +template <class T> +Attribute<T> &IO::DefineAttribute(const std::string &name, const T &value) +{ + if (m_DebugMode) + { + CheckAttributeCommon(name); + } + + auto &attributeMap = GetAttributeMap<T>(); + const unsigned int size = + static_cast<const unsigned int>(attributeMap.size()); + + auto itAttributePair = + attributeMap.emplace(size, Attribute<T>(name, value)); + m_Attributes.emplace(name, std::make_pair(GetType<T>(), size)); + + return itAttributePair.first->second; +} + +template <class T> +Attribute<T> &IO::DefineAttribute(const std::string &name, const T *array, + const size_t elements) +{ + if (m_DebugMode) + { + CheckAttributeCommon(name); + } + + auto &attributeMap = GetAttributeMap<T>(); + const unsigned int size = + static_cast<const unsigned int>(attributeMap.size()); + + auto itAttributePair = + attributeMap.emplace(size, Attribute<T>(name, array, elements)); + m_Attributes.emplace(name, std::make_pair(GetType<T>(), size)); + + return itAttributePair.first->second; +} + +template <class T> +Attribute<T> &IO::GetAttribute(const std::string &name) +{ + return GetAttributeMap<T>().at( + GetMapIndex(name, m_Attributes, "Attribute")); } // PRIVATE @@ -159,6 +207,91 @@ std::map<unsigned int, Variable<cldouble>> &IO::GetVariableMap() return m_CLDouble; } -} // end namespace adios +// attributes +template <> +std::map<unsigned int, Attribute<std::string>> &IO::GetAttributeMap() +{ + return m_StringA; +} + +template <> +std::map<unsigned int, Attribute<char>> &IO::GetAttributeMap() +{ + return m_CharA; +} + +template <> +std::map<unsigned int, Attribute<unsigned char>> &IO::GetAttributeMap() +{ + return m_UCharA; +} + +template <> +std::map<unsigned int, Attribute<short>> &IO::GetAttributeMap() +{ + return m_ShortA; +} + +template <> +std::map<unsigned int, Attribute<unsigned short>> &IO::GetAttributeMap() +{ + return m_UShortA; +} + +template <> +std::map<unsigned int, Attribute<int>> &IO::GetAttributeMap() +{ + return m_IntA; +} + +template <> +std::map<unsigned int, Attribute<unsigned int>> &IO::GetAttributeMap() +{ + return m_UIntA; +} + +template <> +std::map<unsigned int, Attribute<long int>> &IO::GetAttributeMap() +{ + return m_LIntA; +} + +template <> +std::map<unsigned int, Attribute<unsigned long int>> &IO::GetAttributeMap() +{ + return m_ULIntA; +} + +template <> +std::map<unsigned int, Attribute<long long int>> &IO::GetAttributeMap() +{ + return m_LLIntA; +} + +template <> +std::map<unsigned int, Attribute<unsigned long long int>> &IO::GetAttributeMap() +{ + return m_ULLIntA; +} + +template <> +std::map<unsigned int, Attribute<float>> &IO::GetAttributeMap() +{ + return m_FloatA; +} + +template <> +std::map<unsigned int, Attribute<double>> &IO::GetAttributeMap() +{ + return m_DoubleA; +} + +template <> +std::map<unsigned int, Attribute<long double>> &IO::GetAttributeMap() +{ + return m_LDoubleA; +} + +} // end namespace adios2 #endif /* ADIOS2_CORE_IO_TCC_ */ diff --git a/source/adios2/core/Variable.cpp b/source/adios2/core/Variable.cpp index 55777209f8e5382653e6d185106d1eff596c8d94..86b5e3d165d79ef6da78cd90db00ca49e64ea6fd 100644 --- a/source/adios2/core/Variable.cpp +++ b/source/adios2/core/Variable.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * Variable.cpp needed for template separation using Variable.tcc + * Variable.cpp : needed for template separation using Variable.tcc * * Created on: Jun 8, 2017 * Author: William F Godoy godoywf@ornl.gov @@ -14,4 +14,4 @@ namespace adios2 { -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/core/Variable.h b/source/adios2/core/Variable.h index 8e9705fc166ab4284a733a3b3d34a2cd0958ab8a..dbf5ec2dc00f5754d098f8ef79c8cee44f971b3f 100644 --- a/source/adios2/core/Variable.h +++ b/source/adios2/core/Variable.h @@ -18,8 +18,6 @@ #include <vector> /// \endcond -#include "adios2/ADIOSMacros.h" -#include "adios2/core/Transform.h" #include "adios2/core/VariableBase.h" namespace adios2 @@ -50,15 +48,15 @@ public: * @param constantShape * @param debugMode */ - Variable<T>(const std::string &name, const Dims shape, const Dims start, - const Dims count, const bool constantDims, + Variable<T>(const std::string &name, const Dims &shape, const Dims &start, + const Dims &count, const bool constantShape, const bool debugMode); - virtual ~Variable<T>() = default; + ~Variable<T>() = default; void ApplyTransforms() final; }; -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_CORE_VARIABLE_H_ */ diff --git a/source/adios2/core/Variable.tcc b/source/adios2/core/Variable.tcc index 9c1f888c9eee7fb4e82f92eb397c8fa0f68d6747..d6241f856adfd5512ea87ec53cc392e6f5d2a5f9 100644 --- a/source/adios2/core/Variable.tcc +++ b/source/adios2/core/Variable.tcc @@ -14,7 +14,7 @@ #include "Variable.h" #include "adios2/ADIOSMacros.h" -#include "adios2/helper/adiosFunctions.h" //GetType +#include "adios2/helper/adiosFunctions.h" //GetType<T> namespace adios2 { @@ -22,9 +22,9 @@ namespace adios2 #define declare_type(T) \ \ template <> \ - Variable<T>::Variable(const std::string &name, const Dims shape, \ - const Dims start, const Dims count, \ - const bool constantDims, const bool debugMode) \ + Variable<T>::Variable(const std::string &name, const Dims &shape, \ + const Dims &start, const Dims &count, \ + const bool constantShape, const bool debugMode) \ : VariableBase(name, GetType<T>(), sizeof(T), shape, start, count, \ constantDims, debugMode) \ { \ @@ -38,6 +38,6 @@ namespace adios2 ADIOS2_FOREACH_TYPE_1ARG(declare_type) #undef declare_type -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_CORE_VARIABLE_TCC_ */ diff --git a/source/adios2/core/VariableBase.cpp b/source/adios2/core/VariableBase.cpp index d98f572d15db6b399d008e6d5c4364cbbd29f91c..775944e0a775fb2f0ff635c36b50ec790cdf54f0 100644 --- a/source/adios2/core/VariableBase.cpp +++ b/source/adios2/core/VariableBase.cpp @@ -21,8 +21,8 @@ namespace adios2 { VariableBase::VariableBase(const std::string &name, const std::string type, - const size_t elementSize, const Dims shape, - const Dims start, const Dims count, + const size_t elementSize, const Dims &shape, + const Dims &start, const Dims &count, const bool constantDims, const bool debugMode) : m_Name(name), m_Type(type), m_ElementSize(elementSize), m_Shape(shape), m_Start(start), m_Count(count), m_ConstantDims(constantDims), @@ -41,7 +41,7 @@ size_t VariableBase::TotalSize() const noexcept return GetTotalSize(m_Count); } -void VariableBase::SetSelection(const Dims start, const Dims count) +void VariableBase::SetSelection(const Dims &start, const Dims &count) { if (m_DebugMode) { diff --git a/source/adios2/core/VariableBase.h b/source/adios2/core/VariableBase.h index 61fc093dfd72f5860565edc4eb5da69d5ec72611..f169a3299d8251eda7f6d599e6ec2b042673c15d 100644 --- a/source/adios2/core/VariableBase.h +++ b/source/adios2/core/VariableBase.h @@ -63,8 +63,8 @@ public: unsigned int m_AvailableSteps = 1; VariableBase(const std::string &name, const std::string type, - const size_t elementSize, const Dims shape, const Dims start, - const Dims count, const bool constantShape, + const size_t elementSize, const Dims &shape, const Dims &start, + const Dims &count, const bool constantShape, const bool debugMode); virtual ~VariableBase() = default; @@ -82,7 +82,7 @@ public: size_t TotalSize() const noexcept; /** Set the local dimension and global offset of the variable */ - void SetSelection(const Dims start, const Dims count); + void SetSelection(const Dims &start, const Dims &count); /** Overloaded version of SetSelection using a SelectionBoundingBox */ void SetSelection(const SelectionBoundingBox &selection); diff --git a/source/adios2/helper/adiosType.inl b/source/adios2/helper/adiosType.inl index d0573ce5adf1ac073967415341a554962085e304..b81bb598183f5f11080ef293a61f3ed396366718 100644 --- a/source/adios2/helper/adiosType.inl +++ b/source/adios2/helper/adiosType.inl @@ -27,6 +27,13 @@ inline std::string GetType<void>() noexcept { return "unknown"; } + +template <> +inline std::string GetType<std::string>() noexcept +{ + return "string"; +} + template <> inline std::string GetType<char>() noexcept { diff --git a/testing/adios2/interface/CMakeLists.txt b/testing/adios2/interface/CMakeLists.txt index e68ccfa6187ab17710e4bca93579ede6ded95079..c446f5eef939d5f86583f37b3085fc436be5bbbb 100644 --- a/testing/adios2/interface/CMakeLists.txt +++ b/testing/adios2/interface/CMakeLists.txt @@ -9,5 +9,9 @@ target_link_libraries(TestADIOSInterfaceWrite adios2 gtest gtest_main) add_executable(TestADIOSDefineVariable TestADIOSDefineVariable.cpp) target_link_libraries(TestADIOSDefineVariable adios2 gtest gtest_main) +add_executable(TestADIOSDefineAttribute TestADIOSDefineAttribute.cpp) +target_link_libraries(TestADIOSDefineAttribute adios2 gtest gtest_main) + gtest_add_tests(TARGET TestADIOSInterfaceWrite) -gtest_add_tests(TARGET TestADIOSDefineVariable) \ No newline at end of file +gtest_add_tests(TARGET TestADIOSDefineVariable) +gtest_add_tests(TARGET TestADIOSDefineAttribute) \ No newline at end of file diff --git a/testing/adios2/interface/TestADIOSDefineAttribute.cpp b/testing/adios2/interface/TestADIOSDefineAttribute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e31a439c625b5b9a054cb3e073438c064d44b864 --- /dev/null +++ b/testing/adios2/interface/TestADIOSDefineAttribute.cpp @@ -0,0 +1,591 @@ +#include <cstdint> + +#include <iostream> +#include <stdexcept> + +#include <adios2.h> + +#include <gtest/gtest.h> + +class ADIOSDefineAttributeTest : public ::testing::Test +{ +public: + ADIOSDefineAttributeTest() : adios(true), io(adios.DeclareIO("TestIO")) {} + +protected: + // virtual void SetUp() { } + + // virtual void TearDown() { } + + adios2::ADIOS adios; + adios2::IO &io; +}; + +TEST_F(ADIOSDefineAttributeTest, DefineAttributeNameException) +{ + auto &attributeString1 = + io.DefineAttribute<std::string>("attributeString", "-1"); + + EXPECT_THROW(auto &attributeString2 = + io.DefineAttribute<std::string>("attributeString", "0"), + std::invalid_argument); + + EXPECT_THROW(auto &attributeString2 = + io.GetAttribute<std::string>("NoExistingAttribute"), + std::invalid_argument); + + EXPECT_NO_THROW(auto &attributeString3 = + io.GetAttribute<std::string>("attributeString")); +} + +TEST_F(ADIOSDefineAttributeTest, DefineAttributeTypeByValue) +{ + // Define ADIOS global value + auto &attributeString = + io.DefineAttribute<std::string>("attributeString", "-1"); + auto &attributeChar = io.DefineAttribute<char>("attributeChar", '0'); + auto &attributeUChar = + io.DefineAttribute<unsigned char>("attributeUChar", '1'); + auto &attributeShort = io.DefineAttribute<short>("attributeShort", 2); + auto &attributeUShort = + io.DefineAttribute<unsigned short>("attributeUShort", 3); + auto &attributeInt = io.DefineAttribute<int>("attributeInt", 4); + auto &attributeUInt = io.DefineAttribute<unsigned int>("attributeUInt", 5); + auto &attributeLInt = io.DefineAttribute<long int>("attributeLInt", 6); + auto &attributeULInt = + io.DefineAttribute<unsigned long int>("attributeULInt", 7); + auto &attributeLLInt = + io.DefineAttribute<long long int>("attributeLLInt", 8); + auto &attributeULLInt = + io.DefineAttribute<unsigned long long int>("attributeULLInt", 9); + auto &attributeFloat = io.DefineAttribute<float>("attributeFloat", 10); + auto &attributeDouble = io.DefineAttribute<double>("attributeDouble", 11); + auto &attributeLDouble = + io.DefineAttribute<long double>("attributeLDouble", 12); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(attributeString), + adios2::Attribute<std::string> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeChar), + adios2::Attribute<char> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUChar), + adios2::Attribute<unsigned char> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeShort), + adios2::Attribute<short> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUShort), + adios2::Attribute<unsigned short> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeInt), + adios2::Attribute<int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUInt), + adios2::Attribute<unsigned int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLInt), + adios2::Attribute<long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeULInt), + adios2::Attribute<unsigned long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLLInt), + adios2::Attribute<long long int> &>(); + ::testing::StaticAssertTypeEq< + decltype(attributeULLInt), + adios2::Attribute<unsigned long long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeFloat), + adios2::Attribute<float> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeDouble), + adios2::Attribute<double> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLDouble), + adios2::Attribute<long double> &>(); + + // Verify the members are correct + ASSERT_EQ(attributeString.m_DataArray, nullptr); + EXPECT_EQ(attributeString.m_Name, "attributeString"); + EXPECT_EQ(attributeString.m_DataValue, "-1"); + EXPECT_EQ(attributeString.m_Elements, 1); + EXPECT_EQ(attributeString.m_Type, "string"); + + ASSERT_EQ(attributeChar.m_DataArray, nullptr); + EXPECT_EQ(attributeChar.m_Name, "attributeChar"); + EXPECT_EQ(attributeChar.m_DataValue, '0'); + EXPECT_EQ(attributeChar.m_Elements, 1); + EXPECT_EQ(attributeChar.m_Type, "char"); + + ASSERT_EQ(attributeUChar.m_DataArray, nullptr); + EXPECT_EQ(attributeUChar.m_Name, "attributeUChar"); + EXPECT_EQ(attributeUChar.m_DataValue, '1'); + EXPECT_EQ(attributeUChar.m_Elements, 1); + EXPECT_EQ(attributeUChar.m_Type, "unsigned char"); + + ASSERT_EQ(attributeShort.m_DataArray, nullptr); + EXPECT_EQ(attributeShort.m_Name, "attributeShort"); + EXPECT_EQ(attributeShort.m_DataValue, 2); + EXPECT_EQ(attributeShort.m_Elements, 1); + EXPECT_EQ(attributeShort.m_Type, "short"); + + ASSERT_EQ(attributeUShort.m_DataArray, nullptr); + EXPECT_EQ(attributeUShort.m_Name, "attributeUShort"); + EXPECT_EQ(attributeUShort.m_DataValue, 3); + EXPECT_EQ(attributeUShort.m_Elements, 1); + EXPECT_EQ(attributeUShort.m_Type, "unsigned short"); + + ASSERT_EQ(attributeInt.m_DataArray, nullptr); + EXPECT_EQ(attributeInt.m_Name, "attributeInt"); + EXPECT_EQ(attributeInt.m_DataValue, 4); + EXPECT_EQ(attributeInt.m_Elements, 1); + EXPECT_EQ(attributeInt.m_Type, "int"); + + ASSERT_EQ(attributeUInt.m_DataArray, nullptr); + EXPECT_EQ(attributeUInt.m_Name, "attributeUInt"); + EXPECT_EQ(attributeUInt.m_DataValue, 5); + EXPECT_EQ(attributeUInt.m_Elements, 1); + EXPECT_EQ(attributeUInt.m_Type, "unsigned int"); + + ASSERT_EQ(attributeLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeLInt.m_Name, "attributeLInt"); + EXPECT_EQ(attributeLInt.m_DataValue, 6); + EXPECT_EQ(attributeLInt.m_Elements, 1); + EXPECT_EQ(attributeLInt.m_Type, "long int"); + + ASSERT_EQ(attributeULInt.m_DataArray, nullptr); + EXPECT_EQ(attributeULInt.m_Name, "attributeULInt"); + EXPECT_EQ(attributeULInt.m_DataValue, 7); + EXPECT_EQ(attributeULInt.m_Elements, 1); + EXPECT_EQ(attributeULInt.m_Type, "unsigned long int"); + + ASSERT_EQ(attributeLLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeLLInt.m_Name, "attributeLLInt"); + EXPECT_EQ(attributeLLInt.m_DataValue, 8); + EXPECT_EQ(attributeLLInt.m_Elements, 1); + EXPECT_EQ(attributeLLInt.m_Type, "long long int"); + + ASSERT_EQ(attributeULLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeULLInt.m_Name, "attributeULLInt"); + EXPECT_EQ(attributeULLInt.m_DataValue, 9); + EXPECT_EQ(attributeULLInt.m_Elements, 1); + EXPECT_EQ(attributeULLInt.m_Type, "unsigned long long int"); + + ASSERT_EQ(attributeFloat.m_DataArray, nullptr); + EXPECT_EQ(attributeFloat.m_Name, "attributeFloat"); + EXPECT_EQ(attributeFloat.m_DataValue, 10); + EXPECT_EQ(attributeFloat.m_Elements, 1); + EXPECT_EQ(attributeFloat.m_Type, "float"); + + ASSERT_EQ(attributeDouble.m_DataArray, nullptr); + EXPECT_EQ(attributeDouble.m_Name, "attributeDouble"); + EXPECT_EQ(attributeDouble.m_DataValue, 11); + EXPECT_EQ(attributeDouble.m_Elements, 1); + EXPECT_EQ(attributeDouble.m_Type, "double"); + + ASSERT_EQ(attributeLDouble.m_DataArray, nullptr); + EXPECT_EQ(attributeLDouble.m_Name, "attributeLDouble"); + EXPECT_EQ(attributeLDouble.m_DataValue, 12); + EXPECT_EQ(attributeLDouble.m_Elements, 1); + EXPECT_EQ(attributeLDouble.m_Type, "long double"); +} + +TEST_F(ADIOSDefineAttributeTest, DefineAttributeTypeByReference) +{ + // Define ADIOS global value + const std::vector<std::string> vString{"-1", "0", "+1"}; + const std::vector<char> vChar = {0, 0 + 1, 0 + 2}; + const std::vector<unsigned char> vUChar = {1, 1 + 1, 1 + 2}; + const std::vector<short> vShort = {2, 2 + 1, 2 + 2}; + const std::vector<unsigned short> vUShort = {3, 3 + 1, 3 + 2}; + const std::vector<int> vInt = {4, 4 + 1, 4 + 2}; + const std::vector<unsigned int> vUInt = {5, 5 + 1, 5 + 2}; + const std::vector<long int> vLInt = {6, 6 + 1, 6 + 2}; + const std::vector<unsigned long int> vULInt = {7, 7 + 1, 7 + 2}; + const std::vector<long long int> vLLInt = {8, 8 + 1, 8 + 2}; + const std::vector<unsigned long long int> vULLInt = {9, 9 + 1, 9 + 2}; + const std::vector<float> vFloat = {10, 10 + 1, 10 + 2}; + const std::vector<double> vDouble = {11, 11 + 1, 11 + 2}; + const std::vector<long double> vLDouble = {12, 12 + 1, 12 + 2}; + + auto &attributeString = + io.DefineAttribute<std::string>("attributeString", vString.data(), 3); + + auto &attributeChar = + io.DefineAttribute<char>("attributeChar", vChar.data(), 3); + auto &attributeUChar = + io.DefineAttribute<unsigned char>("attributeUChar", vUChar.data(), 3); + auto &attributeShort = + io.DefineAttribute<short>("attributeShort", vShort.data(), 3); + auto &attributeUShort = io.DefineAttribute<unsigned short>( + "attributeUShort", vUShort.data(), 3); + auto &attributeInt = + io.DefineAttribute<int>("attributeInt", vInt.data(), 3); + auto &attributeUInt = + io.DefineAttribute<unsigned int>("attributeUInt", vUInt.data(), 3); + auto &attributeLInt = + io.DefineAttribute<long int>("attributeLInt", vLInt.data(), 3); + auto &attributeULInt = io.DefineAttribute<unsigned long int>( + "attributeULInt", vULInt.data(), 3); + auto &attributeLLInt = + io.DefineAttribute<long long int>("attributeLLInt", vLLInt.data(), 3); + auto &attributeULLInt = io.DefineAttribute<unsigned long long int>( + "attributeULLInt", vULLInt.data(), 3); + auto &attributeFloat = + io.DefineAttribute<float>("attributeFloat", vFloat.data(), 3); + auto &attributeDouble = + io.DefineAttribute<double>("attributeDouble", vDouble.data(), 3); + auto &attributeLDouble = + io.DefineAttribute<long double>("attributeLDouble", vLDouble.data(), 3); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(attributeString), + adios2::Attribute<std::string> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeChar), + adios2::Attribute<char> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUChar), + adios2::Attribute<unsigned char> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeShort), + adios2::Attribute<short> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUShort), + adios2::Attribute<unsigned short> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeInt), + adios2::Attribute<int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUInt), + adios2::Attribute<unsigned int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLInt), + adios2::Attribute<long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeULInt), + adios2::Attribute<unsigned long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLLInt), + adios2::Attribute<long long int> &>(); + ::testing::StaticAssertTypeEq< + decltype(attributeULLInt), + adios2::Attribute<unsigned long long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeFloat), + adios2::Attribute<float> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeDouble), + adios2::Attribute<double> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLDouble), + adios2::Attribute<long double> &>(); + + // Verify the dimensions, name, and type are correct + ASSERT_NE(attributeString.m_DataArray, nullptr); + EXPECT_EQ(attributeString.m_DataArray[0], "-1"); + EXPECT_EQ(attributeString.m_DataArray[1], "0"); + EXPECT_EQ(attributeString.m_DataArray[2], "+1"); + EXPECT_EQ(attributeString.m_Name, "attributeString"); + ASSERT_EQ(attributeString.m_DataValue.empty(), true); + EXPECT_EQ(attributeString.m_Elements, 3); + EXPECT_EQ(attributeString.m_Type, "string"); + + ASSERT_NE(attributeChar.m_DataArray, nullptr); + EXPECT_EQ(attributeChar.m_DataArray[0], 0); + EXPECT_EQ(attributeChar.m_DataArray[1], 0 + 1); + EXPECT_EQ(attributeChar.m_DataArray[2], 0 + 2); + EXPECT_EQ(attributeChar.m_Name, "attributeChar"); + EXPECT_EQ(attributeChar.m_Elements, 3); + EXPECT_EQ(attributeChar.m_Type, "char"); + + ASSERT_NE(attributeUChar.m_DataArray, nullptr); + EXPECT_EQ(attributeUChar.m_DataArray[0], 1); + EXPECT_EQ(attributeUChar.m_DataArray[1], 1 + 1); + EXPECT_EQ(attributeUChar.m_DataArray[2], 1 + 2); + EXPECT_EQ(attributeUChar.m_Name, "attributeUChar"); + EXPECT_EQ(attributeUChar.m_Elements, 3); + EXPECT_EQ(attributeUChar.m_Type, "unsigned char"); + + ASSERT_NE(attributeShort.m_DataArray, nullptr); + EXPECT_EQ(attributeShort.m_DataArray[0], 2); + EXPECT_EQ(attributeShort.m_DataArray[1], 2 + 1); + EXPECT_EQ(attributeShort.m_DataArray[2], 2 + 2); + EXPECT_EQ(attributeShort.m_Name, "attributeShort"); + EXPECT_EQ(attributeShort.m_Elements, 3); + EXPECT_EQ(attributeShort.m_Type, "short"); + + ASSERT_NE(attributeUShort.m_DataArray, nullptr); + EXPECT_EQ(attributeUShort.m_DataArray[0], 3); + EXPECT_EQ(attributeUShort.m_DataArray[1], 3 + 1); + EXPECT_EQ(attributeUShort.m_DataArray[2], 3 + 2); + EXPECT_EQ(attributeUShort.m_Name, "attributeUShort"); + EXPECT_EQ(attributeUShort.m_Elements, 3); + EXPECT_EQ(attributeUShort.m_Type, "unsigned short"); + + ASSERT_NE(attributeInt.m_DataArray, nullptr); + EXPECT_EQ(attributeInt.m_DataArray[0], 4); + EXPECT_EQ(attributeInt.m_DataArray[1], 4 + 1); + EXPECT_EQ(attributeInt.m_DataArray[2], 4 + 2); + EXPECT_EQ(attributeInt.m_Name, "attributeInt"); + EXPECT_EQ(attributeInt.m_Elements, 3); + EXPECT_EQ(attributeInt.m_Type, "int"); + + ASSERT_NE(attributeUInt.m_DataArray, nullptr); + EXPECT_EQ(attributeUInt.m_DataArray[0], 5); + EXPECT_EQ(attributeUInt.m_DataArray[1], 5 + 1); + EXPECT_EQ(attributeUInt.m_DataArray[2], 5 + 2); + EXPECT_EQ(attributeUInt.m_Name, "attributeUInt"); + EXPECT_EQ(attributeUInt.m_Elements, 3); + EXPECT_EQ(attributeUInt.m_Type, "unsigned int"); + + ASSERT_NE(attributeLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeLInt.m_DataArray[0], 6); + EXPECT_EQ(attributeLInt.m_DataArray[1], 6 + 1); + EXPECT_EQ(attributeLInt.m_DataArray[2], 6 + 2); + EXPECT_EQ(attributeLInt.m_Name, "attributeLInt"); + EXPECT_EQ(attributeLInt.m_Elements, 3); + EXPECT_EQ(attributeLInt.m_Type, "long int"); + + ASSERT_NE(attributeULInt.m_DataArray, nullptr); + EXPECT_EQ(attributeULInt.m_DataArray[0], 7); + EXPECT_EQ(attributeULInt.m_DataArray[1], 7 + 1); + EXPECT_EQ(attributeULInt.m_DataArray[2], 7 + 2); + EXPECT_EQ(attributeULInt.m_Name, "attributeULInt"); + EXPECT_EQ(attributeULInt.m_Elements, 3); + EXPECT_EQ(attributeULInt.m_Type, "unsigned long int"); + + ASSERT_NE(attributeLLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeLLInt.m_DataArray[0], 8); + EXPECT_EQ(attributeLLInt.m_DataArray[1], 8 + 1); + EXPECT_EQ(attributeLLInt.m_DataArray[2], 8 + 2); + EXPECT_EQ(attributeLLInt.m_Name, "attributeLLInt"); + EXPECT_EQ(attributeLLInt.m_Elements, 3); + EXPECT_EQ(attributeLLInt.m_Type, "long long int"); + + ASSERT_NE(attributeULLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeULLInt.m_DataArray[0], 9); + EXPECT_EQ(attributeULLInt.m_DataArray[1], 9 + 1); + EXPECT_EQ(attributeULLInt.m_DataArray[2], 9 + 2); + EXPECT_EQ(attributeULLInt.m_Name, "attributeULLInt"); + EXPECT_EQ(attributeULLInt.m_Elements, 3); + EXPECT_EQ(attributeULLInt.m_Type, "unsigned long long int"); + + ASSERT_NE(attributeFloat.m_DataArray, nullptr); + EXPECT_EQ(attributeFloat.m_DataArray[0], 10); + EXPECT_EQ(attributeFloat.m_DataArray[1], 10 + 1); + EXPECT_EQ(attributeFloat.m_DataArray[2], 10 + 2); + EXPECT_EQ(attributeFloat.m_Name, "attributeFloat"); + EXPECT_EQ(attributeFloat.m_Elements, 3); + EXPECT_EQ(attributeFloat.m_Type, "float"); + + ASSERT_NE(attributeDouble.m_DataArray, nullptr); + EXPECT_EQ(attributeDouble.m_DataArray[0], 11); + EXPECT_EQ(attributeDouble.m_DataArray[1], 11 + 1); + EXPECT_EQ(attributeDouble.m_DataArray[2], 11 + 2); + EXPECT_EQ(attributeDouble.m_Name, "attributeDouble"); + EXPECT_EQ(attributeDouble.m_Elements, 3); + EXPECT_EQ(attributeDouble.m_Type, "double"); + + ASSERT_NE(attributeLDouble.m_DataArray, nullptr); + EXPECT_EQ(attributeLDouble.m_DataArray[0], 12); + EXPECT_EQ(attributeLDouble.m_DataArray[1], 12 + 1); + EXPECT_EQ(attributeLDouble.m_DataArray[2], 12 + 2); + EXPECT_EQ(attributeLDouble.m_Name, "attributeLDouble"); + EXPECT_EQ(attributeLDouble.m_Elements, 3); + EXPECT_EQ(attributeLDouble.m_Type, "long double"); +} + +TEST_F(ADIOSDefineAttributeTest, GetAttribute) +{ + // Define ADIOS global value + const std::vector<std::string> vString{"-1", "0", "+1"}; + const std::vector<char> vChar = {0, 0 + 1, 0 + 2}; + const std::vector<unsigned char> vUChar = {1, 1 + 1, 1 + 2}; + const std::vector<short> vShort = {2, 2 + 1, 2 + 2}; + const std::vector<unsigned short> vUShort = {3, 3 + 1, 3 + 2}; + const std::vector<int> vInt = {4, 4 + 1, 4 + 2}; + const std::vector<unsigned int> vUInt = {5, 5 + 1, 5 + 2}; + const std::vector<long int> vLInt = {6, 6 + 1, 6 + 2}; + const std::vector<unsigned long int> vULInt = {7, 7 + 1, 7 + 2}; + const std::vector<long long int> vLLInt = {8, 8 + 1, 8 + 2}; + const std::vector<unsigned long long int> vULLInt = {9, 9 + 1, 9 + 2}; + const std::vector<float> vFloat = {10, 10 + 1, 10 + 2}; + const std::vector<double> vDouble = {11, 11 + 1, 11 + 2}; + const std::vector<long double> vLDouble = {12, 12 + 1, 12 + 2}; + + { + io.DefineAttribute<std::string>("attributeString", vString.data(), 3); + io.DefineAttribute<char>("attributeChar", vChar.data(), 3); + io.DefineAttribute<unsigned char>("attributeUChar", vUChar.data(), 3); + io.DefineAttribute<short>("attributeShort", vShort.data(), 3); + io.DefineAttribute<unsigned short>("attributeUShort", vUShort.data(), + 3); + io.DefineAttribute<int>("attributeInt", vInt.data(), 3); + io.DefineAttribute<unsigned int>("attributeUInt", vUInt.data(), 3); + io.DefineAttribute<long int>("attributeLInt", vLInt.data(), 3); + io.DefineAttribute<unsigned long int>("attributeULInt", vULInt.data(), + 3); + io.DefineAttribute<long long int>("attributeLLInt", vLLInt.data(), 3); + io.DefineAttribute<unsigned long long int>("attributeULLInt", + vULLInt.data(), 3); + io.DefineAttribute<float>("attributeFloat", vFloat.data(), 3); + io.DefineAttribute<double>("attributeDouble", vDouble.data(), 3); + io.DefineAttribute<long double>("attributeLDouble", vLDouble.data(), 3); + } + + auto &attributeString = io.GetAttribute<std::string>("attributeString"); + auto &attributeChar = io.GetAttribute<char>("attributeChar"); + auto &attributeUChar = io.GetAttribute<unsigned char>("attributeUChar"); + auto &attributeShort = io.GetAttribute<short>("attributeShort"); + auto &attributeUShort = io.GetAttribute<unsigned short>("attributeUShort"); + auto &attributeInt = io.GetAttribute<int>("attributeInt"); + auto &attributeUInt = io.GetAttribute<unsigned int>("attributeUInt"); + auto &attributeLInt = io.GetAttribute<long int>("attributeLInt"); + auto &attributeULInt = io.GetAttribute<unsigned long int>("attributeULInt"); + auto &attributeLLInt = io.GetAttribute<long long int>("attributeLLInt"); + auto &attributeULLInt = + io.GetAttribute<unsigned long long int>("attributeULLInt"); + auto &attributeFloat = io.GetAttribute<float>("attributeFloat"); + auto &attributeDouble = io.GetAttribute<double>("attributeDouble"); + auto &attributeLDouble = io.GetAttribute<long double>("attributeLDouble"); + + // Verify the return type is as expected + ::testing::StaticAssertTypeEq<decltype(attributeString), + adios2::Attribute<std::string> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeChar), + adios2::Attribute<char> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUChar), + adios2::Attribute<unsigned char> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeShort), + adios2::Attribute<short> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUShort), + adios2::Attribute<unsigned short> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeInt), + adios2::Attribute<int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeUInt), + adios2::Attribute<unsigned int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLInt), + adios2::Attribute<long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeULInt), + adios2::Attribute<unsigned long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLLInt), + adios2::Attribute<long long int> &>(); + ::testing::StaticAssertTypeEq< + decltype(attributeULLInt), + adios2::Attribute<unsigned long long int> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeFloat), + adios2::Attribute<float> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeDouble), + adios2::Attribute<double> &>(); + ::testing::StaticAssertTypeEq<decltype(attributeLDouble), + adios2::Attribute<long double> &>(); + + // Verify the dimensions, name, and type are correct + ASSERT_NE(attributeString.m_DataArray, nullptr); + EXPECT_EQ(attributeString.m_DataArray[0], "-1"); + EXPECT_EQ(attributeString.m_DataArray[1], "0"); + EXPECT_EQ(attributeString.m_DataArray[2], "+1"); + EXPECT_EQ(attributeString.m_Name, "attributeString"); + ASSERT_EQ(attributeString.m_DataValue.empty(), true); + EXPECT_EQ(attributeString.m_Elements, 3); + EXPECT_EQ(attributeString.m_Type, "string"); + + ASSERT_NE(attributeChar.m_DataArray, nullptr); + EXPECT_EQ(attributeChar.m_DataArray[0], 0); + EXPECT_EQ(attributeChar.m_DataArray[1], 0 + 1); + EXPECT_EQ(attributeChar.m_DataArray[2], 0 + 2); + EXPECT_EQ(attributeChar.m_Name, "attributeChar"); + EXPECT_EQ(attributeChar.m_Elements, 3); + EXPECT_EQ(attributeChar.m_Type, "char"); + + ASSERT_NE(attributeUChar.m_DataArray, nullptr); + EXPECT_EQ(attributeUChar.m_DataArray[0], 1); + EXPECT_EQ(attributeUChar.m_DataArray[1], 1 + 1); + EXPECT_EQ(attributeUChar.m_DataArray[2], 1 + 2); + EXPECT_EQ(attributeUChar.m_Name, "attributeUChar"); + EXPECT_EQ(attributeUChar.m_Elements, 3); + EXPECT_EQ(attributeUChar.m_Type, "unsigned char"); + + ASSERT_NE(attributeShort.m_DataArray, nullptr); + EXPECT_EQ(attributeShort.m_DataArray[0], 2); + EXPECT_EQ(attributeShort.m_DataArray[1], 2 + 1); + EXPECT_EQ(attributeShort.m_DataArray[2], 2 + 2); + EXPECT_EQ(attributeShort.m_Name, "attributeShort"); + EXPECT_EQ(attributeShort.m_Elements, 3); + EXPECT_EQ(attributeShort.m_Type, "short"); + + ASSERT_NE(attributeUShort.m_DataArray, nullptr); + EXPECT_EQ(attributeUShort.m_DataArray[0], 3); + EXPECT_EQ(attributeUShort.m_DataArray[1], 3 + 1); + EXPECT_EQ(attributeUShort.m_DataArray[2], 3 + 2); + EXPECT_EQ(attributeUShort.m_Name, "attributeUShort"); + EXPECT_EQ(attributeUShort.m_Elements, 3); + EXPECT_EQ(attributeUShort.m_Type, "unsigned short"); + + ASSERT_NE(attributeInt.m_DataArray, nullptr); + EXPECT_EQ(attributeInt.m_DataArray[0], 4); + EXPECT_EQ(attributeInt.m_DataArray[1], 4 + 1); + EXPECT_EQ(attributeInt.m_DataArray[2], 4 + 2); + EXPECT_EQ(attributeInt.m_Name, "attributeInt"); + EXPECT_EQ(attributeInt.m_Elements, 3); + EXPECT_EQ(attributeInt.m_Type, "int"); + + ASSERT_NE(attributeUInt.m_DataArray, nullptr); + EXPECT_EQ(attributeUInt.m_DataArray[0], 5); + EXPECT_EQ(attributeUInt.m_DataArray[1], 5 + 1); + EXPECT_EQ(attributeUInt.m_DataArray[2], 5 + 2); + EXPECT_EQ(attributeUInt.m_Name, "attributeUInt"); + EXPECT_EQ(attributeUInt.m_Elements, 3); + EXPECT_EQ(attributeUInt.m_Type, "unsigned int"); + + ASSERT_NE(attributeLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeLInt.m_DataArray[0], 6); + EXPECT_EQ(attributeLInt.m_DataArray[1], 6 + 1); + EXPECT_EQ(attributeLInt.m_DataArray[2], 6 + 2); + EXPECT_EQ(attributeLInt.m_Name, "attributeLInt"); + EXPECT_EQ(attributeLInt.m_Elements, 3); + EXPECT_EQ(attributeLInt.m_Type, "long int"); + + ASSERT_NE(attributeULInt.m_DataArray, nullptr); + EXPECT_EQ(attributeULInt.m_DataArray[0], 7); + EXPECT_EQ(attributeULInt.m_DataArray[1], 7 + 1); + EXPECT_EQ(attributeULInt.m_DataArray[2], 7 + 2); + EXPECT_EQ(attributeULInt.m_Name, "attributeULInt"); + EXPECT_EQ(attributeULInt.m_Elements, 3); + EXPECT_EQ(attributeULInt.m_Type, "unsigned long int"); + + ASSERT_NE(attributeLLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeLLInt.m_DataArray[0], 8); + EXPECT_EQ(attributeLLInt.m_DataArray[1], 8 + 1); + EXPECT_EQ(attributeLLInt.m_DataArray[2], 8 + 2); + EXPECT_EQ(attributeLLInt.m_Name, "attributeLLInt"); + EXPECT_EQ(attributeLLInt.m_Elements, 3); + EXPECT_EQ(attributeLLInt.m_Type, "long long int"); + + ASSERT_NE(attributeULLInt.m_DataArray, nullptr); + EXPECT_EQ(attributeULLInt.m_DataArray[0], 9); + EXPECT_EQ(attributeULLInt.m_DataArray[1], 9 + 1); + EXPECT_EQ(attributeULLInt.m_DataArray[2], 9 + 2); + EXPECT_EQ(attributeULLInt.m_Name, "attributeULLInt"); + EXPECT_EQ(attributeULLInt.m_Elements, 3); + EXPECT_EQ(attributeULLInt.m_Type, "unsigned long long int"); + + ASSERT_NE(attributeFloat.m_DataArray, nullptr); + EXPECT_EQ(attributeFloat.m_DataArray[0], 10); + EXPECT_EQ(attributeFloat.m_DataArray[1], 10 + 1); + EXPECT_EQ(attributeFloat.m_DataArray[2], 10 + 2); + EXPECT_EQ(attributeFloat.m_Name, "attributeFloat"); + EXPECT_EQ(attributeFloat.m_Elements, 3); + EXPECT_EQ(attributeFloat.m_Type, "float"); + + ASSERT_NE(attributeDouble.m_DataArray, nullptr); + EXPECT_EQ(attributeDouble.m_DataArray[0], 11); + EXPECT_EQ(attributeDouble.m_DataArray[1], 11 + 1); + EXPECT_EQ(attributeDouble.m_DataArray[2], 11 + 2); + EXPECT_EQ(attributeDouble.m_Name, "attributeDouble"); + EXPECT_EQ(attributeDouble.m_Elements, 3); + EXPECT_EQ(attributeDouble.m_Type, "double"); + + ASSERT_NE(attributeLDouble.m_DataArray, nullptr); + EXPECT_EQ(attributeLDouble.m_DataArray[0], 12); + EXPECT_EQ(attributeLDouble.m_DataArray[1], 12 + 1); + EXPECT_EQ(attributeLDouble.m_DataArray[2], 12 + 2); + EXPECT_EQ(attributeLDouble.m_Name, "attributeLDouble"); + EXPECT_EQ(attributeLDouble.m_Elements, 3); + EXPECT_EQ(attributeLDouble.m_Type, "long double"); +} + +int main(int argc, char **argv) +{ +#ifdef ADIOS2_HAVE_MPI + MPI_Init(nullptr, nullptr); +#endif + + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return result; +}