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 
134 public:
135  Iteration(Iteration const &) = default;
136  Iteration &operator=(Iteration const &) = default;
137 
138  using IterationIndex_t = uint64_t;
139 
145  template <typename T>
146  T time() const;
154  template <typename T>
155  Iteration &setTime(T newTime);
156 
162  template <typename T>
163  T dt() const;
171  template <typename T>
172  Iteration &setDt(T newDt);
173 
177  double timeUnitSI() const;
183  Iteration &setTimeUnitSI(double newTimeUnitSI);
184 
194  /*
195  * Note: If the API is changed in future to allow reopening closed
196  * iterations, measures should be taken to prevent this in the streaming
197  * API. Currently, disallowing to reopen closed iterations satisfies
198  * the requirements of the streaming API.
199  */
200  Iteration &close(bool flush = true);
201 
215  Iteration &open();
216 
223  bool closed() const;
224 
236  [[deprecated("This attribute is no longer set by the openPMD-api.")]] bool
237  closedByWriter() const;
238 
239  Container<Mesh> meshes{};
240  Container<ParticleSpecies> particles{}; // particleSpecies?
241 
242  virtual ~Iteration() = default;
243 
244 private:
245  Iteration();
246 
248  std::shared_ptr<Data_t> m_iterationData;
249 
250  inline Data_t const &get() const
251  {
252  return *m_iterationData;
253  }
254 
255  inline Data_t &get()
256  {
257  return *m_iterationData;
258  }
259 
260  inline void setData(std::shared_ptr<Data_t> data)
261  {
262  m_iterationData = std::move(data);
263  Attributable::setData(m_iterationData);
264  }
265 
266  void flushFileBased(
267  std::string const &, IterationIndex_t, internal::FlushParams const &);
268  void flushGroupBased(IterationIndex_t, internal::FlushParams const &);
269  void flushVariableBased(IterationIndex_t, internal::FlushParams const &);
270  void flush(internal::FlushParams const &);
271  void deferParseAccess(internal::DeferredParseAccess);
272  /*
273  * Control flow for runDeferredParseAccess(), readFileBased(),
274  * readGroupBased() and read_impl():
275  * runDeferredParseAccess() is called as the entry point.
276  * File-based and group-based
277  * iteration layouts need to be parsed slightly differently:
278  * In file-based iteration layout, each iteration's file also contains
279  * attributes for the /data group. In group-based layout, those have
280  * already been parsed during opening of the Series.
281  * Hence, runDeferredParseAccess() will call either readFileBased() or
282  * readGroupBased() to
283  * allow for those different control flows.
284  * Finally, read_impl() is called which contains the common parsing
285  * logic for an iteration.
286  *
287  * reread() reads again an Iteration that has been previously read.
288  * Calling it on an Iteration not yet parsed is an error.
289  *
290  */
291  void reread(std::string const &path);
292  void readFileBased(
293  std::string const &filePath,
294  std::string const &groupPath,
295  bool beginStep);
296  void readGorVBased(std::string const &groupPath, bool beginStep);
297  void read_impl(std::string const &groupPath);
298  void readMeshes(std::string const &meshesPath);
299  void readParticles(std::string const &particlesPath);
300 
306  struct BeginStepStatus
307  {
308  using AvailableIterations_t = std::optional<std::deque<uint64_t> >;
309 
310  AdvanceStatus stepStatus{};
311  /*
312  * If the iteration attribute `snapshot` is present, the value of that
313  * attribute. Otherwise empty.
314  */
315  AvailableIterations_t iterationsInOpenedStep;
316 
317  /*
318  * Most of the time, the AdvanceStatus part of this struct is what we
319  * need, so let's make it easy to access.
320  */
321  inline operator AdvanceStatus() const
322  {
323  return stepStatus;
324  }
325 
326  /*
327  * Support for std::tie()
328  */
329  inline operator std::tuple<AdvanceStatus &, AvailableIterations_t &>()
330  {
331  return std::tuple<AdvanceStatus &, AvailableIterations_t &>{
332  stepStatus, iterationsInOpenedStep};
333  }
334  };
335 
343  BeginStepStatus beginStep(bool reread);
344 
345  /*
346  * Iteration-independent variant for beginStep().
347  * Useful in group-based iteration encoding where the Iteration will only
348  * be known after opening the step.
349  */
350  static BeginStepStatus beginStep(
351  std::optional<Iteration> thisObject,
352  Series &series,
353  bool reread,
354  std::set<IterationIndex_t> const &ignoreIterations = {});
355 
361  void endStep();
362 
371  StepStatus getStepStatus();
372 
381  void setStepStatus(StepStatus);
382 
388  virtual void linkHierarchy(Writable &w);
389 
395  void runDeferredParseAccess();
396 }; // Iteration
397 
398 extern template float Iteration::time<float>() const;
399 
400 extern template double Iteration::time<double>() const;
401 
402 extern template long double Iteration::time<long double>() const;
403 
404 template <typename T>
405 inline T Iteration::time() const
406 {
407  return this->readFloatingpoint<T>("time");
408 }
409 
410 extern template float Iteration::dt<float>() const;
411 
412 extern template double Iteration::dt<double>() const;
413 
414 extern template long double Iteration::dt<long double>() const;
415 
416 template <typename T>
417 inline T Iteration::dt() const
418 {
419  return this->readFloatingpoint<T>("dt");
420 }
421 
427 {
428  friend class SeriesIterator;
429  friend class WriteIterations;
430 
431 public:
432  using index_t = Iteration::IterationIndex_t;
433  index_t const iterationIndex;
434 
435 private:
436  template <typename Iteration_t>
437  IndexedIteration(Iteration_t &&it, index_t index)
438  : Iteration(std::forward<Iteration_t>(it)), iterationIndex(index)
439  {}
440 };
441 } // namespace openPMD
Layer to manage storage of attributes associated with file objects.
Definition: Attributable.hpp:101
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:427
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:77
double timeUnitSI() const
Definition: Iteration.cpp:72
Iteration & setTime(T newTime)
Set the global reference time for this iteration.
Definition: Iteration.cpp:51
bool closedByWriter() const
Has the iteration been closed by the writer? Background: Upon calling Iteration::close(),...
Definition: Iteration.cpp:183
T time() const
Definition: Iteration.hpp:405
bool closed() const
Has the iteration been closed? A closed iteration may not (yet) be reopened.
Definition: Iteration.cpp:163
T dt() const
Definition: Iteration.hpp:417
Iteration & open()
Open an iteration.
Definition: Iteration.cpp:147
Iteration & close(bool flush=true)
Close an iteration.
Definition: Iteration.cpp:85
Iteration & setDt(T newDt)
Set the time step used to reach this iteration.
Definition: Iteration.cpp:62
Implementation for the root level of the openPMD hierarchy.
Definition: Series.hpp:219
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
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