openPMD-api
Iteration.hpp
1 /* Copyright 2017-2021 Fabian Koller
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  {
48  Open,
55  };
56 
58  {
64  std::string path;
68  uint64_t iteration = 0;
73  bool fileBased = false;
78  std::string filename;
79  bool beginStep = false;
80  };
81 
83  {
84  public:
85  /*
86  * An iteration may be logically closed in the frontend,
87  * but not necessarily yet in the backend.
88  * Will be propagated to the backend upon next flush.
89  * Store the current status.
90  * Once an iteration has been closed, no further flushes shall be
91  * performed. If flushing a closed file, the old file may otherwise be
92  * overwritten.
93  */
94  CloseStatus m_closed = CloseStatus::Open;
95 
103  StepStatus m_stepStatus = StepStatus::NoStep;
104 
109  std::optional<DeferredParseAccess> m_deferredParseAccess{};
110 
117  std::optional<std::string> m_overrideFilebasedFilename{};
118  };
119 } // namespace internal
126 class Iteration : public Attributable
127 {
128  template <typename T, typename T_key, typename T_container>
129  friend class Container;
130  friend class Series;
131  friend class WriteIterations;
132  friend class SeriesIterator;
133  friend class internal::AttributableData;
134  template <typename T>
135  friend T &internal::makeOwning(T &self, Series);
136  friend class Writable;
137 
138 public:
139  Iteration(Iteration const &) = default;
140  Iteration &operator=(Iteration const &) = default;
141 
142  using IterationIndex_t = uint64_t;
143 
149  template <typename T>
150  T time() const;
158  template <typename T>
159  Iteration &setTime(T newTime);
160 
166  template <typename T>
167  T dt() const;
175  template <typename T>
176  Iteration &setDt(T newDt);
177 
181  double timeUnitSI() const;
187  Iteration &setTimeUnitSI(double newTimeUnitSI);
188 
198  /*
199  * Note: If the API is changed in future to allow reopening closed
200  * iterations, measures should be taken to prevent this in the streaming
201  * API. Currently, disallowing to reopen closed iterations satisfies
202  * the requirements of the streaming API.
203  */
204  Iteration &close(bool flush = true);
205 
219  Iteration &open();
220 
227  bool closed() const;
228 
240  [[deprecated("This attribute is no longer set by the openPMD-api.")]] bool
241  closedByWriter() const;
242 
243  Container<Mesh> meshes{};
244  Container<ParticleSpecies> particles{}; // particleSpecies?
245 
246  virtual ~Iteration() = default;
247 
248 private:
249  Iteration();
250 
252  std::shared_ptr<Data_t> m_iterationData;
253 
254  inline Data_t const &get() const
255  {
256  return *m_iterationData;
257  }
258 
259  inline Data_t &get()
260  {
261  return *m_iterationData;
262  }
263 
264  inline std::shared_ptr<Data_t> getShared()
265  {
266  return m_iterationData;
267  }
268 
269  inline void setData(std::shared_ptr<Data_t> data)
270  {
271  m_iterationData = std::move(data);
272  Attributable::setData(m_iterationData);
273  }
274 
275  void flushFileBased(
276  std::string const &, IterationIndex_t, internal::FlushParams const &);
277  void flushGroupBased(IterationIndex_t, internal::FlushParams const &);
278  void flushVariableBased(IterationIndex_t, internal::FlushParams const &);
279  void flush(internal::FlushParams const &);
280  void deferParseAccess(internal::DeferredParseAccess);
281  /*
282  * Control flow for runDeferredParseAccess(), readFileBased(),
283  * readGroupBased() and read_impl():
284  * runDeferredParseAccess() is called as the entry point.
285  * File-based and group-based
286  * iteration layouts need to be parsed slightly differently:
287  * In file-based iteration layout, each iteration's file also contains
288  * attributes for the /data group. In group-based layout, those have
289  * already been parsed during opening of the Series.
290  * Hence, runDeferredParseAccess() will call either readFileBased() or
291  * readGroupBased() to
292  * allow for those different control flows.
293  * Finally, read_impl() is called which contains the common parsing
294  * logic for an iteration.
295  *
296  * reread() reads again an Iteration that has been previously read.
297  * Calling it on an Iteration not yet parsed is an error.
298  *
299  */
300  void reread(std::string const &path);
301  void readFileBased(
302  std::string const &filePath,
303  std::string const &groupPath,
304  bool beginStep);
305  void readGorVBased(std::string const &groupPath, bool beginStep);
306  void read_impl(std::string const &groupPath);
307  void readMeshes(std::string const &meshesPath);
308  void readParticles(std::string const &particlesPath);
309 
315  struct BeginStepStatus
316  {
317  using AvailableIterations_t = std::optional<std::deque<uint64_t> >;
318 
319  AdvanceStatus stepStatus{};
320  /*
321  * If the iteration attribute `snapshot` is present, the value of that
322  * attribute. Otherwise empty.
323  */
324  AvailableIterations_t iterationsInOpenedStep;
325 
326  /*
327  * Most of the time, the AdvanceStatus part of this struct is what we
328  * need, so let's make it easy to access.
329  */
330  inline operator AdvanceStatus() const
331  {
332  return stepStatus;
333  }
334 
335  /*
336  * Support for std::tie()
337  */
338  inline operator std::tuple<AdvanceStatus &, AvailableIterations_t &>()
339  {
340  return std::tuple<AdvanceStatus &, AvailableIterations_t &>{
341  stepStatus, iterationsInOpenedStep};
342  }
343  };
344 
352  BeginStepStatus beginStep(bool reread);
353 
354  /*
355  * Iteration-independent variant for beginStep().
356  * Useful in group-based iteration encoding where the Iteration will only
357  * be known after opening the step.
358  */
359  static BeginStepStatus beginStep(
360  std::optional<Iteration> thisObject,
361  Series &series,
362  bool reread,
363  std::set<IterationIndex_t> const &ignoreIterations = {});
364 
370  void endStep();
371 
380  StepStatus getStepStatus();
381 
390  void setStepStatus(StepStatus);
391 
397  virtual void linkHierarchy(Writable &w);
398 
404  void runDeferredParseAccess();
405 }; // Iteration
406 
407 extern template float Iteration::time<float>() const;
408 
409 extern template double Iteration::time<double>() const;
410 
411 extern template long double Iteration::time<long double>() const;
412 
413 template <typename T>
414 inline T Iteration::time() const
415 {
416  return this->readFloatingpoint<T>("time");
417 }
418 
419 extern template float Iteration::dt<float>() const;
420 
421 extern template double Iteration::dt<double>() const;
422 
423 extern template long double Iteration::dt<long double>() const;
424 
425 template <typename T>
426 inline T Iteration::dt() const
427 {
428  return this->readFloatingpoint<T>("dt");
429 }
430 
436 {
437  friend class SeriesIterator;
438  friend class WriteIterations;
439 
440 public:
441  using index_t = Iteration::IterationIndex_t;
442  index_t const iterationIndex;
443 
444 private:
445  template <typename Iteration_t>
446  IndexedIteration(Iteration_t &&it, index_t index)
447  : Iteration(std::forward<Iteration_t>(it)), iterationIndex(index)
448  {}
449 };
450 } // namespace openPMD
Layer to manage storage of attributes associated with file objects.
Definition: Attributable.hpp:155
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:436
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:127
Iteration & setTimeUnitSI(double newTimeUnitSI)
Set the conversion factor to convert time and dt to seconds.
Definition: Iteration.cpp:78
double timeUnitSI() const
Definition: Iteration.cpp:73
Iteration & setTime(T newTime)
Set the global reference time for this iteration.
Definition: Iteration.cpp:52
bool closedByWriter() const
Has the iteration been closed by the writer? Background: Upon calling Iteration::close(),...
Definition: Iteration.cpp:184
T time() const
Definition: Iteration.hpp:414
bool closed() const
Has the iteration been closed? A closed iteration may not (yet) be reopened.
Definition: Iteration.cpp:164
T dt() const
Definition: Iteration.hpp:426
Iteration & open()
Open an iteration.
Definition: Iteration.cpp:148
Iteration & close(bool flush=true)
Close an iteration.
Definition: Iteration.cpp:86
Iteration & setDt(T newDt)
Set the time step used to reach this iteration.
Definition: Iteration.cpp:63
Implementation for the root level of the openPMD hierarchy.
Definition: Series.hpp:251
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:60
Definition: Iteration.hpp:83
StepStatus m_stepStatus
Whether a step is currently active for this iteration.
Definition: Iteration.hpp:103
std::optional< DeferredParseAccess > m_deferredParseAccess
Information on a parsing request that has not yet been executed.
Definition: Iteration.hpp:109
std::optional< std::string > m_overrideFilebasedFilename
Upon reading a file, set this field to the used file name.
Definition: Iteration.hpp:117
CloseStatus
Whether an iteration has been closed yet.
Definition: Iteration.hpp:46
@ ParseAccessDeferred
The reader has not yet parsed this iteration.
@ Open
Iteration has not been closed.
Public definitions of openPMD-api.
Definition: Date.cpp:29
StepStatus
Used in step-based mode (i.e.
Definition: Streaming.hpp:46
AdvanceStatus
In step-based mode (i.e.
Definition: Streaming.hpp:21
Definition: Iteration.hpp:58
std::string filename
If fileBased == true, the file name (without file path) of the file containing this iteration.
Definition: Iteration.hpp:78
uint64_t iteration
The iteration index as accessed by the user in series.iterations[i].
Definition: Iteration.hpp:68
std::string path
The group path within /data containing this iteration.
Definition: Iteration.hpp:64
bool fileBased
If this iteration is part of a Series with file-based layout.
Definition: Iteration.hpp:73
Parameters recursively passed through the openPMD hierarchy when flushing.
Definition: AbstractIOHandler.hpp:86