diff --git a/include/openPMD/Series.hpp b/include/openPMD/Series.hpp
index 2000920c6e..a81fc0eda5 100644
--- a/include/openPMD/Series.hpp
+++ b/include/openPMD/Series.hpp
@@ -127,6 +127,33 @@ class Series : public Attributable
*/
Series& setMeshesPath(std::string const& meshesPath);
+ /**
+ * @throw no_such_attribute_error If optional attribute is not present.
+ * @return Vector with a String per (writing) MPI rank, indicating user-
+ * defined meta information per rank. Example: host name.
+ */
+ chunk_assignment::RankMeta
+ mpiRanksMetaInfo() const;
+
+ /**
+ * @brief Set the Mpi Ranks Meta Info attribute, i.e. a Vector with
+ * a String per (writing) MPI rank, indicating user-
+ * defined meta information per rank. Example: host name.
+ *
+ * @return Reference to modified series.
+ */
+ Series & setMpiRanksMetaInfo( chunk_assignment::RankMeta );
+
+ /**
+ * @brief Set the Mpi Ranks Meta Info attribute, i.e. a Vector with
+ * a String per (writing) MPI rank, indicating user-
+ * defined meta information per rank. Example: host name.
+ *
+ * @return Reference to modified series.
+ */
+ Series &
+ setMpiRanksMetaInfo( std::string const & myRankInfo );
+
/**
* @throw no_such_attribute_error If optional attribute is not present.
* @return String representing the path to particle species, relative(!) to basePath
.
@@ -376,6 +403,9 @@ class Series : public Attributable
std::shared_ptr< auxiliary::Option< WriteIterations > > m_writeIterations =
std::make_shared< auxiliary::Option< WriteIterations > >();
+#if openPMD_HAVE_MPI
+ MPI_Comm m_communicator;
+#endif
}; // Series
/**
diff --git a/include/openPMD/auxiliary/Filesystem.hpp b/include/openPMD/auxiliary/Filesystem.hpp
index 686cbf1384..a5d20250d7 100644
--- a/include/openPMD/auxiliary/Filesystem.hpp
+++ b/include/openPMD/auxiliary/Filesystem.hpp
@@ -100,5 +100,20 @@ std::string
collective_file_read( std::string const & path, MPI_Comm );
#endif
-} // namespace auxiliary
-} // namespace openPMD
+
+struct no_such_file_error
+{
+};
+
+/**
+ * @brief Read a file line by line.
+ *
+ * @param path Path to the file.
+ * @return Lines of the read file, excluding newline characters.
+ *
+ * @throws no_such_file_error
+ */
+std::vector< std::string >
+read_file_by_lines( std::string const & path );
+} // auxiliary
+} // openPMD
diff --git a/include/openPMD/auxiliary/MPI.hpp b/include/openPMD/auxiliary/MPI.hpp
index 9527907e0f..04504d42af 100644
--- a/include/openPMD/auxiliary/MPI.hpp
+++ b/include/openPMD/auxiliary/MPI.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "openPMD/config.hpp"
+
#if openPMD_HAVE_MPI
# include
diff --git a/src/Series.cpp b/src/Series.cpp
index 6b9af1b9ef..7fb33431c3 100644
--- a/src/Series.cpp
+++ b/src/Series.cpp
@@ -20,6 +20,7 @@
*/
#include "openPMD/auxiliary/Date.hpp"
#include "openPMD/auxiliary/Filesystem.hpp"
+#include "openPMD/auxiliary/MPI.hpp"
#include "openPMD/auxiliary/StringManip.hpp"
#include "openPMD/IO/AbstractIOHandler.hpp"
#include "openPMD/IO/AbstractIOHandlerHelper.hpp"
@@ -81,6 +82,7 @@ Series::Series(
std::string const & options )
: iterations{ Container< Iteration, uint64_t >() }
, m_iterationEncoding{ std::make_shared< IterationEncoding >() }
+ , m_communicator{ comm }
{
auto input = parseInput( filepath );
auto handler =
@@ -182,6 +184,90 @@ Series::setMeshesPath(std::string const& mp)
return *this;
}
+chunk_assignment::RankMeta
+Series::mpiRanksMetaInfo() const
+{
+ std::vector< std::string > asContiguousVector;
+ try
+ {
+ asContiguousVector =
+ getAttribute( "rankMetaInfo" ).get< std::vector< std::string > >();
+ }
+ catch( std::runtime_error const & )
+ {
+ // workaround: if vector has length 1, some backends may report a
+ // single value instead of a vector
+ asContiguousVector = {
+ getAttribute( "rankMetaInfo" ).get< std::string >()
+ };
+ }
+ chunk_assignment::RankMeta res;
+ for( size_t i = 0; i < asContiguousVector.size(); ++i )
+ {
+ res[ i ] = std::move( asContiguousVector[ i ] );
+ }
+ return res;
+}
+
+Series &
+Series::setMpiRanksMetaInfo( chunk_assignment::RankMeta rankMeta )
+{
+ std::vector< std::string > asContiguousVector;
+ asContiguousVector.reserve( rankMeta.size() );
+ try
+ {
+ for( size_t i = 0; i < rankMeta.size(); ++i )
+ {
+ asContiguousVector.emplace_back( std::move( rankMeta.at( i ) ) );
+ }
+ }
+ catch( std::out_of_range )
+ {
+ throw std::runtime_error( "[setMpiRanksMetaInfo] Can only set meta "
+ "info for contiguous ranks 0 to n." );
+ }
+
+ setAttribute( "rankMetaInfo", std::move( asContiguousVector ) );
+ return *this;
+}
+
+Series &
+Series::setMpiRanksMetaInfo( std::string const & myRankInfo )
+{
+ if( auxiliary::starts_with( myRankInfo, '@' ) )
+ {
+ // read from file
+ std::string fileName = auxiliary::replace_first( myRankInfo, "@", "" );
+ std::vector< std::string > rankMeta;
+ try
+ {
+ rankMeta = auxiliary::read_file_by_lines( fileName );
+ }
+ catch( auxiliary::no_such_file_error const & )
+ {
+ std::cerr << "Not setting rank meta information, because file has "
+ "not been found: "
+ << fileName << std::endl;
+ return *this;
+ }
+ setAttribute( "rankMetaInfo", rankMeta );
+ return *this;
+ }
+#if openPMD_HAVE_MPI
+ int rank;
+ MPI_Comm_rank( m_communicator, &rank );
+ std::vector< std::string > rankMeta =
+ auxiliary::collectStringsTo( m_communicator, 0, myRankInfo );
+ if( rank == 0 )
+ {
+ setAttribute( "rankMetaInfo", std::move( rankMeta ) );
+ }
+ return *this;
+#else
+ setAttribute( "rankMetaInfo", std::vector< std::string >{ myRankInfo } );
+#endif
+}
+
std::string
Series::particlesPath() const
{
diff --git a/src/auxiliary/Filesystem.cpp b/src/auxiliary/Filesystem.cpp
index 4bd7765a4d..59fa0534c1 100644
--- a/src/auxiliary/Filesystem.cpp
+++ b/src/auxiliary/Filesystem.cpp
@@ -35,6 +35,8 @@
#include
#include
#include
+#include
+#include
namespace openPMD
@@ -258,5 +260,22 @@ collective_file_read( std::string const & path, MPI_Comm comm )
#endif
-} // namespace auxiliary
-} // namespace openPMD
+std::vector< std::string >
+read_file_by_lines( std::string const & path )
+{
+ std::vector< std::string > res;
+ std::ifstream file( path, std::ios_base::in );
+ if ( file.fail( ) )
+ {
+ throw no_such_file_error( );
+ }
+ std::string line;
+ while( std::getline( file, line ) )
+ {
+ res.push_back( std::move( line ) );
+ line = std::string( );
+ }
+ return res;
+}
+} // auxiliary
+} // openPMD
diff --git a/test/CoreTest.cpp b/test/CoreTest.cpp
index 0565a2fd0a..c09d7a0556 100644
--- a/test/CoreTest.cpp
+++ b/test/CoreTest.cpp
@@ -4,7 +4,7 @@
# define OPENPMD_protected public
#endif
-#include "openPMD/Chunk.hpp"
+#include "openPMD/ChunkInfo.hpp"
#include "openPMD/openPMD.hpp"
#include
@@ -56,7 +56,7 @@ print( ChunkTable const & table )
{
for( auto const & chunk : table )
{
- std::cout << "[Rank: " << chunk.mpi_rank << ",\tOffset: ";
+ std::cout << "[Rank: " << chunk.sourceID << ",\tOffset: ";
for( auto offset : chunk.offset )
{
std::cout << offset << ", ";