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 
139  std::optional<uint64_t> m_iterationIndex = std::nullopt;
140 
145  std::optional<DeferredParseAccess> m_deferredParseAccess{};
146  };
147 } // namespace internal
154 class Iteration : public Attributable
155 {
156  template <typename T, typename T_key, typename T_container>
157  friend class Container;
158  friend class Series;
159  friend class internal::AttributableData;
160  template <typename T>
161  friend T &internal::makeOwning(T &self, Series);
162  friend class Writable;
163  friend class StatefulIterator;
164  friend class StatefulSnapshotsContainer;
165  template <typename>
166  friend struct traits::GenerationPolicy;
167 
168 public:
169  Iteration(Iteration const &) = default;
170  Iteration(Iteration &&) = default;
171  Iteration &operator=(Iteration const &) = default;
172  Iteration &operator=(Iteration &&) = default;
173 
174  using IterationIndex_t = uint64_t;
175 
181  template <typename T>
182  T time() const;
190  template <typename T>
191  Iteration &setTime(T newTime);
192 
198  template <typename T>
199  T dt() const;
207  template <typename T>
208  Iteration &setDt(T newDt);
209 
213  double timeUnitSI() const;
219  Iteration &setTimeUnitSI(double newTimeUnitSI);
220 
230  /*
231  * Note: If the API is changed in future to allow reopening closed
232  * iterations, measures should be taken to prevent this in the streaming
233  * API. Currently, disallowing to reopen closed iterations satisfies
234  * the requirements of the streaming API.
235  */
236  Iteration &close(bool flush = true);
237 
251  Iteration &open();
252 
258  bool closed() const;
259 
266  bool parsed() const;
267 
279  [[deprecated("This attribute is no longer set by the openPMD-api.")]] bool
280  closedByWriter() const;
281 
282  Container<Mesh> meshes{};
283  Container<ParticleSpecies> particles{}; // particleSpecies?
284 
285  virtual ~Iteration() = default;
286 
287 private:
288  Iteration();
289 
298  uint64_t getCachedIterationIndex() const;
299 
301  std::shared_ptr<Data_t> m_iterationData;
302 
303  inline Data_t const &get() const
304  {
305  return *m_iterationData;
306  }
307 
308  inline Data_t &get()
309  {
310  return *m_iterationData;
311  }
312 
313  inline std::shared_ptr<Data_t> getShared()
314  {
315  return m_iterationData;
316  }
317 
318  inline void setData(std::shared_ptr<Data_t> data)
319  {
320  m_iterationData = std::move(data);
321  Attributable::setData(m_iterationData);
322  }
323 
324  void flushFileBased(
325  std::string const &, IterationIndex_t, internal::FlushParams const &);
326  void flushGroupBased(IterationIndex_t, internal::FlushParams const &);
327  void flushVariableBased(IterationIndex_t, internal::FlushParams const &);
328  void flush(internal::FlushParams const &);
329  void deferParseAccess(internal::DeferredParseAccess);
330  /*
331  * Control flow for runDeferredParseAccess(), readFileBased(),
332  * readGroupBased() and read_impl():
333  * runDeferredParseAccess() is called as the entry point.
334  * File-based and group-based
335  * iteration layouts need to be parsed slightly differently:
336  * In file-based iteration layout, each iteration's file also contains
337  * attributes for the /data group. In group-based layout, those have
338  * already been parsed during opening of the Series.
339  * Hence, runDeferredParseAccess() will call either readFileBased() or
340  * readGroupBased() to
341  * allow for those different control flows.
342  * Finally, read_impl() is called which contains the common parsing
343  * logic for an iteration.
344  *
345  * reread() reads again an Iteration that has been previously read.
346  * Calling it on an Iteration not yet parsed is an error.
347  *
348  */
349  void reread(std::string const &path);
350  void readFileBased(
351  IterationIndex_t,
352  std::string const &filePath,
353  std::string const &groupPath,
354  bool beginStep);
355  void readGorVBased(
356  std::string const &groupPath, internal::BeginStep const &beginStep);
357  void read_impl(std::string const &groupPath);
358  void readMeshes(std::string const &meshesPath);
359  void readParticles(std::string const &particlesPath);
360 
366  struct BeginStepStatus
367  {
368  using AvailableIterations_t = std::vector<IterationIndex_t>;
369 
370  AdvanceStatus stepStatus{};
371  /*
372  * If the iteration attribute `snapshot` is present, the value of that
373  * attribute. Otherwise empty.
374  */
375  AvailableIterations_t iterationsInOpenedStep;
376 
377  /*
378  * Most of the time, the AdvanceStatus part of this struct is what we
379  * need, so let's make it easy to access.
380  */
381  inline operator AdvanceStatus() const
382  {
383  return stepStatus;
384  }
385 
386  /*
387  * Support for std::tie()
388  */
389  inline operator std::tuple<AdvanceStatus &, AvailableIterations_t &>()
390  {
391  return std::tuple<AdvanceStatus &, AvailableIterations_t &>{
392  stepStatus, iterationsInOpenedStep};
393  }
394  };
395 
403  BeginStepStatus beginStep(bool reread);
404 
405  /*
406  * Iteration-independent variant for beginStep().
407  * Useful in group-based iteration encoding where the Iteration will only
408  * be known after opening the step.
409  */
410  static BeginStepStatus
411  beginStep(std::optional<Iteration> thisObject, Series &series, bool reread);
412 
418  void endStep();
419 
428  StepStatus getStepStatus();
429 
438  void setStepStatus(StepStatus);
439 
445  virtual void linkHierarchy(Writable &w);
446 
452  void runDeferredParseAccess();
453 }; // Iteration
454 
455 namespace traits
456 {
457  template <>
459  {
460  constexpr static bool is_noop = false;
461  template <typename Iterator>
462  void operator()(Iterator &it)
463  {
464  it->second.get().m_iterationIndex = it->first;
465  }
466  };
467 } // namespace traits
468 
469 extern template float Iteration::time<float>() const;
470 
471 extern template double Iteration::time<double>() const;
472 
473 extern template long double Iteration::time<long double>() const;
474 
475 template <typename T>
476 inline T Iteration::time() const
477 {
478  return this->readFloatingpoint<T>("time");
479 }
480 
481 extern template float Iteration::dt<float>() const;
482 
483 extern template double Iteration::dt<double>() const;
484 
485 extern template long double Iteration::dt<long double>() const;
486 
487 template <typename T>
488 inline T Iteration::dt() const
489 {
490  return this->readFloatingpoint<T>("dt");
491 }
492 
498 {
499  friend class StatefulIterator;
500  friend class LegacyIteratorAdaptor;
501 
502 public:
503  using index_t = Iteration::IterationIndex_t;
504  index_t const iterationIndex;
505 
506  inline IndexedIteration(std::pair<index_t const, Iteration> pair)
507  : Iteration(std::move(pair.second)), iterationIndex(pair.first)
508  {}
509 
510 private:
511  template <typename Iteration_t>
512  IndexedIteration(Iteration_t &&it, index_t index)
513  : Iteration(std::forward<Iteration_t>(it)), iterationIndex(index)
514  {}
515 };
516 } // 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:498
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:155
Iteration & setTimeUnitSI(double newTimeUnitSI)
Set the conversion factor to convert time and dt to seconds.
Definition: Iteration.cpp:99
bool parsed() const
Has the iteration been parsed yet? If not, it will contain no structure yet.
Definition: Iteration.cpp:212
double timeUnitSI() const
Definition: Iteration.cpp:94
Iteration & setTime(T newTime)
Set the global reference time for this iteration.
Definition: Iteration.cpp:73
bool closedByWriter() const
Has the iteration been closed by the writer? Background: Upon calling Iteration::close(),...
Definition: Iteration.cpp:226
T time() const
Definition: Iteration.hpp:476
bool closed() const
Has the iteration been closed?
Definition: Iteration.cpp:193
T dt() const
Definition: Iteration.hpp:488
Iteration & open()
Open an iteration.
Definition: Iteration.cpp:156
Iteration & close(bool flush=true)
Close an iteration.
Definition: Iteration.cpp:107
Iteration & setDt(T newDt)
Set the time step used to reach this iteration.
Definition: Iteration.cpp:84
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< uint64_t > m_iterationIndex
Cached copy of the key under which this Iteration lives in Series::iterations.
Definition: Iteration.hpp:139
std::optional< DeferredParseAccess > m_deferredParseAccess
Information on a parsing request that has not yet been executed.
Definition: Iteration.hpp:145
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
Container Element Creation Policy.
Definition: Container.hpp:52