openPMD-api
Iteration.hpp
1 /* Copyright 2017-2025 Fabian Koller, Axel Huebl, Franz Poeschel, Luca Fedeli
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/IterationEncoding.hpp"
24 #include "openPMD/Mesh.hpp"
25 #include "openPMD/ParticleSpecies.hpp"
26 #include "openPMD/Streaming.hpp"
27 #include "openPMD/auxiliary/Variant.hpp"
28 #include "openPMD/backend/Attributable.hpp"
29 #include "openPMD/backend/Container.hpp"
30 
31 #include <cstdint>
32 #include <deque>
33 #include <optional>
34 #include <set>
35 #include <tuple>
36 
37 namespace openPMD
38 {
39 namespace internal
40 {
45  enum class CloseStatus
46  {
47  ParseAccessDeferred,
48  Open,
49  ClosedInFrontend,
51  Closed,
53  };
54 
55  namespace BeginStepTypes
56  {
58  {};
60  {};
62  {
63  size_t step;
64  };
65  } // namespace BeginStepTypes
66 
67  using BeginStep = std::variant<
71 
72  namespace BeginStepTypes
73  {
74  template <typename T, typename... Args>
75  constexpr auto make(Args &&...args) -> BeginStep
76  {
77  return BeginStep{T{std::forward<Args>(args)...}};
78  }
79  } // namespace BeginStepTypes
80 
82  {
88  std::string path;
92  uint64_t iteration = 0;
97  bool fileBased = false;
98  BeginStep beginStep = BeginStepTypes::DontBeginStep{};
99  };
100 
102  {
103  public:
104  /*
105  * An iteration may be logically closed in the frontend,
106  * but not necessarily yet in the backend.
107  * Will be propagated to the backend upon next flush.
108  * Store the current status.
109  * Once an iteration has been closed, no further flushes shall be
110  * performed. If flushing a closed file, the old file may otherwise be
111  * overwritten.
112  */
113  CloseStatus m_closed = CloseStatus::Open;
114  /*
115  * While parsing a file-based Series, each file is opened, read, then
116  * closed again. Explicitly `Iteration::open()`ing a file should only be
117  * necessary after having explicitly closed it (or in
118  * defer_iteration_parsing mode). So, the parsing procedures will set
119  * this flag as true when closing an Iteration.
120  */
121  bool allow_reopening_implicitly = false;
122 
130  StepStatus m_stepStatus = StepStatus::NoStep;
131 
136  std::optional<DeferredParseAccess> m_deferredParseAccess{};
137  };
138 } // namespace internal
145 class Iteration : public Attributable
146 {
147  template <typename T, typename T_key, typename T_container>
148  friend class Container;
149  friend class Series;
150  friend class internal::AttributableData;
151  template <typename T>
152  friend T &internal::makeOwning(T &self, Series);
153  friend class Writable;
154  friend class StatefulIterator;
155  friend class StatefulSnapshotsContainer;
156 
157 public:
158  Iteration(Iteration const &) = default;
159  Iteration(Iteration &&) = default;
160  Iteration &operator=(Iteration const &) = default;
161  Iteration &operator=(Iteration &&) = default;
162 
163  using IterationIndex_t = uint64_t;
164 
170  template <typename T>
171  T time() const;
179  template <typename T>
180  Iteration &setTime(T newTime);
181 
187  template <typename T>
188  T dt() const;
196  template <typename T>
197  Iteration &setDt(T newDt);
198 
202  double timeUnitSI() const;
208  Iteration &setTimeUnitSI(double newTimeUnitSI);
209 
219  /*
220  * Note: If the API is changed in future to allow reopening closed
221  * iterations, measures should be taken to prevent this in the streaming
222  * API. Currently, disallowing to reopen closed iterations satisfies
223  * the requirements of the streaming API.
224  */
225  Iteration &close(bool flush = true);
226 
240  Iteration &open();
241 
247  bool closed() const;
248 
255  bool parsed() const;
256 
268  [[deprecated("This attribute is no longer set by the openPMD-api.")]] bool
269  closedByWriter() const;
270 
271  Container<Mesh> meshes{};
272  Container<ParticleSpecies> particles{}; // particleSpecies?
273 
274  virtual ~Iteration() = default;
275 
276 private:
277  Iteration();
278 
280  std::shared_ptr<Data_t> m_iterationData;
281 
282  inline Data_t const &get() const
283  {
284  return *m_iterationData;
285  }
286 
287  inline Data_t &get()
288  {
289  return *m_iterationData;
290  }
291 
292  inline std::shared_ptr<Data_t> getShared()
293  {
294  return m_iterationData;
295  }
296 
297  inline void setData(std::shared_ptr<Data_t> data)
298  {
299  m_iterationData = std::move(data);
300  Attributable::setData(m_iterationData);
301  }
302 
303  void flushFileBased(
304  std::string const &, IterationIndex_t, internal::FlushParams const &);
305  void flushGroupBased(IterationIndex_t, internal::FlushParams const &);
306  void flushVariableBased(IterationIndex_t, internal::FlushParams const &);
307  void flush(internal::FlushParams const &);
308  void deferParseAccess(internal::DeferredParseAccess);
309  /*
310  * Control flow for runDeferredParseAccess(), readFileBased(),
311  * readGroupBased() and read_impl():
312  * runDeferredParseAccess() is called as the entry point.
313  * File-based and group-based
314  * iteration layouts need to be parsed slightly differently:
315  * In file-based iteration layout, each iteration's file also contains
316  * attributes for the /data group. In group-based layout, those have
317  * already been parsed during opening of the Series.
318  * Hence, runDeferredParseAccess() will call either readFileBased() or
319  * readGroupBased() to
320  * allow for those different control flows.
321  * Finally, read_impl() is called which contains the common parsing
322  * logic for an iteration.
323  *
324  * reread() reads again an Iteration that has been previously read.
325  * Calling it on an Iteration not yet parsed is an error.
326  *
327  */
328  void reread(std::string const &path);
329  void readFileBased(
330  IterationIndex_t,
331  std::string const &filePath,
332  std::string const &groupPath,
333  bool beginStep);
334  void readGorVBased(
335  std::string const &groupPath, internal::BeginStep const &beginStep);
336  void read_impl(std::string const &groupPath);
337  void readMeshes(std::string const &meshesPath);
338  void readParticles(std::string const &particlesPath);
339 
345  struct BeginStepStatus
346  {
347  using AvailableIterations_t = std::vector<uint64_t>;
348 
349  AdvanceStatus stepStatus{};
350  /*
351  * If the iteration attribute `snapshot` is present, the value of that
352  * attribute. Otherwise empty.
353  */
354  AvailableIterations_t iterationsInOpenedStep;
355 
356  /*
357  * Most of the time, the AdvanceStatus part of this struct is what we
358  * need, so let's make it easy to access.
359  */
360  inline operator AdvanceStatus() const
361  {
362  return stepStatus;
363  }
364 
365  /*
366  * Support for std::tie()
367  */
368  inline operator std::tuple<AdvanceStatus &, AvailableIterations_t &>()
369  {
370  return std::tuple<AdvanceStatus &, AvailableIterations_t &>{
371  stepStatus, iterationsInOpenedStep};
372  }
373  };
374 
382  BeginStepStatus beginStep(bool reread);
383 
384  /*
385  * Iteration-independent variant for beginStep().
386  * Useful in group-based iteration encoding where the Iteration will only
387  * be known after opening the step.
388  */
389  static BeginStepStatus
390  beginStep(std::optional<Iteration> thisObject, Series &series, bool reread);
391 
397  void endStep();
398 
407  StepStatus getStepStatus();
408 
417  void setStepStatus(StepStatus);
418 
424  virtual void linkHierarchy(Writable &w);
425 
431  void runDeferredParseAccess();
432 }; // Iteration
433 
434 extern template float Iteration::time<float>() const;
435 
436 extern template double Iteration::time<double>() const;
437 
438 extern template long double Iteration::time<long double>() const;
439 
440 template <typename T>
441 inline T Iteration::time() const
442 {
443  return this->readFloatingpoint<T>("time");
444 }
445 
446 extern template float Iteration::dt<float>() const;
447 
448 extern template double Iteration::dt<double>() const;
449 
450 extern template long double Iteration::dt<long double>() const;
451 
452 template <typename T>
453 inline T Iteration::dt() const
454 {
455  return this->readFloatingpoint<T>("dt");
456 }
457 
463 {
464  friend class StatefulIterator;
465  friend class LegacyIteratorAdaptor;
466 
467 public:
468  using index_t = Iteration::IterationIndex_t;
469  index_t const iterationIndex;
470 
471  inline IndexedIteration(std::pair<index_t const, Iteration> pair)
472  : Iteration(std::move(pair.second)), iterationIndex(pair.first)
473  {}
474 
475 private:
476  template <typename Iteration_t>
477  IndexedIteration(Iteration_t &&it, index_t index)
478  : Iteration(std::forward<Iteration_t>(it)), iterationIndex(index)
479  {}
480 };
481 } // namespace openPMD
Layer to manage storage of attributes associated with file objects.
Definition: Attributable.hpp:222
Map-like container that enforces openPMD requirements and handles IO.
Definition: Container.hpp:104
Subclass of Iteration that knows its own index withing the containing Series.
Definition: Iteration.hpp:463
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:146
Iteration & setTimeUnitSI(double newTimeUnitSI)
Set the conversion factor to convert time and dt to seconds.
Definition: Iteration.cpp:89
bool parsed() const
Has the iteration been parsed yet? If not, it will contain no structure yet.
Definition: Iteration.cpp:202
double timeUnitSI() const
Definition: Iteration.cpp:84
Iteration & setTime(T newTime)
Set the global reference time for this iteration.
Definition: Iteration.cpp:63
bool closedByWriter() const
Has the iteration been closed by the writer? Background: Upon calling Iteration::close(),...
Definition: Iteration.cpp:216
T time() const
Definition: Iteration.hpp:441
bool closed() const
Has the iteration been closed?
Definition: Iteration.cpp:183
T dt() const
Definition: Iteration.hpp:453
Iteration & open()
Open an iteration.
Definition: Iteration.cpp:146
Iteration & close(bool flush=true)
Close an iteration.
Definition: Iteration.cpp:97
Iteration & setDt(T newDt)
Set the time step used to reach this iteration.
Definition: Iteration.cpp:74
Legacy Iterator type for Series::readIterations()
Definition: ReadIterations.hpp:39
Implementation for the root level of the openPMD hierarchy.
Definition: Series.hpp:288
Based on the logic of the former class ReadIterations, integrating into itself the logic of former Wr...
Definition: StatefulIterator.hpp:204
Definition: ContainerImpls.hpp:36
Layer to mirror structure of logical data and persistent data in file.
Definition: Writable.hpp:76
Definition: Attributable.hpp:107
Definition: Iteration.hpp:102
StepStatus m_stepStatus
Whether a step is currently active for this iteration.
Definition: Iteration.hpp:130
std::optional< DeferredParseAccess > m_deferredParseAccess
Information on a parsing request that has not yet been executed.
Definition: Iteration.hpp:136
Public definitions of openPMD-api.
Definition: Date.cpp:29
StepStatus
Used in step-based mode (i.e.
Definition: Streaming.hpp:57
AdvanceStatus
In step-based mode (i.e.
Definition: Streaming.hpp:32
Definition: Iteration.hpp:82
uint64_t iteration
The iteration index as accessed by the user in series.iterations[i].
Definition: Iteration.hpp:92
std::string path
The group path within /data containing this iteration.
Definition: Iteration.hpp:88
bool fileBased
If this iteration is part of a Series with file-based layout.
Definition: Iteration.hpp:97
Parameters recursively passed through the openPMD hierarchy when flushing.
Definition: AbstractIOHandler.hpp:106