openPMD-api
Series.hpp
1 /* Copyright 2017-2021 Fabian Koller, Axel Huebl
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 #pragma once
22 
23 #include "openPMD/Error.hpp"
24 #include "openPMD/IO/AbstractIOHandler.hpp"
25 #include "openPMD/IO/Access.hpp"
26 #include "openPMD/IO/Format.hpp"
27 #include "openPMD/Iteration.hpp"
28 #include "openPMD/IterationEncoding.hpp"
29 #include "openPMD/Streaming.hpp"
30 #include "openPMD/WriteIterations.hpp"
31 #include "openPMD/auxiliary/Variant.hpp"
32 #include "openPMD/backend/Attributable.hpp"
33 #include "openPMD/backend/Container.hpp"
34 #include "openPMD/backend/ParsePreference.hpp"
35 #include "openPMD/config.hpp"
36 #include "openPMD/version.hpp"
37 
38 #if openPMD_HAVE_MPI
39 #include <mpi.h>
40 #endif
41 
42 #include <cstdint> // uint64_t
43 #include <deque>
44 #include <functional>
45 #include <map>
46 #include <memory>
47 #include <optional>
48 #include <set>
49 #include <stdexcept>
50 #include <string>
51 #include <tuple>
52 
53 // expose private and protected members for invasive testing
54 #ifndef OPENPMD_private
55 #define OPENPMD_private private:
56 #endif
57 
58 namespace openPMD
59 {
60 class ReadIterations;
61 class SeriesIterator;
62 class Series;
63 class Series;
64 
65 namespace internal
66 {
78  class SeriesData final : public AttributableData
79  {
80  public:
81  explicit SeriesData() = default;
82 
83  virtual ~SeriesData();
84 
85  SeriesData(SeriesData const &) = delete;
86  SeriesData(SeriesData &&) = delete;
87 
88  SeriesData &operator=(SeriesData const &) = delete;
89  SeriesData &operator=(SeriesData &&) = delete;
90 
91  using IterationIndex_t = Iteration::IterationIndex_t;
93  IterationsContainer_t iterations{};
94 
101  std::optional<WriteIterations> m_writeIterations;
102 
118  std::unique_ptr<SeriesIterator> m_sharedStatefulIterator;
124  std::set<IterationIndex_t> m_currentlyActiveIterations;
134  std::optional<std::string> m_overrideFilebasedFilename;
141  std::string m_name;
146  std::string m_filenamePrefix;
150  std::string m_filenamePostfix;
155  std::string m_filenameExtension;
177  StepStatus m_stepStatus = StepStatus::NoStep;
181  bool m_parseLazily = false;
182 
191 
198  std::optional<ParsePreference> m_parsePreference;
199 
200  std::optional<std::function<AbstractIOHandler *(Series &)>>
201  m_deferred_initialization = std::nullopt;
202 
203  void close();
204  }; // SeriesData
205 
206  class SeriesInternal;
207 } // namespace internal
208 
218 class Series : public Attributable
219 {
220  friend class Attributable;
221  friend class Iteration;
222  friend class Writable;
223  friend class ReadIterations;
224  friend class SeriesIterator;
225  friend class internal::SeriesData;
226  friend class WriteIterations;
227 
228 public:
229  explicit Series();
230 
231 #if openPMD_HAVE_MPI
244  Series(
245  std::string const &filepath,
246  Access at,
247  MPI_Comm comm,
248  std::string const &options = "{}");
249 #endif
250 
297  Series(
298  std::string const &filepath,
299  Access at,
300  std::string const &options = "{}");
301 
302  Series(Series const &) = default;
303  Series(Series &&) = default;
304 
305  Series &operator=(Series const &) = default;
306  Series &operator=(Series &&) = default;
307 
308  ~Series() override = default;
309 
313  using IterationIndex_t = Iteration::IterationIndex_t;
318  IterationsContainer_t iterations;
319 
326  operator bool() const;
327 
333  std::string openPMD() const;
342  Series &setOpenPMD(std::string const &openPMD);
343 
349  uint32_t openPMDextension() const;
359 
364  std::string basePath() const;
372  Series &setBasePath(std::string const &basePath);
373 
379  std::string meshesPath() const;
389  Series &setMeshesPath(std::string const &meshesPath);
390 
396  std::string particlesPath() const;
406  Series &setParticlesPath(std::string const &particlesPath);
407 
413  std::string author() const;
420  Series &setAuthor(std::string const &author);
421 
427  std::string software() const;
437  std::string const &newName,
438  std::string const &newVersion = std::string("unspecified"));
439 
445  std::string softwareVersion() const;
455  [[deprecated(
456  "Set the version with the second argument of setSoftware()")]] Series &
457  setSoftwareVersion(std::string const &softwareVersion);
458 
463  std::string date() const;
469  Series &setDate(std::string const &date);
470 
476  std::string softwareDependencies() const;
484  Series &setSoftwareDependencies(std::string const &newSoftwareDependencies);
485 
491  std::string machine() const;
498  Series &setMachine(std::string const &newMachine);
499 
522 
528  std::string iterationFormat() const;
540  Series &setIterationFormat(std::string const &iterationFormat);
541 
545  std::string name() const;
546 
553  Series &setName(std::string const &name);
554 
561  std::string backend() const;
562  std::string backend();
563 
571  void flush(std::string backendConfig = "{}");
572 
589 
604  void parseBase();
605 
624 
635  void close();
636 
637  // clang-format off
638 OPENPMD_private
639  // clang-format on
640 
641  static constexpr char const *const BASEPATH = "/data/%T/";
642 
643  struct ParsedInput;
644  using iterations_t = decltype(internal::SeriesData::iterations);
645  using iterations_iterator = iterations_t::iterator;
646 
648  std::shared_ptr<Data_t> m_series = nullptr;
649 
650  inline Data_t &get()
651  {
652  if (m_series)
653  {
654  return *m_series;
655  }
656  else
657  {
658  throw std::runtime_error(
659  "[Series] Cannot use default-constructed Series.");
660  }
661  }
662 
663  inline Data_t const &get() const
664  {
665  if (m_series)
666  {
667  return *m_series;
668  }
669  else
670  {
671  throw std::runtime_error(
672  "[Series] Cannot use default-constructed Series.");
673  }
674  }
675 
676  inline void setData(std::shared_ptr<internal::SeriesData> series)
677  {
678  m_series = std::move(series);
679  iterations = m_series->iterations;
680  Attributable::setData(m_series);
681  }
682 
683  std::unique_ptr<ParsedInput> parseInput(std::string);
693  template <typename TracingJSON>
694  void parseJsonOptions(TracingJSON &options, ParsedInput &);
695  bool hasExpansionPattern(std::string filenameWithExtension);
696  bool reparseExpansionPattern(std::string filenameWithExtension);
697  template <typename... MPI_Communicator>
698  void init(
699  std::string const &filepath,
700  Access at,
701  std::string const &options,
702  MPI_Communicator &&...);
703  template <typename TracingJSON, typename... MPI_Communicator>
704  std::tuple<std::unique_ptr<ParsedInput>, TracingJSON> initIOHandler(
705  std::string const &filepath,
706  std::string const &options,
707  Access at,
708  bool resolve_generic_extension,
709  MPI_Communicator &&...);
710  void initSeries(
711  std::unique_ptr<AbstractIOHandler>, std::unique_ptr<ParsedInput>);
712  void initDefaults(IterationEncoding, bool initAll = false);
724  std::future<void> flush_impl(
725  iterations_iterator begin,
726  iterations_iterator end,
727  internal::FlushParams const &flushParams,
728  bool flushIOHandler = true);
729  void flushFileBased(
730  iterations_iterator begin,
731  iterations_iterator end,
732  internal::FlushParams const &flushParams,
733  bool flushIOHandler = true);
734  /*
735  * Group-based and variable-based iteration layouts share a lot of logic
736  * (realistically, the variable-based iteration layout only throws out
737  * one layer in the hierarchy).
738  * As a convention, methods that deal with both layouts are called
739  * .*GorVBased, short for .*GroupOrVariableBased
740  */
741  void flushGorVBased(
742  iterations_iterator begin,
743  iterations_iterator end,
744  internal::FlushParams const &flushParams,
745  bool flushIOHandler = true);
746  void flushMeshesPath();
747  void flushParticlesPath();
748  void readFileBased();
749  void readOneIterationFileBased(std::string const &filePath);
763  std::optional<std::deque<IterationIndex_t>> readGorVBased(
764  bool do_always_throw_errors,
765  bool init,
766  std::set<IterationIndex_t> const &ignoreIterations = {});
767  void readBase();
768  std::string iterationFilename(IterationIndex_t i);
769 
770  enum class IterationOpened : bool
771  {
772  HasBeenOpened,
773  RemainsClosed
774  };
775  /*
776  * For use by flushFileBased, flushGorVBased
777  * Open an iteration, but only if necessary.
778  * Only open if the iteration is dirty and if it is not in deferred
779  * parse state.
780  */
781  IterationOpened
782  openIterationIfDirty(IterationIndex_t index, Iteration iteration);
783  /*
784  * Open an iteration. Ensures that the iteration's m_closed status
785  * is set properly and that any files pertaining to the iteration
786  * is opened.
787  * Does not create files when called in CREATE mode.
788  */
789  void openIteration(IterationIndex_t index, Iteration iteration);
790 
795  iterations_iterator indexOf(Iteration const &);
796 
813  AdvanceMode mode,
814  internal::AttributableData &file,
815  iterations_iterator it,
816  Iteration &iteration);
817 
819 
827  void flushStep(bool doFlush);
828 
829  /*
830  * Returns the current content of the /data/snapshot attribute.
831  * (We could also add this to the public API some time)
832  */
833  std::optional<std::vector<IterationIndex_t>> currentSnapshot() const;
834 
835  AbstractIOHandler *runDeferredInitialization();
836 
837  AbstractIOHandler *IOHandler();
838  AbstractIOHandler const *IOHandler() const;
839 }; // Series
840 
841 namespace debug
842 {
843  void printDirty(Series const &);
844 }
845 } // namespace openPMD
846 
847 // Make sure that this one is always included if Series.hpp is included,
848 // otherwise Series::readIterations() cannot be used
849 #include "openPMD/ReadIterations.hpp"
Interface for communicating between logical and physically persistent data.
Definition: AbstractIOHandler.hpp:186
Layer to manage storage of attributes associated with file objects.
Definition: Attributable.hpp:101
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:127
Reading side of the streaming API.
Definition: ReadIterations.hpp:162
Implementation for the root level of the openPMD hierarchy.
Definition: Series.hpp:219
Series & setName(std::string const &name)
Set the pattern for file names.
Definition: Series.cpp:372
std::string softwareVersion() const
Definition: Series.cpp:243
std::optional< std::deque< IterationIndex_t > > readGorVBased(bool do_always_throw_errors, bool init, std::set< IterationIndex_t > const &ignoreIterations={})
Note on re-parsing of a Series: If init == false, the parsing process will seek for new Iterations/Re...
Definition: Series.cpp:1572
Series & setMeshesPath(std::string const &meshesPath)
Set the path to mesh records, relative(!) to basePath.
Definition: Series.cpp:172
std::string iterationFormat() const
Definition: Series.cpp:337
void flush(std::string backendConfig="{}")
Execute all required remaining IO operations to write or read data.
Definition: Series.cpp:421
void parseBase()
Parse the Series.
Definition: Series.cpp:2610
std::string basePath() const
Definition: Series.cpp:151
Series & setSoftwareDependencies(std::string const &newSoftwareDependencies)
Indicate dependencies of software that were used to create the file.
Definition: Series.cpp:271
iterations_iterator indexOf(Iteration const &)
Find the given iteration in Series::iterations and return an iterator into Series::iterations at that...
Definition: Series.cpp:2009
Iteration::IterationIndex_t IterationIndex_t
An unsigned integer type, used to identify Iterations in a Series.
Definition: Series.hpp:313
Series & setParticlesPath(std::string const &particlesPath)
Set the path to groups for each particle species, relative(!) to basePath.
Definition: Series.cpp:198
std::future< void > flush_impl(iterations_iterator begin, iterations_iterator end, internal::FlushParams const &flushParams, bool flushIOHandler=true)
Internal call for flushing a Series.
Definition: Series.cpp:961
std::string machine() const
Definition: Series.cpp:277
std::string date() const
Definition: Series.cpp:254
WriteIterations writeIterations()
Entry point to the writing end of the streaming API.
Definition: Series.cpp:2615
std::string backend() const
The currently used backend.
Definition: Series.cpp:410
void close()
Close the Series and release the data storage/transport backends.
Definition: Series.cpp:2629
Series & setOpenPMD(std::string const &openPMD)
Set the version of the enforced openPMD standard.
Definition: Series.cpp:134
void flushStep(bool doFlush)
Called at the end of an IO step to store the iterations defined in the IO step to the snapshot attrib...
Definition: Series.cpp:2221
std::string openPMD() const
Definition: Series.cpp:129
Series & setAuthor(std::string const &author)
Indicate the author and contact for the information in the file.
Definition: Series.cpp:224
Series & setSoftwareVersion(std::string const &softwareVersion)
Indicate the version of the software/code/simulation that created the file.
Definition: Series.cpp:248
std::string author() const
Definition: Series.cpp:219
std::string meshesPath() const
Definition: Series.cpp:167
Series & setMachine(std::string const &newMachine)
Indicate the machine or relevant hardware that created the file.
Definition: Series.cpp:282
std::string software() const
Definition: Series.cpp:230
uint32_t openPMDextension() const
Definition: Series.cpp:140
Series & setBasePath(std::string const &basePath)
Set the common prefix for all data sets and sub-groups of a specific iteration.
Definition: Series.cpp:156
void parseJsonOptions(TracingJSON &options, ParsedInput &)
Parse non-backend-specific configuration in JSON config.
Definition: Series.cpp:2426
std::string particlesPath() const
Definition: Series.cpp:193
AdvanceStatus advance(AdvanceMode mode, internal::AttributableData &file, iterations_iterator it, Iteration &iteration)
In step-based IO mode, begin or end an IO step for the given iteration.
Definition: Series.cpp:2024
Series & setDate(std::string const &date)
Indicate the date of creation.
Definition: Series.cpp:259
std::string name() const
Definition: Series.cpp:367
Series & setSoftware(std::string const &newName, std::string const &newVersion=std::string("unspecified"))
Indicate the software/code/simulation that created the file.
Definition: Series.cpp:236
std::string softwareDependencies() const
Definition: Series.cpp:265
ReadIterations readIterations()
Entry point to the reading end of the streaming API.
Definition: Series.cpp:2600
Series & setOpenPMDextension(uint32_t openPMDextension)
Set a 32-bit mask of applied extensions to the openPMD standard.
Definition: Series.cpp:145
Series & setIterationEncoding(IterationEncoding iterationEncoding)
Set the encoding style for multiple iterations in this series.
Definition: Series.cpp:293
IterationEncoding iterationEncoding() const
Definition: Series.cpp:288
Series & setIterationFormat(std::string const &iterationFormat)
Set a pattern describing how to access single iterations in the raw file.
Definition: Series.cpp:342
Definition: ReadIterations.hpp:35
Layer to mirror structure of logical data and persistent data in file.
Definition: Writable.hpp:75
Writing side of the streaming API.
Definition: WriteIterations.hpp:67
Definition: Attributable.hpp:57
Data members for Series.
Definition: Series.hpp:79
std::string m_filenamePrefix
Filename leading up to the expansion pattern.
Definition: Series.hpp:146
std::set< IterationIndex_t > m_currentlyActiveIterations
For writing: Remember which iterations have been written in the currently active output step.
Definition: Series.hpp:124
std::unique_ptr< SeriesIterator > m_sharedStatefulIterator
Series::readIterations() returns an iterator type that modifies the state of the Series (by proceedin...
Definition: Series.hpp:118
std::optional< std::string > m_overrideFilebasedFilename
Needed if reading a single iteration of a file-based series.
Definition: Series.hpp:134
StepStatus m_stepStatus
Whether a step is currently active for this iteration.
Definition: Series.hpp:177
std::optional< WriteIterations > m_writeIterations
For each instance of Series, there is only one instance of WriteIterations, stored in this Option.
Definition: Series.hpp:101
std::string m_name
Name of the iteration without filename suffix.
Definition: Series.hpp:141
std::optional< ParsePreference > m_parsePreference
Remember the preference that the backend specified for parsing.
Definition: Series.hpp:198
std::string m_filenamePostfix
Filename after the expansion pattern without filename extension.
Definition: Series.hpp:150
int m_filenamePadding
The padding in file-based iteration encoding.
Definition: Series.hpp:161
bool m_parseLazily
True if a user opts into lazy parsing.
Definition: Series.hpp:181
bool m_wroteAtLeastOneIOStep
In variable-based encoding, all backends except ADIOS2 can only write one single iteration.
Definition: Series.hpp:190
std::string m_filenameExtension
Filename extension as specified by the user.
Definition: Series.hpp:155
IterationEncoding m_iterationEncoding
The iteration encoding used in this series.
Definition: Series.hpp:165
Format m_format
Detected IO format (backend).
Definition: Series.hpp:169
Public definitions of openPMD-api.
Definition: Date.cpp:29
Access
File access mode to use during IO.
Definition: Access.hpp:30
AdvanceMode
In step-based mode (i.e.
Definition: Streaming.hpp:35
StepStatus
Used in step-based mode (i.e.
Definition: Streaming.hpp:46
AdvanceStatus
In step-based mode (i.e.
Definition: Streaming.hpp:21
Format
File format to use during IO.
Definition: Format.hpp:30
IterationEncoding
Encoding scheme of an Iterations Series'.
Definition: IterationEncoding.hpp:33
Definition: Series.cpp:118