diff --git a/bindings/CXX11/adios2/cxx11/IO.cpp b/bindings/CXX11/adios2/cxx11/IO.cpp index 4c63287587..64fcf8204c 100644 --- a/bindings/CXX11/adios2/cxx11/IO.cpp +++ b/bindings/CXX11/adios2/cxx11/IO.cpp @@ -109,9 +109,9 @@ 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::InquireGroup(const std::string &path, char delimiter) +Group IO::InquireGroup(char delimiter) { - return Group(&m_IO->CreateGroup(path, delimiter)); + return Group(&m_IO->CreateGroup(delimiter)); }; void IO::FlushAll() { diff --git a/bindings/CXX11/adios2/cxx11/IO.h b/bindings/CXX11/adios2/cxx11/IO.h index 3e4dee8ebc..49067e7512 100644 --- a/bindings/CXX11/adios2/cxx11/IO.h +++ b/bindings/CXX11/adios2/cxx11/IO.h @@ -262,7 +262,7 @@ class IO * @param a delimiter to separate groups in a string representation * @return Group object */ - Group InquireGroup(const std::string &path, char delimiter = '/'); + Group InquireGroup(char delimiter = '/'); #if ADIOS2_USE_MPI /** diff --git a/source/adios2/core/Group.cpp b/source/adios2/core/Group.cpp index 216377b955..1c862b9f85 100644 --- a/source/adios2/core/Group.cpp +++ b/source/adios2/core/Group.cpp @@ -32,7 +32,7 @@ std::vector split(const std::string &s, char delimiter) } return tokens; } -void Group::setPath(std::string path) { currentPath = path; } +void Group::setPath(std::string path) { currentPath = ADIOS_root + "/" + path; } void Group::setDelimiter(char delimiter) { groupDelimiter = delimiter; } Group::Group(std::string path, char delimiter, IO &io) @@ -51,10 +51,13 @@ Group::Group(const Group &G) } Group *Group::InquireGroup(std::string groupName) { - Group *g_out = new Group(currentPath + groupDelimiter + groupName, - this->groupDelimiter, this->m_IO); - g_out->mapPtr = this->mapPtr; - return g_out; + if (currentPath.compare("") != 0) + { + groupName = currentPath + groupDelimiter + groupName; + } + m_Gr = std::make_shared(groupName, this->groupDelimiter, this->m_IO); + m_Gr->mapPtr = this->mapPtr; + return m_Gr.get(); } void Group::PrintTree() { @@ -74,6 +77,12 @@ void Group::BuildTree() { std::vector tokens = split(variablePair.first, groupDelimiter); + // Adding artificial root element + if (tokens[0] == "") + tokens[0] = ADIOS_root; + else + tokens.insert(tokens.begin(), ADIOS_root); + currentPath = ADIOS_root; if (tokens.size() == 0) { @@ -83,7 +92,7 @@ void Group::BuildTree() { // case record = "/group1" or "group/" } - if (tokens.size() > 1) + else { std::string key = tokens[0]; for (int level = 1; level < tokens.size(); level++) @@ -140,9 +149,10 @@ std::vector Group::AvailableVariables() mapPtr->treeMap.end()) { const core::VarMap &variables = m_IO.GetVariables(); - - if (variables.find(currentPath + groupDelimiter + v) != - variables.end()) + std::string variablePath = currentPath + groupDelimiter + v; + variablePath = variablePath.substr( + ADIOS_root.size() + 1, variablePath.size() - ADIOS_root.size()); + if (variables.find(variablePath) != variables.end()) { available_variables.push_back(v); } @@ -164,8 +174,10 @@ std::vector Group::AvailableAttributes() mapPtr->treeMap.end()) { const core::AttrMap &attributes = m_IO.GetAttributes(); - if (attributes.find(currentPath + groupDelimiter + v) != - attributes.end()) + std::string variablePath = currentPath + groupDelimiter + v; + variablePath = variablePath.substr( + ADIOS_root.size() + 1, variablePath.size() - ADIOS_root.size()); + if (attributes.find(variablePath) != attributes.end()) { available_attributes.push_back(v); } @@ -180,14 +192,14 @@ 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); + for (auto v : val) + { + if (mapPtr->treeMap.find(currentPath + groupDelimiter + v) != + mapPtr->treeMap.end()) + available_groups.push_back(v); + } } - return available_groups; } diff --git a/source/adios2/core/Group.h b/source/adios2/core/Group.h index c81735b1e8..59fc211d73 100644 --- a/source/adios2/core/Group.h +++ b/source/adios2/core/Group.h @@ -35,6 +35,8 @@ class Group char groupDelimiter; /** shared pointer to a map representing the tree structure */ std::shared_ptr mapPtr = nullptr; + /** root of the tree */ + const std::string ADIOS_root = "_ADIOS_ROOT_"; public: /** @@ -50,6 +52,8 @@ class Group Group(const Group &G); /** destructor */ ~Group(); + /** a pointer to a Group Object */ + std::shared_ptr m_Gr; /** * @brief Builds map that represents tree structure from m_Variable and * m_Attributes from IO class diff --git a/source/adios2/core/Group.tcc b/source/adios2/core/Group.tcc index da5c883115..3741e7d701 100644 --- a/source/adios2/core/Group.tcc +++ b/source/adios2/core/Group.tcc @@ -20,8 +20,10 @@ namespace core template Variable *Group::InquireVariable(const std::string &name) noexcept { - Variable &variable = - *m_IO.InquireVariable(currentPath + groupDelimiter + name); + std::string variablePath = currentPath + groupDelimiter + name; + variablePath = variablePath.substr(ADIOS_root.size() + 1, + variablePath.size() - ADIOS_root.size()); + Variable &variable = *m_IO.InquireVariable(variablePath); return &variable; } @@ -30,8 +32,11 @@ 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); + std::string variablePath = currentPath + groupDelimiter + name; + variablePath = variablePath.substr(ADIOS_root.size() + 1, + variablePath.size() - ADIOS_root.size()); + Attribute &attribute = + m_IO.InquireAttribute(variablePath, variableName, separator); return &attribute; } } // end namespace core diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index af026ab02e..369529dfeb 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -655,10 +655,9 @@ Engine &IO::Open(const std::string &name, const Mode mode) { return Open(name, mode, m_ADIOS.GetComm().Duplicate()); } -Group &IO::CreateGroup(const std::string &path, char delimiter) +Group &IO::CreateGroup(char delimiter) { - - m_Gr = std::make_shared(path, delimiter, *this); + m_Gr = std::make_shared("", delimiter, *this); m_Gr->BuildTree(); return *m_Gr; } diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index b63f136152..9d77006057 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -412,7 +412,7 @@ class IO */ void FlushAll(); - Group &CreateGroup(const std::string &path, char delimiter); + Group &CreateGroup(char delimiter); // READ FUNCTIONS, not yet implemented: /** diff --git a/testing/adios2/hierarchy/TestHierarchicalReading.cpp b/testing/adios2/hierarchy/TestHierarchicalReading.cpp index 0637494ac9..dfd4e31d8d 100644 --- a/testing/adios2/hierarchy/TestHierarchicalReading.cpp +++ b/testing/adios2/hierarchy/TestHierarchicalReading.cpp @@ -24,11 +24,16 @@ TEST_F(ADIOSHierarchicalReadVariableTest, Read) std::string filename = "ADIOSHierarchicalReadVariable.bp"; // Number of steps - const std::size_t NSteps = 1; + const std::size_t NSteps = 2; + + long unsigned int rank, size; #if ADIOS2_USE_MPI - MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); - MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); +#else + rank = 0; + size = 1; #endif // Write test data using BP @@ -43,9 +48,10 @@ TEST_F(ADIOSHierarchicalReadVariableTest, Read) 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}; + const std::size_t Nx = 10; + const adios2::Dims shape = {size * Nx}; + const adios2::Dims start = {rank * Nx}; + const adios2::Dims count = {Nx}; auto var1 = io.DefineVariable( "group1/group2/group3/group4/variable1", shape, start, count); @@ -57,7 +63,10 @@ TEST_F(ADIOSHierarchicalReadVariableTest, Read) "group1/group2/group3/group4/variable4", shape, start, count); auto var5 = io.DefineVariable( "group1/group2/group3/group4/variable5", shape, start, count); + auto var6 = + io.DefineVariable("variable6", 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(); @@ -67,16 +76,21 @@ TEST_F(ADIOSHierarchicalReadVariableTest, Read) engine.Put(var3, Ints.data()); engine.Put(var4, Ints.data()); engine.Put(var5, Ints.data()); + engine.Put(var6, Ints.data()); engine.EndStep(); } + engine.Close(); + engine = io.Open(filename, adios2::Mode::Read); for (int step = 0; step < NSteps; step++) { engine.BeginStep(); - auto g = io.InquireGroup("group1", '/'); + auto g = io.InquireGroup('/'); auto res = g.AvailableGroups(); - EXPECT_EQ(res[0], "group2"); + EXPECT_EQ(res[0], "group1"); + res = g.AvailableVariables(); + EXPECT_EQ(res[0], "variable6"); g.setPath("group1/group2"); res = g.AvailableGroups(); EXPECT_EQ(res[0], "group3"); @@ -92,6 +106,44 @@ TEST_F(ADIOSHierarchicalReadVariableTest, Read) EXPECT_EQ(res.size(), 0); engine.EndStep(); } + for (int step = 0; step < NSteps; step++) + { + engine.BeginStep(); + auto g = io.InquireGroup('/'); + auto res = g.AvailableGroups(); + EXPECT_EQ(res[0], "group1"); + res = g.AvailableVariables(); + EXPECT_EQ(res[0], "variable6"); + engine.EndStep(); + } + for (int step = 0; step < NSteps; step++) + { + auto g = io.InquireGroup('/'); + auto var = g.InquireVariable("variable6"); + EXPECT_TRUE(var); + if (var) + { + std::vector myInts; + var.SetSelection({{Nx * rank}, {Nx}}); + engine.Get(var, myInts, adios2::Mode::Sync); + EXPECT_EQ(Ints, myInts); + } + } + for (int step = 0; step < NSteps; step++) + { + auto g = io.InquireGroup('/'); + g.setPath("group1/group2/group3/group4"); + auto var = g.InquireVariable("variable1"); + EXPECT_TRUE(var); + if (var) + { + std::vector myInts; + var.SetSelection({{Nx * rank}, {Nx}}); + engine.Get(var, myInts, adios2::Mode::Sync); + + EXPECT_EQ(Ints, myInts); + } + } engine.Close(); } }