From 7a7d092915d4bfbaa6d8d295a27eb157e5bcd5e0 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 17 Sep 2020 16:22:08 -0400 Subject: [PATCH 01/10] Hierarchical reading implementation --- bindings/CXX11/CMakeLists.txt | 2 + bindings/CXX11/adios2.h | 1 + bindings/CXX11/adios2/cxx11/Group.cpp | 75 ++++++ bindings/CXX11/adios2/cxx11/Group.h | 148 ++++++++++++ bindings/CXX11/adios2/cxx11/Group.tcc | 42 ++++ bindings/CXX11/adios2/cxx11/IO.cpp | 5 +- bindings/CXX11/adios2/cxx11/IO.h | 9 +- bindings/CXX11/adios2/cxx11/Variable.h | 3 +- source/adios2/CMakeLists.txt | 1 + source/adios2/core/Group.cpp | 226 ++++++++++++++++++ source/adios2/core/Group.h | 161 +++++++++++++ source/adios2/core/Group.tcc | 40 ++++ source/adios2/core/IO.cpp | 7 + source/adios2/core/IO.h | 6 + testing/adios2/CMakeLists.txt | 1 + testing/adios2/hierarchy/CMakeLists.txt | 6 + .../hierarchy/TestHierarchicalReading.cpp | 106 ++++++++ 17 files changed, 836 insertions(+), 3 deletions(-) create mode 100644 bindings/CXX11/adios2/cxx11/Group.cpp create mode 100644 bindings/CXX11/adios2/cxx11/Group.h create mode 100644 bindings/CXX11/adios2/cxx11/Group.tcc create mode 100644 source/adios2/core/Group.cpp create mode 100644 source/adios2/core/Group.h create mode 100644 source/adios2/core/Group.tcc create mode 100644 testing/adios2/hierarchy/CMakeLists.txt create mode 100644 testing/adios2/hierarchy/TestHierarchicalReading.cpp diff --git a/bindings/CXX11/CMakeLists.txt b/bindings/CXX11/CMakeLists.txt index 606161274e..bcfa0ce8de 100644 --- a/bindings/CXX11/CMakeLists.txt +++ b/bindings/CXX11/CMakeLists.txt @@ -16,6 +16,8 @@ add_library(adios2_cxx11 adios2/cxx11/Types.tcc adios2/cxx11/Variable.cpp adios2/cxx11/fstream/ADIOS2fstream.cpp + adios2/cxx11/Group.cpp + adios2/cxx11/Group.tcc ) set_property(TARGET adios2_cxx11 PROPERTY EXPORT_NAME cxx11) set_property(TARGET adios2_cxx11 PROPERTY OUTPUT_NAME adios2${ADIOS2_LIBRARY_SUFFIX}_cxx11) diff --git a/bindings/CXX11/adios2.h b/bindings/CXX11/adios2.h index 73dd03d75a..57b9c5a968 100644 --- a/bindings/CXX11/adios2.h +++ b/bindings/CXX11/adios2.h @@ -33,5 +33,6 @@ constexpr bool DebugOFF = false; #include "adios2/cxx11/Types.h" #include "adios2/cxx11/Variable.h" #include "adios2/cxx11/fstream/ADIOS2fstream.h" +#include "adios2/cxx11/Group.h" #endif /* ADIOS2_BINDINGS_CXX11_H_ */ diff --git a/bindings/CXX11/adios2/cxx11/Group.cpp b/bindings/CXX11/adios2/cxx11/Group.cpp new file mode 100644 index 0000000000..6647f38a70 --- /dev/null +++ b/bindings/CXX11/adios2/cxx11/Group.cpp @@ -0,0 +1,75 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Group.cpp : + * + * Created on: August 25, 2020 + * Author: Dmitry Ganyushin ganyushindi@ornl.gov + */ + +#include "Group.h" +#include "Group.tcc" +#include "adios2/core/Group.h" + +namespace adios2 +{ +Group::Group(core::Group *group) : m_Group(group) {} + +Group Group::OpenGroup(std::string group_name) +{ + auto m = m_Group->OpenGroup(group_name); + return Group(m); +} +void Group::PrintTree() +{ + m_Group->PrintTree(); + return; +} + +void Group::BuildTree() +{ + m_Group->BuildTree(); + return; +} +std::vector Group::AvailableVariables() +{ + return m_Group->AvailableVariables(); +} +std::vector Group::AvailableAttributes() +{ + return m_Group->AvailableAttributes(); +} +std::vector Group::AvailableGroups() +{ + return m_Group->AvailableGroups(); +} + +std::map> &Group::getTreeMap() +{ + return m_Group->getTreeMap(); +} + +std::string Group::InquirePath() { return m_Group->InquirePath(); } + +void Group::setPath(std::string path) { m_Group->setPath(path); } +DataType Group::VariableType(const std::string &name) const +{ + helper::CheckForNullptr(m_Group, "in call to IO::VariableType"); + return m_Group->InquireVariableType(name); +} + +DataType Group::AttributeType(const std::string &name) const +{ + helper::CheckForNullptr(m_Group, "in call to IO::AttributeType"); + return m_Group->InquireAttributeType(name); +} +Group::~Group() { m_Group->~Group(); } +// Explicit declaration of the public template methods +// Limits the types +#define declare_template_instantiation(T) \ + template Variable Group::InquireVariable(const std::string &); + +ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} // end of namespace diff --git a/bindings/CXX11/adios2/cxx11/Group.h b/bindings/CXX11/adios2/cxx11/Group.h new file mode 100644 index 0000000000..8265f53be8 --- /dev/null +++ b/bindings/CXX11/adios2/cxx11/Group.h @@ -0,0 +1,148 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Group.h : + * + * Created on: August 25, 2020 + * Author: Dmitry Ganyushin ganyushindi@ornl.gov + */ +#ifndef ADIOS2_BINDINGS_CXX11_CXX11_GROUP_H_ + +#define ADIOS2_BINDINGS_CXX11_CXX11_GROUP_H_ + +#include "Attribute.h" +#include "Variable.h" +#include "adios2/core/Group.h" +#include +#include +#include +#include +#include + +#if ADIOS2_USE_MPI +#include +#endif + +#include "Group.h" +#include "adios2/common/ADIOSMacros.h" +#include "adios2/common/ADIOSTypes.h" + +namespace adios2 +{ +class IO; + +namespace core +{ +class Group; // private implementation +} +class Group +{ + friend class IO; + +private: + Group(core::Group *group); + core::Group *m_Group = nullptr; + +public: + ~Group(); + /** + * @brief Builds map that represents tree structure from m_Variable and + * m_Attributes from IO class + * @param + */ + void BuildTree(); + /** + * @brief Prints map that represents tree structure + * @param + */ + void PrintTree(); + /** + * @brief returns available groups on the path set + * @param + * @return vector of strings + */ + std::vector AvailableGroups(); + /** + * @brief returns available variables on the path set + * @param + * @return vector of strings + */ + std::vector AvailableVariables(); + /** + * @brief returns available attributes on the path set + * @param + * @return vector of strings + */ + std::vector AvailableAttributes(); + /** + * @brief returns the current path + * @param + * @return current path as a string + */ + std::string InquirePath(); + /** + * @brief set the path, points to a particular node on the tree + * @param next possible path extension + */ + void setPath(std::string path); + /** + * @brief returns a new group object + * @param name of the group + * @return new group object + */ + Group OpenGroup(std::string group_name); + /** + * @brief returns a reference to the map representing the tree stucture + * @param delimiter symbol + */ + std::map> &getTreeMap(); + /** + * @brief Gets an existing variable of primitive type by name. A wrapper for + * the corresponding function of the IO class + * @param name of variable to be retrieved + * @return pointer to an existing variable in current IO, nullptr if not + * found + */ + template + Variable InquireVariable(const std::string &name); + /** + * Gets an existing attribute of primitive type by name. A wrapper for + * the corresponding function of the IO class + * @param name of attribute to be retrieved + * @return pointer to an existing attribute in current IO, nullptr if not + * found + */ + template + Attribute InquireAttribute(const std::string &name, + const std::string &variableName = "", + const std::string separator = "/"); + + /** + * Inspects variable type. This function can be used in conjunction with + * MACROS in an else if (type == adios2::GetType() ) {} loop + * @param name unique variable name identifier in current IO + * @return type as in adios2::GetType() (e.g. "double", "float"), + * empty std::string if variable not found + */ + DataType VariableType(const std::string &name) const; + + /** + * Inspects attribute type. This function can be used in conjunction with + * MACROS in an else if (type == adios2::GetType() ) {} loop + * @param name unique attribute name identifier in current IO + * @return type as in adios2::GetType() (e.g. "double", "float"), empty + * std::string if attribute not found + */ + DataType AttributeType(const std::string &name) const; +}; +// Explicit declaration of the public template methods +// Limits the types +#define declare_template_instantiation(T) \ + extern template Variable Group::InquireVariable(const std::string &); +ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + +} +#endif // ADIOS2_BINDINGS_CXX11_CXX11_GROUP_H_ + diff --git a/bindings/CXX11/adios2/cxx11/Group.tcc b/bindings/CXX11/adios2/cxx11/Group.tcc new file mode 100644 index 0000000000..e051a62fa5 --- /dev/null +++ b/bindings/CXX11/adios2/cxx11/Group.tcc @@ -0,0 +1,42 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Group.tcc : + * + * Created on: August 25, 2020 + * Author: Dmitry Ganyushin ganyushindi@ornl.gov + */ +#ifndef ADIOS2_BINDINGS_CXX11_CXX11_GROUP_TCC_ +#define ADIOS2_BINDINGS_CXX11_CXX11_GROUP_TCC_ + +#include "Group.h" + +#include "adios2/core/Group.h" + +namespace adios2 +{ +template +Variable Group::InquireVariable(const std::string &name) +{ + helper::CheckForNullptr(m_Group, "for variable name " + name + + ", in call to Group::InquireVariable"); + return Variable( + m_Group->InquireVariable::IOType>(name)); +} + +template +Attribute Group::InquireAttribute(const std::string &name, + const std::string &variableName, + const std::string separator) +{ + using IOType = typename TypeInfo::IOType; + helper::CheckForNullptr(m_Group, "for attribute name " + name + + ", in call to IO::InquireAttribute"); + return Attribute( + m_Group->InquireAttribute(name, variableName, separator)); +} + +} // end namespace adios2 + +#endif /* ADIOS2_BINDINGS_CXX11_CXX11_GROUP_TCC_ */ diff --git a/bindings/CXX11/adios2/cxx11/IO.cpp b/bindings/CXX11/adios2/cxx11/IO.cpp index 2e45b596df..68fcb1b89a 100644 --- a/bindings/CXX11/adios2/cxx11/IO.cpp +++ b/bindings/CXX11/adios2/cxx11/IO.cpp @@ -109,7 +109,10 @@ Engine IO::Open(const std::string &name, const Mode mode) "for engine " + name + ", in call to IO::Open"); return Engine(&m_IO->Open(name, mode)); } - +Group IO::GetGroup(const std::string &path, char delimiter) +{ + return Group(&m_IO->GetGroup(path, delimiter)); +}; void IO::FlushAll() { helper::CheckForNullptr(m_IO, "in call to IO::FlushAll"); diff --git a/bindings/CXX11/adios2/cxx11/IO.h b/bindings/CXX11/adios2/cxx11/IO.h index 717b6be72b..bf1cfdb16d 100644 --- a/bindings/CXX11/adios2/cxx11/IO.h +++ b/bindings/CXX11/adios2/cxx11/IO.h @@ -15,7 +15,7 @@ #include "Engine.h" #include "Operator.h" #include "Variable.h" - +#include "Group.h" #if ADIOS2_USE_MPI #include #endif @@ -256,6 +256,13 @@ class IO * @return engine object */ Engine Open(const std::string &name, const Mode mode); + /** + * Return a Group object for hierarchical reading. + * @param name starting path + * @param a delimiter to separate groups in a string representation + * @return Group object + */ + Group GetGroup(const std::string &path, char delimiter = '/'); #if ADIOS2_USE_MPI /** diff --git a/bindings/CXX11/adios2/cxx11/Variable.h b/bindings/CXX11/adios2/cxx11/Variable.h index 6b0dbb1177..13c64b210d 100644 --- a/bindings/CXX11/adios2/cxx11/Variable.h +++ b/bindings/CXX11/adios2/cxx11/Variable.h @@ -22,7 +22,7 @@ namespace adios2 // forward declare class IO; // friend class Engine; // friend - +class Group; //friend namespace core { @@ -131,6 +131,7 @@ class Variable friend class IO; friend class Engine; + friend class Group; public: /** diff --git a/source/adios2/CMakeLists.txt b/source/adios2/CMakeLists.txt index f7a500455e..2b3a844474 100644 --- a/source/adios2/CMakeLists.txt +++ b/source/adios2/CMakeLists.txt @@ -29,6 +29,7 @@ add_library(adios2_core core/Variable.cpp core/Variable.tcc core/VariableBase.cpp core/VariableCompound.cpp core/VariableCompound.tcc + core/Group.cpp core/Group.tcc #operator callback operator/callback/Signature1.cpp diff --git a/source/adios2/core/Group.cpp b/source/adios2/core/Group.cpp new file mode 100644 index 0000000000..aecc2ae0dc --- /dev/null +++ b/source/adios2/core/Group.cpp @@ -0,0 +1,226 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Group.cpp : + * + * Created on: August 25, 2020 + * Author: Dmitry Ganyushin ganyushindi@ornl.gov + */ +#include "Group.h" +#include "Group.tcc" +#include +#include +#include +#include +#include + +#include "adios2/common/ADIOSMacros.h" +#include "adios2/core/IO.h" +namespace adios2 +{ +namespace core +{ +std::vector split(const std::string &s, char delimiter) +{ + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) + { + tokens.push_back(token); + } + return tokens; +} +void Group::setPath(std::string path) { currentPath = path; } +void Group::setDelimiter(char delimiter) { groupDelimiter = delimiter; } + +Group::Group(std::string path, char delimiter, IO &io) + : currentPath(path), groupDelimiter(delimiter), m_IO(io) +{ + if (mapPtr == nullptr) + { + mapPtr = std::shared_ptr(new TreeMap()); + } +} +// copy constructor +Group::Group(const Group &G) + : currentPath(G.currentPath), groupDelimiter(G.groupDelimiter), m_IO(G.m_IO) +{ + mapPtr = G.mapPtr; +} +Group *Group::OpenGroup(std::string groupName) +{ + Group *g_out = new Group(currentPath + groupDelimiter + groupName, + this->groupDelimiter, this->m_IO); + g_out->mapPtr = this->mapPtr; + return g_out; +} +void Group::PrintTree() +{ + for (auto k : mapPtr->treeMap) + { + std::cout << k.first << "=>"; + for (auto v : k.second) + std::cout << v << " "; + std::cout << std::endl; + } +} + +void Group::BuildTree() +{ + const core::VarMap &variables = m_IO.GetVariables(); + for (const auto &variablePair : variables) + { + std::vector tokens = + split(variablePair.first, groupDelimiter); + + if (tokens.size() == 0) + { + // record = "group". Handled by default case + } + else if (tokens.size() == 1) + { + // case record = "/group1" or "group/" + } + if (tokens.size() > 1) + { + std::string key = tokens[0]; + for (int level = 1; level < tokens.size(); level++) + { + std::string value = tokens[level]; + // get previous vector + std::set val = mapPtr->treeMap[key]; + // modify it + val.insert(value); + mapPtr->treeMap[key] = val; + key += groupDelimiter + tokens[level]; + } + } + } + const core::AttrMap &attributes = m_IO.GetAttributes(); + for (const auto &attributePair : attributes) + { + std::vector tokens = + split(attributePair.first, groupDelimiter); + + if (tokens.size() == 0) + { + // record = "group". Handled by default case + } + else if (tokens.size() == 1) + { + // case record = "/group1" or "group/" + } + if (tokens.size() > 1) + { + std::string key = tokens[0]; + for (int level = 1; level < tokens.size(); level++) + { + std::string value = tokens[level]; + // get previous vector + std::set val = mapPtr->treeMap[key]; + // modify it + val.insert(value); + mapPtr->treeMap[key] = val; + key += groupDelimiter + tokens[level]; + } + } + } +} +std::vector Group::AvailableVariables() +{ + // look into map + std::set val = mapPtr->treeMap[currentPath]; + // TODODG check that currentPath exists + std::vector available_variables; + for (auto v : val) + { + if (mapPtr->treeMap.find(currentPath + groupDelimiter + v) == + mapPtr->treeMap.end()) + { + const core::VarMap &variables = m_IO.GetVariables(); + + if (variables.find(currentPath + groupDelimiter + v) != + variables.end()) + { + available_variables.push_back(v); + } + } + } + + return available_variables; +} + +std::vector Group::AvailableAttributes() +{ + // look into map + std::set val = mapPtr->treeMap[currentPath]; + // TODODG check that currentPath exists + std::vector available_attributes; + for (auto v : val) + { + if (mapPtr->treeMap.find(currentPath + groupDelimiter + v) == + mapPtr->treeMap.end()) + { + const core::AttrMap &attributes = m_IO.GetAttributes(); + if (attributes.find(currentPath + groupDelimiter + v) != + attributes.end()) + { + available_attributes.push_back(v); + } + } + } + + return available_attributes; +} + +std::vector Group::AvailableGroups() +{ + + std::vector available_groups; + std::set val = mapPtr->treeMap[currentPath]; + + for (auto v : val) + { + if (mapPtr->treeMap.find(currentPath + groupDelimiter + v) != + mapPtr->treeMap.end()) + available_groups.push_back(v); + } + + return available_groups; +} + +std::map> &Group::getTreeMap() +{ + std::map> &tree = mapPtr->treeMap; + return tree; +} + +std::string Group::InquirePath() { return currentPath; } +Group::~Group(){ + +}; +DataType Group::InquireVariableType(const std::string &name) const noexcept +{ + + return m_IO.InquireVariableType(currentPath + groupDelimiter + name); +} + +DataType +Group::InquireAttributeType(const std::string &name, + const std::string &variableName, + const std::string separator) const noexcept +{ + return m_IO.InquireAttributeType(name, variableName, separator); +} +// Explicitly instantiate the necessary public template implementations +#define define_template_instantiation(T) \ + template Variable *Group::InquireVariable( \ + const std::string &) noexcept; + +ADIOS2_FOREACH_STDTYPE_1ARG(define_template_instantiation) +#undef define_template_instatiation + +} // end namespace core +} // end namespace adios2 diff --git a/source/adios2/core/Group.h b/source/adios2/core/Group.h new file mode 100644 index 0000000000..6cc806edcc --- /dev/null +++ b/source/adios2/core/Group.h @@ -0,0 +1,161 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Group.h template implementations with fix types and specializations + * + * Created on: August 25, 2020 + * Author: Dmitry Ganyushin ganyushindi@ornl.gov + */ +#ifndef ADIOS2_CORE_GROUP_H +#define ADIOS2_CORE_GROUP_H +#include "adios2/core/IO.h" +#include "adios2/core/Variable.h" +#include +#include +#include +#include +namespace adios2 +{ +namespace core +{ +/** used for Variables and Attributes, name, type, type-index */ +using DataMap = +std::unordered_map>; +class Group +{ +private: + struct TreeMap + { + std::map> treeMap; + }; + /** current path of the Group object */ + std::string currentPath; + /** demiliter symbol between groups */ + char groupDelimiter; + /** shared pointer to a map representing the tree structure */ + std::shared_ptr mapPtr = nullptr; + +public: + /** + * @brief Constructor called from IO factory class GetGroup function. + * Not to be used directly in applications. + * @param current path + * @param a separate symbol + * @param IO reference object to IO object that owns the current Group + * object + */ + Group(std::string path, char delimiter, IO &m_IO); + /** copy constructor */ + Group(const Group &G); + /** destructor */ + ~Group(); + /** + * @brief Builds map that represents tree structure from m_Variable and + * m_Attributes from IO class + * @param + */ + void BuildTree(); + /** + * @brief Prints map that represents tree structure + * @param + */ + void PrintTree(); + /** + * @brief returns available groups on the path set + * @param + * @return vector of strings + */ + std::vector AvailableGroups(); + /** + * @brief returns available variables on the path set + * @param + * @return vector of strings + */ + std::vector AvailableVariables(); + /** + * @brief returns available attributes on the path set + * @param + * @return vector of strings + */ + std::vector AvailableAttributes(); + /** + * @brief returns the current path + * @param + * @return current path as a string + */ + std::string InquirePath(); + /** + * @brief returns a new group object + * @param name of the group + * @return new group object + */ + Group *OpenGroup(std::string groupName); + /** + * @brief set the path, points to a particular node on the tree + * @param next possible path extension + */ + void setPath(std::string path); + /** + * @brief set the delimiter for group connection in a string representation + * @param delimiter symbol + */ + void setDelimiter(char delimiter); + /** + * @brief returns a reference to the map representing the tree stucture + * @param delimiter symbol + */ + std::map> &getTreeMap(); + /** reference to object that created current Group */ + IO &m_IO; + /** + * @brief Gets an existing variable of primitive type by name. A wrapper for + * the corresponding function of the IO class + * @param name of variable to be retrieved + * @return pointer to an existing variable in current IO, nullptr if not + * found + */ + template + Variable *InquireVariable(const std::string &name) noexcept; + /** + * Gets an existing attribute of primitive type by name. A wrapper for + * the corresponding function of the IO class + * @param name of attribute to be retrieved + * @return pointer to an existing attribute in current IO, nullptr if not + * found + */ + template + Attribute *InquireAttribute(const std::string &name, + const std::string &variableName = "", + const std::string separator = "/") noexcept; + /** + * @brief Returns the type of an existing variable as an string. A wrapper + * for the corresponding function of the IO class + * @param name input variable name + * @return type primitive type + */ + DataType InquireVariableType(const std::string &name) const noexcept; + + /** + * @brief Returns the type of an existing attribute as an string. A wrapper + * for the corresponding function of the IO class + * @param name input attribute name + * @return type if found returns type as string, otherwise an empty string + */ + DataType + InquireAttributeType(const std::string &name, + const std::string &variableName = "", + const std::string separator = "/") const noexcept; +}; +// Explicit declaration of the public template methods +#define declare_template_instantiation(T) \ + extern template Variable *Group::InquireVariable( \ + const std::string &name) noexcept; + +ADIOS2_FOREACH_STDTYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} // end namespace core +} // end namespace adios2 + +#endif // ADIOS2_CORE_GROUP_H + diff --git a/source/adios2/core/Group.tcc b/source/adios2/core/Group.tcc new file mode 100644 index 0000000000..da5c883115 --- /dev/null +++ b/source/adios2/core/Group.tcc @@ -0,0 +1,40 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Group.tcc template implementations with fix types and specializations + * + * Created on: August 25, 2020 + * Author: Dmitry Ganyushin ganyushindi@ornl.gov + */ +#ifndef ADIOS2_CORE_GROUP_TCC_ +#define ADIOS2_CORE_GROUP_TCC_ + +#include "Group.h" + +namespace adios2 +{ +namespace core +{ + +template +Variable *Group::InquireVariable(const std::string &name) noexcept +{ + Variable &variable = + *m_IO.InquireVariable(currentPath + groupDelimiter + name); + return &variable; +} + +template +Attribute *Group::InquireAttribute(const std::string &name, + const std::string &variableName, + const std::string separator) noexcept +{ + Attribute &attribute = m_IO.InquireAttribute( + currentPath + groupDelimiter + name, variableName, separator); + return &attribute; +} +} // end namespace core +} // end namespace adios2 + +#endif /* ADIOS2_CORE_GROUP_TCC_ */ diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index 764a4c2c45..d880b39435 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -654,7 +654,14 @@ Engine &IO::Open(const std::string &name, const Mode mode) { return Open(name, mode, m_ADIOS.GetComm().Duplicate()); } +Group &IO::GetGroup(const std::string &path, char delimiter) +{ + m_Gr = new Group(path, delimiter, *this); + m_Gr->BuildTree(); + m_Gr->BuildTree(); + return *m_Gr; +} Engine &IO::GetEngine(const std::string &name) { TAU_SCOPED_TIMER("IO::other"); diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index 316725aa8d..c1057213c4 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -27,6 +27,7 @@ #include "adios2/core/Attribute.h" #include "adios2/core/Variable.h" #include "adios2/core/VariableCompound.h" +#include "adios2/core/Group.h" namespace adios2 { @@ -40,6 +41,7 @@ using AttrMap = std::unordered_map>; // forward declaration needed as IO is passed to Engine derived // classes class Engine; +class Group; /** Factory class IO for settings, variables, and transports to an engine */ class IO @@ -48,6 +50,8 @@ class IO public: /** reference to object that created current IO */ ADIOS &m_ADIOS; + /** a pointer to a Group Object created from IO */ + Group *m_Gr; /** unique identifier */ const std::string m_Name; @@ -408,6 +412,8 @@ class IO */ void FlushAll(); + Group &GetGroup(const std::string &path, char delimiter); + // READ FUNCTIONS, not yet implemented: /** * not yet implented diff --git a/testing/adios2/CMakeLists.txt b/testing/adios2/CMakeLists.txt index f9047a86a7..9a840fdd3d 100644 --- a/testing/adios2/CMakeLists.txt +++ b/testing/adios2/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(xml) add_subdirectory(yaml) add_subdirectory(performance) add_subdirectory(helper) +add_subdirectory(hierarchy) diff --git a/testing/adios2/hierarchy/CMakeLists.txt b/testing/adios2/hierarchy/CMakeLists.txt new file mode 100644 index 0000000000..cd6ecbd343 --- /dev/null +++ b/testing/adios2/hierarchy/CMakeLists.txt @@ -0,0 +1,6 @@ +#------------------------------------------------------------------------------# +#Distributed under the OSI - approved Apache License, Version 2.0. See +#accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +gtest_add_tests_helper(HierarchicalReading MPI_NONE "" "". "") \ No newline at end of file diff --git a/testing/adios2/hierarchy/TestHierarchicalReading.cpp b/testing/adios2/hierarchy/TestHierarchicalReading.cpp new file mode 100644 index 0000000000..a5655d3815 --- /dev/null +++ b/testing/adios2/hierarchy/TestHierarchicalReading.cpp @@ -0,0 +1,106 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ +#include +#include + +#include +#include + +#include +#include + +#include + +class ADIOSHierarchicalReadVariableTest : public ::testing::Test +{ +public: + ADIOSHierarchicalReadVariableTest() = default; +}; + +TEST_F(ADIOSHierarchicalReadVariableTest, Read) +{ + std::string filename = "ADIOSHierarchicalReadVariable.bp"; + + int mpiRank = 0, mpiSize = 1; + // Number of rows + const std::size_t Nx = 8; + + // Number of steps + const std::size_t NSteps = 1; + +#if ADIOS2_USE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + + // Write test data using BP + { +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + adios2::IO io = adios.DeclareIO("TestIO"); + io.SetEngine("BPFile"); + + io.AddTransport("file"); + adios2::Engine engine = io.Open(filename, adios2::Mode::Write); + const adios2::Dims shape = {10}; + const adios2::Dims start = {0}; + const adios2::Dims count = {10}; + + auto var1 = io.DefineVariable( + "group1/group2/group3/group4/variable1", shape, start, count); + auto var2 = io.DefineVariable( + "group1/group2/group3/group4/variable2", shape, start, count); + auto var3 = io.DefineVariable( + "group1/group2/group3/group4/variable3", shape, start, count); + auto var4 = io.DefineVariable( + "group1/group2/group3/group4/variable4", shape, start, count); + auto var5 = io.DefineVariable( + "group1/group2/group3/group4/variable5", shape, start, count); + std::vector Ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + for (size_t step = 0; step < NSteps; ++step) + { + engine.BeginStep(); + + engine.Put(var1, Ints.data()); + engine.Put(var2, Ints.data()); + engine.Put(var3, Ints.data()); + engine.Put(var4, Ints.data()); + engine.Put(var5, Ints.data()); + + engine.EndStep(); + } + + for (int step = 0; step < NSteps; step++) + { + engine.BeginStep(); + auto g = io.GetGroup("group1", '/'); + auto res = g.AvailableGroups(); + EXPECT_EQ(res[0], "group2"); + g.setPath("group1/group2"); + res = g.AvailableGroups(); + EXPECT_EQ(res[0], "group3"); + g.setPath("group1/group2/group3"); + res = g.AvailableGroups(); + EXPECT_EQ(res[0], "group4"); + g.setPath("group1/group2/group3/group4"); + res = g.AvailableGroups(); + EXPECT_EQ(res.size(), 0); + res = g.AvailableVariables(); + EXPECT_EQ(res.size(), 5); + res = g.AvailableAttributes(); + EXPECT_EQ(res.size(), 0); + engine.EndStep(); + } + engine.Close(); + } +} +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From 508bbcf782c07f886b46f232bb09df4238e980c2 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Tue, 22 Sep 2020 10:53:29 -0400 Subject: [PATCH 02/10] Removed a redundant BuildTree function. --- source/adios2/core/IO.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index d880b39435..2fa1af0ee3 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -658,8 +658,6 @@ Group &IO::GetGroup(const std::string &path, char delimiter) { m_Gr = new Group(path, delimiter, *this); m_Gr->BuildTree(); - m_Gr->BuildTree(); - return *m_Gr; } Engine &IO::GetEngine(const std::string &name) From ae06d09d59bdae9992eaa9ffc968402a7d3336ba Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Tue, 22 Sep 2020 14:01:56 -0400 Subject: [PATCH 03/10] Fixed a memory leak. --- bindings/CXX11/adios2/cxx11/Group.cpp | 2 +- source/adios2/core/Group.cpp | 4 +--- source/adios2/core/IO.cpp | 4 +++- source/adios2/core/IO.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bindings/CXX11/adios2/cxx11/Group.cpp b/bindings/CXX11/adios2/cxx11/Group.cpp index 6647f38a70..7dfa336c77 100644 --- a/bindings/CXX11/adios2/cxx11/Group.cpp +++ b/bindings/CXX11/adios2/cxx11/Group.cpp @@ -64,7 +64,7 @@ DataType Group::AttributeType(const std::string &name) const helper::CheckForNullptr(m_Group, "in call to IO::AttributeType"); return m_Group->InquireAttributeType(name); } -Group::~Group() { m_Group->~Group(); } +Group::~Group(){}; // Explicit declaration of the public template methods // Limits the types #define declare_template_instantiation(T) \ diff --git a/source/adios2/core/Group.cpp b/source/adios2/core/Group.cpp index aecc2ae0dc..4c6dc0f7a9 100644 --- a/source/adios2/core/Group.cpp +++ b/source/adios2/core/Group.cpp @@ -198,9 +198,7 @@ std::map> &Group::getTreeMap() } std::string Group::InquirePath() { return currentPath; } -Group::~Group(){ - -}; +Group::~Group()= default; DataType Group::InquireVariableType(const std::string &name) const noexcept { diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index 2fa1af0ee3..1851240165 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -11,6 +11,7 @@ #include "IO.h" #include "IO.tcc" +#include #include #include #include // std::pair @@ -656,7 +657,8 @@ Engine &IO::Open(const std::string &name, const Mode mode) } Group &IO::GetGroup(const std::string &path, char delimiter) { - m_Gr = new Group(path, delimiter, *this); + + m_Gr = std::make_shared(path, delimiter, *this); m_Gr->BuildTree(); return *m_Gr; } diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index c1057213c4..167128376e 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -51,7 +51,7 @@ class IO /** reference to object that created current IO */ ADIOS &m_ADIOS; /** a pointer to a Group Object created from IO */ - Group *m_Gr; + std::shared_ptr m_Gr; /** unique identifier */ const std::string m_Name; From 529f3ab7c0e7fd3b29e8c7967fa1da30312d13f0 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Tue, 22 Sep 2020 14:49:23 -0400 Subject: [PATCH 04/10] Added missing header file --- bindings/CXX11/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/CXX11/CMakeLists.txt b/bindings/CXX11/CMakeLists.txt index bcfa0ce8de..6ac821bb52 100644 --- a/bindings/CXX11/CMakeLists.txt +++ b/bindings/CXX11/CMakeLists.txt @@ -80,6 +80,7 @@ install( FILES adios2/cxx11/ADIOS.h adios2/cxx11/ADIOS.inl adios2/cxx11/IO.h + adios2/cxx11/Group.h adios2/cxx11/Variable.h adios2/cxx11/Attribute.h adios2/cxx11/Engine.h From 984faa3f0020ffaa5fe0e95ed12b41597b72d240 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Tue, 22 Sep 2020 16:37:35 -0400 Subject: [PATCH 05/10] Added newline --- testing/adios2/hierarchy/TestHierarchicalReading.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/adios2/hierarchy/TestHierarchicalReading.cpp b/testing/adios2/hierarchy/TestHierarchicalReading.cpp index a5655d3815..ca11dd06a7 100644 --- a/testing/adios2/hierarchy/TestHierarchicalReading.cpp +++ b/testing/adios2/hierarchy/TestHierarchicalReading.cpp @@ -103,4 +103,4 @@ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +} From 7644bf942e1ffb995541ce940d347e001a3eb25a Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Wed, 23 Sep 2020 16:27:59 -0400 Subject: [PATCH 06/10] Removed a redundant include file --- bindings/CXX11/adios2/cxx11/Group.h | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/CXX11/adios2/cxx11/Group.h b/bindings/CXX11/adios2/cxx11/Group.h index 8265f53be8..a0043255f2 100644 --- a/bindings/CXX11/adios2/cxx11/Group.h +++ b/bindings/CXX11/adios2/cxx11/Group.h @@ -13,7 +13,6 @@ #include "Attribute.h" #include "Variable.h" -#include "adios2/core/Group.h" #include #include #include From 96e4d7dd833d65c281936351cdbf0f530a6fb781 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Wed, 23 Sep 2020 18:07:55 -0400 Subject: [PATCH 07/10] Removed unused variables in a test --- testing/adios2/hierarchy/TestHierarchicalReading.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/testing/adios2/hierarchy/TestHierarchicalReading.cpp b/testing/adios2/hierarchy/TestHierarchicalReading.cpp index ca11dd06a7..98939237fc 100644 --- a/testing/adios2/hierarchy/TestHierarchicalReading.cpp +++ b/testing/adios2/hierarchy/TestHierarchicalReading.cpp @@ -23,10 +23,6 @@ TEST_F(ADIOSHierarchicalReadVariableTest, Read) { std::string filename = "ADIOSHierarchicalReadVariable.bp"; - int mpiRank = 0, mpiSize = 1; - // Number of rows - const std::size_t Nx = 8; - // Number of steps const std::size_t NSteps = 1; From f32ccb5762375becb6981bf3a52b9bfc246aea2b Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 24 Sep 2020 09:25:58 -0400 Subject: [PATCH 08/10] Fixed clang formatting --- bindings/CXX11/adios2.h | 2 +- bindings/CXX11/adios2/cxx11/Group.h | 1 - bindings/CXX11/adios2/cxx11/Group.tcc | 4 ++-- bindings/CXX11/adios2/cxx11/IO.h | 2 +- bindings/CXX11/adios2/cxx11/Variable.h | 2 +- source/adios2/core/Group.cpp | 13 ++++++------- source/adios2/core/Group.h | 3 +-- source/adios2/core/IO.h | 14 +++++++------- 8 files changed, 19 insertions(+), 22 deletions(-) diff --git a/bindings/CXX11/adios2.h b/bindings/CXX11/adios2.h index 57b9c5a968..4e5d97de3a 100644 --- a/bindings/CXX11/adios2.h +++ b/bindings/CXX11/adios2.h @@ -27,12 +27,12 @@ constexpr bool DebugOFF = false; #include "adios2/cxx11/ADIOS.h" #include "adios2/cxx11/Attribute.h" #include "adios2/cxx11/Engine.h" +#include "adios2/cxx11/Group.h" #include "adios2/cxx11/IO.h" #include "adios2/cxx11/Operator.h" #include "adios2/cxx11/Query.h" #include "adios2/cxx11/Types.h" #include "adios2/cxx11/Variable.h" #include "adios2/cxx11/fstream/ADIOS2fstream.h" -#include "adios2/cxx11/Group.h" #endif /* ADIOS2_BINDINGS_CXX11_H_ */ diff --git a/bindings/CXX11/adios2/cxx11/Group.h b/bindings/CXX11/adios2/cxx11/Group.h index a0043255f2..a0888097aa 100644 --- a/bindings/CXX11/adios2/cxx11/Group.h +++ b/bindings/CXX11/adios2/cxx11/Group.h @@ -144,4 +144,3 @@ ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) } #endif // ADIOS2_BINDINGS_CXX11_CXX11_GROUP_H_ - diff --git a/bindings/CXX11/adios2/cxx11/Group.tcc b/bindings/CXX11/adios2/cxx11/Group.tcc index e051a62fa5..57966c0532 100644 --- a/bindings/CXX11/adios2/cxx11/Group.tcc +++ b/bindings/CXX11/adios2/cxx11/Group.tcc @@ -20,7 +20,7 @@ template Variable Group::InquireVariable(const std::string &name) { helper::CheckForNullptr(m_Group, "for variable name " + name + - ", in call to Group::InquireVariable"); + ", in call to Group::InquireVariable"); return Variable( m_Group->InquireVariable::IOType>(name)); } @@ -32,7 +32,7 @@ Attribute Group::InquireAttribute(const std::string &name, { using IOType = typename TypeInfo::IOType; helper::CheckForNullptr(m_Group, "for attribute name " + name + - ", in call to IO::InquireAttribute"); + ", in call to IO::InquireAttribute"); return Attribute( m_Group->InquireAttribute(name, variableName, separator)); } diff --git a/bindings/CXX11/adios2/cxx11/IO.h b/bindings/CXX11/adios2/cxx11/IO.h index bf1cfdb16d..b598fcf7ec 100644 --- a/bindings/CXX11/adios2/cxx11/IO.h +++ b/bindings/CXX11/adios2/cxx11/IO.h @@ -13,9 +13,9 @@ #include "Attribute.h" #include "Engine.h" +#include "Group.h" #include "Operator.h" #include "Variable.h" -#include "Group.h" #if ADIOS2_USE_MPI #include #endif diff --git a/bindings/CXX11/adios2/cxx11/Variable.h b/bindings/CXX11/adios2/cxx11/Variable.h index 13c64b210d..c1928f47c8 100644 --- a/bindings/CXX11/adios2/cxx11/Variable.h +++ b/bindings/CXX11/adios2/cxx11/Variable.h @@ -22,7 +22,7 @@ namespace adios2 // forward declare class IO; // friend class Engine; // friend -class Group; //friend +class Group; // friend namespace core { diff --git a/source/adios2/core/Group.cpp b/source/adios2/core/Group.cpp index 4c6dc0f7a9..f2f2004036 100644 --- a/source/adios2/core/Group.cpp +++ b/source/adios2/core/Group.cpp @@ -36,7 +36,7 @@ void Group::setPath(std::string path) { currentPath = path; } void Group::setDelimiter(char delimiter) { groupDelimiter = delimiter; } Group::Group(std::string path, char delimiter, IO &io) - : currentPath(path), groupDelimiter(delimiter), m_IO(io) +: currentPath(path), groupDelimiter(delimiter), m_IO(io) { if (mapPtr == nullptr) { @@ -45,7 +45,7 @@ Group::Group(std::string path, char delimiter, IO &io) } // copy constructor Group::Group(const Group &G) - : currentPath(G.currentPath), groupDelimiter(G.groupDelimiter), m_IO(G.m_IO) +: currentPath(G.currentPath), groupDelimiter(G.groupDelimiter), m_IO(G.m_IO) { mapPtr = G.mapPtr; } @@ -198,17 +198,16 @@ std::map> &Group::getTreeMap() } std::string Group::InquirePath() { return currentPath; } -Group::~Group()= default; +Group::~Group() = default; DataType Group::InquireVariableType(const std::string &name) const noexcept { return m_IO.InquireVariableType(currentPath + groupDelimiter + name); } -DataType -Group::InquireAttributeType(const std::string &name, - const std::string &variableName, - const std::string separator) const noexcept +DataType Group::InquireAttributeType(const std::string &name, + const std::string &variableName, + const std::string separator) const noexcept { return m_IO.InquireAttributeType(name, variableName, separator); } diff --git a/source/adios2/core/Group.h b/source/adios2/core/Group.h index 6cc806edcc..65a2b7629a 100644 --- a/source/adios2/core/Group.h +++ b/source/adios2/core/Group.h @@ -21,7 +21,7 @@ namespace core { /** used for Variables and Attributes, name, type, type-index */ using DataMap = -std::unordered_map>; + std::unordered_map>; class Group { private: @@ -158,4 +158,3 @@ ADIOS2_FOREACH_STDTYPE_1ARG(declare_template_instantiation) } // end namespace adios2 #endif // ADIOS2_CORE_GROUP_H - diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index 167128376e..c2881e9fed 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -25,9 +25,9 @@ #include "adios2/common/ADIOSTypes.h" #include "adios2/core/ADIOS.h" #include "adios2/core/Attribute.h" +#include "adios2/core/Group.h" #include "adios2/core/Variable.h" #include "adios2/core/VariableCompound.h" -#include "adios2/core/Group.h" namespace adios2 { @@ -286,8 +286,8 @@ class IO * @param itVariable * @return type primitive type */ - DataType InquireVariableType(const VarMap::const_iterator itVariable) const - noexcept; + DataType + InquireVariableType(const VarMap::const_iterator itVariable) const noexcept; /** * Retrieves hash holding internal variable identifiers @@ -325,10 +325,10 @@ class IO * @param name input attribute name * @return type if found returns type as string, otherwise an empty string */ - DataType InquireAttributeType(const std::string &name, - const std::string &variableName = "", - const std::string separator = "/") const - noexcept; + DataType + InquireAttributeType(const std::string &name, + const std::string &variableName = "", + const std::string separator = "/") const noexcept; /** * @brief Retrieve map with attributes info. Use when reading. From 89f4d7dfb97db715c9391f7522b5759a734a3703 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 24 Sep 2020 10:08:19 -0400 Subject: [PATCH 09/10] Fixed clang formatting --- source/adios2/core/Group.h | 6 +++--- source/adios2/core/IO.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/adios2/core/Group.h b/source/adios2/core/Group.h index 65a2b7629a..52d3e5b643 100644 --- a/source/adios2/core/Group.h +++ b/source/adios2/core/Group.h @@ -142,10 +142,10 @@ class Group * @param name input attribute name * @return type if found returns type as string, otherwise an empty string */ - DataType - InquireAttributeType(const std::string &name, + DataType InquireAttributeType(const std::string &name, const std::string &variableName = "", - const std::string separator = "/") const noexcept; + const std::string separator = "/") const + noexcept; }; // Explicit declaration of the public template methods #define declare_template_instantiation(T) \ diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index c2881e9fed..4e9a6a5292 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -286,8 +286,8 @@ class IO * @param itVariable * @return type primitive type */ - DataType - InquireVariableType(const VarMap::const_iterator itVariable) const noexcept; + DataType InquireVariableType(const VarMap::const_iterator itVariable) const + noexcept; /** * Retrieves hash holding internal variable identifiers @@ -325,10 +325,10 @@ class IO * @param name input attribute name * @return type if found returns type as string, otherwise an empty string */ - DataType - InquireAttributeType(const std::string &name, + DataType InquireAttributeType(const std::string &name, const std::string &variableName = "", - const std::string separator = "/") const noexcept; + const std::string separator = "/") const + noexcept; /** * @brief Retrieve map with attributes info. Use when reading. From 39a0f215b53a87b48dc5c19dd2367c9be586dc1e Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 24 Sep 2020 10:43:17 -0400 Subject: [PATCH 10/10] Fixed clang formatting --- source/adios2/core/Group.h | 4 ++-- source/adios2/core/IO.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/adios2/core/Group.h b/source/adios2/core/Group.h index 52d3e5b643..79879d0f38 100644 --- a/source/adios2/core/Group.h +++ b/source/adios2/core/Group.h @@ -143,8 +143,8 @@ class Group * @return type if found returns type as string, otherwise an empty string */ DataType InquireAttributeType(const std::string &name, - const std::string &variableName = "", - const std::string separator = "/") const + const std::string &variableName = "", + const std::string separator = "/") const noexcept; }; // Explicit declaration of the public template methods diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index 4e9a6a5292..361a1cad14 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -326,8 +326,8 @@ class IO * @return type if found returns type as string, otherwise an empty string */ DataType InquireAttributeType(const std::string &name, - const std::string &variableName = "", - const std::string separator = "/") const + const std::string &variableName = "", + const std::string separator = "/") const noexcept; /**