diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h index f3043732b588cbde469d3b5f9e06adcc85afa03b..f15756cacb133a52f0c3f7de2a8d72e32a4a8095 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 @@ -49,6 +51,8 @@ MACRO(unsigned int) \ MACRO(long int) \ MACRO(unsigned long int) \ + MACRO(long long int) \ + MACRO(unsigned long long int) \ MACRO(float) \ MACRO(double) @@ -62,4 +66,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/core/Attribute.h b/source/adios2/core/Attribute.h new file mode 100644 index 0000000000000000000000000000000000000000..7ed3cc7799ccd394014dc82e3aa84129f4384f86 --- /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 + * + * 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 /* SOURCE_ADIOS2_CORE_ATTRIBUTE_H_ */ diff --git a/source/adios2/core/Attribute.tcc b/source/adios2/core/Attribute.tcc new file mode 100644 index 0000000000000000000000000000000000000000..47343256f652ee08587822e8858ebcb5ba3d331f --- /dev/null +++ b/source/adios2/core/Attribute.tcc @@ -0,0 +1,41 @@ +/* + * 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() \ + { \ + } + +ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_type) +#undef declare_type + +} // end namespace adios2 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..cf09b54f3b58767e7a6b9b695cd74c72d7b17daf --- /dev/null +++ b/source/adios2/core/AttributeBase.h @@ -0,0 +1,39 @@ +/* + * 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_ + +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 fe70d534ec6094c44a30440ddd2072daf12bcd2b..4fd7b69fca46345f860c3976d3552bf0a12333f0 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -62,7 +62,7 @@ unsigned int IO::AddTransport(const std::string type, const Params ¶meters) 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 @@ -235,30 +235,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 diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index 59fc9f6c7fb2589feaf1f470d230b7b6b56d0e3d..a738fd7bc71f1e7deba72b2717a41c39e1624bc6 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; @@ -137,6 +141,26 @@ public: const Dims start = Dims{}, const Dims count = Dims{}, const bool constantShape = false); + /** + * Define attribute from contiguous data array + * @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 + * @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 @@ -163,6 +187,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 @@ -222,7 +255,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; @@ -243,25 +276,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; }; @@ -276,6 +347,15 @@ private: ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) #undef declare_template_instantiation +#define declare_template_instantiation(T) \ + extern template Attribute<T> &IO::DefineAttribute<T>( \ + const std::string &name, const T *array, const size_t elements); \ + extern template Attribute<T> &IO::DefineAttribute<T>( \ + const std::string &name, const T &value); + +ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + } // end namespace adios #include "adios2/core/IO.inl" diff --git a/source/adios2/core/IO.inl b/source/adios2/core/IO.inl index 6ef9299c028b5033a4030448308ee695cca69db4..9dd0f53f29f414aaa8dd0b4503c19ad1ac5e5eff 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 @@ -27,14 +28,16 @@ VariableCompound &IO::DefineVariableCompound(const std::string &name, { 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 + - ", in call to DefineVariable\n"); + throw std::invalid_argument( + "ERROR: compound variable " + name + " exists in IO object " + + m_Name + ", in call to DefineVariableCompound\n"); } } - const unsigned int size = m_Compound.size(); + const unsigned int size = + static_cast<const unsigned int>(m_Compound.size()); auto itVariableCompound = m_Compound.emplace( size, VariableCompound(name, sizeof(T), shape, start, count, constantShape, m_DebugMode)); @@ -42,6 +45,6 @@ VariableCompound &IO::DefineVariableCompound(const std::string &name, return itVariableCompound.first->second; } -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_CORE_IO_INL_ */ diff --git a/source/adios2/core/IO.tcc b/source/adios2/core/IO.tcc index dddb3167848b6849ab92c1d0cfd8a16b7af1ddeb..572fa53bfba548a8729851796f42e844e474818c 100644 --- a/source/adios2/core/IO.tcc +++ b/source/adios2/core/IO.tcc @@ -32,7 +32,8 @@ Variable<T> &IO::DefineVariable(const std::string &name, const Dims shape, { 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, constantShape, 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 @@ -153,6 +201,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.h b/source/adios2/core/Variable.h index 9ed428735bb8f924d61d7314cd94fbd49084a781..8f5482857bffc4f94d4b49d626b831a266fd480c 100644 --- a/source/adios2/core/Variable.h +++ b/source/adios2/core/Variable.h @@ -54,7 +54,7 @@ public: const Dims count, const bool constantShape, const bool debugMode); - virtual ~Variable<T>() = default; + ~Variable<T>() = default; void ApplyTransforms() final; }; diff --git a/source/adios2/core/Variable.tcc b/source/adios2/core/Variable.tcc index e5a241109009f95fd99e07aa5750f5bfca1a93a7..603b9300dd31114ddfdc47c6b49e2c2e4be69e0d 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 {