diff --git a/include/openPMD/auxiliary/StringManip.hpp b/include/openPMD/auxiliary/StringManip.hpp index 2ba041e5cf..66ad258554 100644 --- a/include/openPMD/auxiliary/StringManip.hpp +++ b/include/openPMD/auxiliary/StringManip.hpp @@ -243,6 +243,13 @@ namespace auxiliary return std::forward(s); } + /** Create a string representation of a vector or another iterable + * container. + * + * @param v The vector or other iterable container. + * @return A string that shows the items of the container. Each item is + * formatted using the default definition for operator<<(). + */ template auto format_vec(Vec const &v) -> std::string { @@ -254,6 +261,7 @@ namespace auxiliary auto end = v.end(); std::stringstream res; res << '[' << *it++; + res.operator<<(*it); for (; it != end; ++it) { res << ", " << *it; diff --git a/test/ParallelIOTest.cpp b/test/ParallelIOTest.cpp index e835dd88af..ecc9f48eac 100644 --- a/test/ParallelIOTest.cpp +++ b/test/ParallelIOTest.cpp @@ -4,6 +4,7 @@ #include "openPMD/IO/ADIOS/macros.hpp" #include "openPMD/auxiliary/Environment.hpp" #include "openPMD/auxiliary/Filesystem.hpp" +#include "openPMD/backend/PatchRecordComponent.hpp" #include "openPMD/openPMD.hpp" #include @@ -397,7 +398,7 @@ void available_chunks_test(std::string const &file_ending) MPI_Comm_size(MPI_COMM_WORLD, &r_mpi_size); unsigned mpi_rank{static_cast(r_mpi_rank)}, mpi_size{static_cast(r_mpi_size)}; - std::string name = "../samples/available_chunks." + file_ending; + std::string name = "../samples/parallel_available_chunks." + file_ending; /* * ADIOS2 assigns writerIDs to blocks in a BP file by id of the substream @@ -410,7 +411,6 @@ void available_chunks_test(std::string const &file_ending) { "engine": { - "type": "bp4", "parameters": { "NumAggregators":)END" @@ -429,6 +429,14 @@ void available_chunks_test(std::string const &file_ending) E_x.resetDataset({Datatype::INT, {mpi_size, 4}}); E_x.storeChunk(data, {mpi_rank, 0}, {1, 4}); + /* + * Verify that block decomposition also works in "local value" variable + * shape. That shape instructs the data to participate in ADIOS2 + * metadata aggregation, hence there is only one "real" written block, + * the aggregated one. We still need the original logical blocks to be + * present in reading. + */ + auto electrons = it0.particles["e"].particlePatches; auto numParticles = electrons["numParticles"]; auto numParticlesOffset = electrons["numParticlesOffset"]; @@ -501,12 +509,40 @@ void available_chunks_test(std::string const &file_ending) { REQUIRE(ranks[i] == i); } + + auto electrons = it0.particles["e"].particlePatches; + for (PatchRecordComponent *prc : + {static_cast(&electrons["numParticles"]), + static_cast( + &electrons["numParticlesOffset"]), + &electrons["offset"]["x"], + &electrons["offset"]["y"], + &electrons["extent"]["z"], + &electrons["offset"]["x"], + &electrons["extent"]["y"], + &electrons["extent"]["z"]}) + { + auto available_chunks = prc->availableChunks(); + REQUIRE(size_t(r_mpi_size) == available_chunks.size()); + for (size_t i = 0; i < available_chunks.size(); ++i) + { + auto const &chunk = available_chunks[i]; + REQUIRE(chunk.extent == Extent{1}); + REQUIRE(chunk.offset == Offset{i}); + REQUIRE(chunk.sourceID == i); + } + } } } TEST_CASE("available_chunks_test", "[parallel][adios]") { +#if HAS_ADIOS_2_9 + available_chunks_test("bp4"); + available_chunks_test("bp5"); +#else available_chunks_test("bp"); +#endif } #endif