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 #include "openPMD/backend/HierarchyVisitor.hpp"
31 #include "openPMD/backend/scientific_defaults/ScientificDefaults.hpp"
32 
33 #include <cstdint>
34 #include <deque>
35 #include <optional>
36 #include <set>
37 #include <tuple>
38 
39 namespace openPMD
40 {
41 namespace internal
42 {
47  enum class CloseStatus
48  {
49  ParseAccessDeferred,
50  Open,
51  ClosedInFrontend,
53  Closed,
55  };
56 
57  namespace BeginStepTypes
58  {
60  {};
62  {};
64  {
65  size_t step;
66  };
67  } // namespace BeginStepTypes
68 
69  using BeginStep = std::variant<
73 
74  namespace BeginStepTypes
75  {
76  template <typename T, typename... Args>
77  constexpr auto make(Args &&...args) -> BeginStep
78  {
79  return BeginStep{T{std::forward<Args>(args)...}};
80  }
81  } // namespace BeginStepTypes
82 
84  {
90  std::string path;
94  uint64_t iteration = 0;
99  bool fileBased = false;
100  BeginStep beginStep = BeginStepTypes::DontBeginStep{};
101  };
102 
104  {
105  public:
106  /*
107  * An iteration may be logically closed in the frontend,
108  * but not necessarily yet in the backend.
109  * Will be propagated to the backend upon next flush.
110  * Store the current status.
111  * Once an iteration has been closed, no further flushes shall be
112  * performed. If flushing a closed file, the old file may otherwise be
113  * overwritten.
114  */
115  CloseStatus m_closed = CloseStatus::Open;
116  /*
117  * While parsing a file-based Series, each file is opened, read, then
118  * closed again. Explicitly `Iteration::open()`ing a file should only be
119  * necessary after having explicitly closed it (or in
120  * defer_iteration_parsing mode). So, the parsing procedures will set
121  * this flag as true when closing an Iteration.
122  */
123  bool allow_reopening_implicitly = false;
124 
132  StepStatus m_stepStatus = StepStatus::NoStep;
133 
141  std::optional<uint64_t> m_iterationIndex = std::nullopt;
142 
147  std::optional<DeferredParseAccess> m_deferredParseAccess{};
148  };
149 } // namespace internal
150 
151 class Meshes : public Container<Mesh>
152 {
153 public:
154  void visitHierarchy(HierarchyVisitor &v, bool recursive) override;
155 };
156 
157 class Particles : public Container<ParticleSpecies>
158 {
159 public:
160  void visitHierarchy(HierarchyVisitor &v, bool recursive) override;
161 };
162 
170  : public Attributable
172 {
173  template <typename T, typename T_key, typename T_container>
174  friend class Container;
175  friend class Series;
176  friend class internal::AttributableData;
177  template <typename T>
178  friend T &internal::makeOwning(T &self, Series);
179  friend class Writable;
180  friend class StatefulIterator;
181  friend class StatefulSnapshotsContainer;
182  template <typename>
183  friend struct traits::GenerationPolicy;
184  friend class internal::ScientificDefaults;
185  friend class Attributable;
186 
187 public:
188  Iteration(Iteration const &) = default;
189  Iteration(Iteration &&) = default;
190  Iteration &operator=(Iteration const &) = default;
191  Iteration &operator=(Iteration &&) = default;
192 
193  using IterationIndex_t = uint64_t;
194 
200  template <typename T>
201  T time() const;
209  template <typename T>
210  Iteration &setTime(T newTime);
211 
217  template <typename T>
218  T dt() const;
226  template <typename T>
227  Iteration &setDt(T newDt);
228 
232  double timeUnitSI() const;
238  Iteration &setTimeUnitSI(double newTimeUnitSI);
239 
249  /*
250  * Note: If the API is changed in future to allow reopening closed
251  * iterations, measures should be taken to prevent this in the streaming
252  * API. Currently, disallowing to reopen closed iterations satisfies
253  * the requirements of the streaming API.
254  */
255  Iteration &close(bool flush = true);
256 
270  Iteration &open();
271 
277  bool closed() const;
278 
285  bool parsed() const;
286 
298  [[deprecated("This attribute is no longer set by the openPMD-api.")]] bool
299  closedByWriter() const;
300 
301  void visitHierarchy(HierarchyVisitor &v, bool recursive) override;
302 
303  Meshes meshes{};
304  Particles particles{};
305 
306  virtual ~Iteration() = default;
307 
308 private:
309  Iteration();
310 
319  uint64_t getCachedIterationIndex() const;
320 
322  std::shared_ptr<Data_t> m_iterationData;
323 
324  inline Data_t const &get() const
325  {
326  return *m_iterationData;
327  }
328 
329  inline Data_t &get()
330  {
331  return *m_iterationData;
332  }
333 
334  inline std::shared_ptr<Data_t> getShared()
335  {
336  return m_iterationData;
337  }
338 
339  inline void setData(std::shared_ptr<Data_t> data)
340  {
341  m_iterationData = std::move(data);
342  Attributable::setData(m_iterationData);
343  }
344 
345  void flushFileBased(
346  std::string const &, IterationIndex_t, internal::FlushParams const &);
347  void flushGroupBased(IterationIndex_t, internal::FlushParams const &);
348  void flushVariableBased(IterationIndex_t, internal::FlushParams const &);
349  void flush(internal::FlushParams const &);
350  void deferParseAccess(internal::DeferredParseAccess);
351  /*
352  * Control flow for runDeferredParseAccess(), readFileBased(),
353  * readGroupBased() and read_impl():
354  * runDeferredParseAccess() is called as the entry point.
355  * File-based and group-based
356  * iteration layouts need to be parsed slightly differently:
357  * In file-based iteration layout, each iteration's file also contains
358  * attributes for the /data group. In group-based layout, those have
359  * already been parsed during opening of the Series.
360  * Hence, runDeferredParseAccess() will call either readFileBased() or
361  * readGroupBased() to
362  * allow for those different control flows.
363  * Finally, read_impl() is called which contains the common parsing
364  * logic for an iteration.
365  *
366  * reread() reads again an Iteration that has been previously read.
367  * Calling it on an Iteration not yet parsed is an error.
368  *
369  */
370  void reread(std::string const &path);
371  void readFileBased(
372  IterationIndex_t,
373  std::string const &filePath,
374  std::string const &groupPath,
375  bool beginStep);
376  void readGorVBased(
377  std::string const &groupPath, internal::BeginStep const &beginStep);
378  void read_impl(std::string const &groupPath);
379  void readMeshes(std::string const &meshesPath);
380  void readParticles(std::string const &particlesPath);
381 
387  struct BeginStepStatus
388  {
389  using AvailableIterations_t = std::vector<IterationIndex_t>;
390 
391  AdvanceStatus stepStatus{};
392  /*
393  * If the iteration attribute `snapshot` is present, the value of that
394  * attribute. Otherwise empty.
395  */
396  AvailableIterations_t iterationsInOpenedStep;
397 
398  /*
399  * Most of the time, the AdvanceStatus part of this struct is what we
400  * need, so let's make it easy to access.
401  */
402  inline operator AdvanceStatus() const
403  {
404  return stepStatus;
405  }
406 
407  /*
408  * Support for std::tie()
409  */
410  inline operator std::tuple<AdvanceStatus &, AvailableIterations_t &>()
411  {
412  return std::tuple<AdvanceStatus &, AvailableIterations_t &>{
413  stepStatus, iterationsInOpenedStep};
414  }
415  };
416 
424  BeginStepStatus beginStep(bool reread);
425 
426  /*
427  * Iteration-independent variant for beginStep().
428  * Useful in group-based iteration encoding where the Iteration will only
429  * be known after opening the step.
430  */
431  static BeginStepStatus
432  beginStep(std::optional<Iteration> thisObject, Series &series, bool reread);
433 
439  void endStep();
440 
449  StepStatus getStepStatus();
450 
459  void setStepStatus(StepStatus);
460 
466  void linkHierarchy(Writable &w) override;
467 
473  void runDeferredParseAccess();
474 
475 protected:
476  void scientificDefaults_impl(
477  internal::WriteOrRead, OpenpmdStandard) override;
478 }; // Iteration
479 
480 namespace traits
481 {
482  template <>
484  {
485  constexpr static bool is_noop = false;
486  template <typename Iterator>
487  void operator()(Iterator &it)
488  {
489  it->second.get().m_iterationIndex = it->first;
490  }
491  };
492 } // namespace traits
493 
494 extern template float Iteration::time<float>() const;
495 
496 extern template double Iteration::time<double>() const;
497 
498 extern template long double Iteration::time<long double>() const;
499 
500 template <typename T>
501 inline T Iteration::time() const
502 {
503  return this->readFloatingpoint<T>("time");
504 }
505 
506 extern template float Iteration::dt<float>() const;
507 
508 extern template double Iteration::dt<double>() const;
509 
510 extern template long double Iteration::dt<long double>() const;
511 
512 template <typename T>
513 inline T Iteration::dt() const
514 {
515  return this->readFloatingpoint<T>("dt");
516 }
517 
523 {
524  friend class StatefulIterator;
525  friend class LegacyIteratorAdaptor;
526 
527 public:
528  using index_t = Iteration::IterationIndex_t;
529  index_t const iterationIndex;
530 
531  inline IndexedIteration(std::pair<index_t const, Iteration> pair)
532  : Iteration(std::move(pair.second)), iterationIndex(pair.first)
533  {}
534 
535 private:
536  template <typename Iteration_t>
537  IndexedIteration(Iteration_t &&it, index_t index)
538  : Iteration(std::forward<Iteration_t>(it)), iterationIndex(index)
539  {}
540 };
541 
543 {
544 public:
545  void visitHierarchy(HierarchyVisitor &v, bool recursive) override;
546 };
547 } // namespace openPMD
Layer to manage storage of attributes associated with file objects.
Definition: Attributable.hpp:225
Map-like container that enforces openPMD requirements and handles IO.
Definition: Container.hpp:106
Definition: HierarchyVisitor.hpp:20
Subclass of Iteration that knows its own index withing the containing Series.
Definition: Iteration.hpp:523
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:172
Iteration & setTimeUnitSI(double newTimeUnitSI)
Set the conversion factor to convert time and dt to seconds.
Definition: Iteration.cpp:111
bool parsed() const
Has the iteration been parsed yet? If not, it will contain no structure yet.
Definition: Iteration.cpp:230
double timeUnitSI() const
Definition: Iteration.cpp:106
Iteration & setTime(T newTime)
Set the global reference time for this iteration.
Definition: Iteration.cpp:85
bool closedByWriter() const
Has the iteration been closed by the writer? Background: Upon calling Iteration::close(),...
Definition: Iteration.cpp:244
T time() const
Definition: Iteration.hpp:501
bool closed() const
Has the iteration been closed?
Definition: Iteration.cpp:211
T dt() const
Definition: Iteration.hpp:513
Iteration & open()
Open an iteration.
Definition: Iteration.cpp:174
Iteration & close(bool flush=true)
Close an iteration.
Definition: Iteration.cpp:119
Iteration & setDt(T newDt)
Set the time step used to reach this iteration.
Definition: Iteration.cpp:96
void visitHierarchy(HierarchyVisitor &v, bool recursive) override
Visitor pattern for the openPMD object hierarchy in postfix traversal.
Definition: Iteration.cpp:257
Definition: Iteration.hpp:543
Legacy Iterator type for Series::readIterations()
Definition: ReadIterations.hpp:39
Definition: Iteration.hpp:152
void visitHierarchy(HierarchyVisitor &v, bool recursive) override
Visitor pattern for the openPMD object hierarchy in postfix traversal.
Definition: Iteration.cpp:57
Definition: Iteration.hpp:158
void visitHierarchy(HierarchyVisitor &v, bool recursive) override
Visitor pattern for the openPMD object hierarchy in postfix traversal.
Definition: Iteration.cpp:62
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:77
Definition: Attributable.hpp:110
Definition: Iteration.hpp:104
StepStatus m_stepStatus
Whether a step is currently active for this iteration.
Definition: Iteration.hpp:132
std::optional< uint64_t > m_iterationIndex
Cached copy of the key under which this Iteration lives in Series::iterations.
Definition: Iteration.hpp:141
std::optional< DeferredParseAccess > m_deferredParseAccess
Information on a parsing request that has not yet been executed.
Definition: Iteration.hpp:147
Definition: ScientificDefaults.hpp:23
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:84
uint64_t iteration
The iteration index as accessed by the user in series.iterations[i].
Definition: Iteration.hpp:94
std::string path
The group path within /data containing this iteration.
Definition: Iteration.hpp:90
bool fileBased
If this iteration is part of a Series with file-based layout.
Definition: Iteration.hpp:99
Parameters recursively passed through the openPMD hierarchy when flushing.
Definition: AbstractIOHandler.hpp:106
Container Element Creation Policy.
Definition: Container.hpp:54