forked from openPMD/openPMD-api
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathIteration.hpp
More file actions
481 lines (429 loc) · 15.4 KB
/
Iteration.hpp
File metadata and controls
481 lines (429 loc) · 15.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
/* Copyright 2017-2025 Fabian Koller, Axel Huebl, Franz Poeschel, Luca Fedeli
*
* This file is part of openPMD-api.
*
* openPMD-api is free software: you can redistribute it and/or modify
* it under the terms of of either the GNU General Public License or
* the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* openPMD-api is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with openPMD-api.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "openPMD/IterationEncoding.hpp"
#include "openPMD/Mesh.hpp"
#include "openPMD/ParticleSpecies.hpp"
#include "openPMD/Streaming.hpp"
#include "openPMD/auxiliary/Variant.hpp"
#include "openPMD/backend/Attributable.hpp"
#include "openPMD/backend/Container.hpp"
#include <cstdint>
#include <deque>
#include <optional>
#include <set>
#include <tuple>
namespace openPMD
{
namespace internal
{
/**
* @brief Whether an iteration has been closed yet.
*
*/
enum class CloseStatus
{
ParseAccessDeferred, //!< The reader has not yet parsed this iteration
Open, //!< Iteration has not been closed
ClosedInFrontend, /*!< Iteration has been closed, but task has not yet
been propagated to the backend */
Closed, /*!< Iteration has been closed and task has been
propagated to the backend */
};
namespace BeginStepTypes
{
struct DontBeginStep
{};
struct BeginStepSequentially
{};
struct BeginStepRandomAccess
{
size_t step;
};
} // namespace BeginStepTypes
using BeginStep = std::variant<
BeginStepTypes::DontBeginStep,
BeginStepTypes::BeginStepSequentially,
BeginStepTypes::BeginStepRandomAccess>;
namespace BeginStepTypes
{
template <typename T, typename... Args>
constexpr auto make(Args &&...args) -> BeginStep
{
return BeginStep{T{std::forward<Args>(args)...}};
}
} // namespace BeginStepTypes
struct DeferredParseAccess
{
/**
* The group path within /data containing this iteration.
* Example: "1" for iteration 1, "" in variable-based iteration
* encoding.
*/
std::string path;
/**
* The iteration index as accessed by the user in series.iterations[i]
*/
uint64_t iteration = 0;
/**
* If this iteration is part of a Series with file-based layout.
* (Group- and variable-based parsing shares the same code logic.)
*/
bool fileBased = false;
BeginStep beginStep = BeginStepTypes::DontBeginStep{};
};
class IterationData : public AttributableData
{
public:
/*
* An iteration may be logically closed in the frontend,
* but not necessarily yet in the backend.
* Will be propagated to the backend upon next flush.
* Store the current status.
* Once an iteration has been closed, no further flushes shall be
* performed. If flushing a closed file, the old file may otherwise be
* overwritten.
*/
CloseStatus m_closed = CloseStatus::Open;
/*
* While parsing a file-based Series, each file is opened, read, then
* closed again. Explicitly `Iteration::open()`ing a file should only be
* necessary after having explicitly closed it (or in
* defer_iteration_parsing mode). So, the parsing procedures will set
* this flag as true when closing an Iteration.
*/
bool allow_reopening_implicitly = false;
/**
* Whether a step is currently active for this iteration.
* Used for file-based iteration layout, see Series.hpp for
* group-based layout.
* Access via stepStatus() method to automatically select the correct
* one among both flags.
*/
StepStatus m_stepStatus = StepStatus::NoStep;
/**
* Information on a parsing request that has not yet been executed.
* Otherwise empty.
*/
std::optional<DeferredParseAccess> m_deferredParseAccess{};
};
} // namespace internal
/** @brief Logical compilation of data from one snapshot (e.g. a single
* simulation cycle).
*
* @see
* https://github.com/openPMD/openPMD-standard/blob/latest/STANDARD.md#required-attributes-for-the-basepath
*/
class Iteration : public Attributable
{
template <typename T, typename T_key, typename T_container>
friend class Container;
friend class Series;
friend class internal::AttributableData;
template <typename T>
friend T &internal::makeOwning(T &self, Series);
friend class Writable;
friend class StatefulIterator;
friend class StatefulSnapshotsContainer;
public:
Iteration(Iteration const &) = default;
Iteration(Iteration &&) = default;
Iteration &operator=(Iteration const &) = default;
Iteration &operator=(Iteration &&) = default;
using IterationIndex_t = uint64_t;
/**
* @tparam T Floating point type of user-selected precision (e.g. float,
* double).
* @return Global reference time for this iteration.
*/
template <typename T>
T time() const;
/** Set the global reference time for this iteration.
*
* @tparam T Floating point type of user-selected precision (e.g.
* float, double).
* @param newTime Global reference time for this iteration.
* @return Reference to modified iteration.
*/
template <typename T>
Iteration &setTime(T newTime);
/**
* @tparam T Floating point type of user-selected precision (e.g. float,
* double).
* @return Time step used to reach this iteration.
*/
template <typename T>
T dt() const;
/** Set the time step used to reach this iteration.
*
* @tparam T Floating point type of user-selected precision (e.g.
* float, double).
* @param newDt Time step used to reach this iteration.
* @return Reference to modified iteration.
*/
template <typename T>
Iteration &setDt(T newDt);
/**
* @return Conversion factor to convert time and dt to seconds.
*/
double timeUnitSI() const;
/** Set the conversion factor to convert time and dt to seconds.
*
* @param newTimeUnitSI new value for timeUnitSI
* @return Reference to modified iteration.
*/
Iteration &setTimeUnitSI(double newTimeUnitSI);
/** Close an iteration
*
* No further (backend-propagating) accesses may be performed on this
* iteration. A closed iteration may not (yet) be reopened.
*
* With an MPI-parallel series, close is an MPI-collective operation.
*
* @return Reference to iteration.
*/
/*
* Note: If the API is changed in future to allow reopening closed
* iterations, measures should be taken to prevent this in the streaming
* API. Currently, disallowing to reopen closed iterations satisfies
* the requirements of the streaming API.
*/
Iteration &close(bool flush = true);
/** Open an iteration
*
* Explicitly open an iteration.
* Usually, file-open operations are delayed until the first load/storeChunk
* operation is flush-ed. In parallel contexts where it is know that such a
* first access needs to be run non-collectively, one can explicitly open
* an iteration through this collective call.
* Also necessary when using defer_iteration_parsing.
* The Streaming API (i.e. Series::readIterations()) will call this method
* implicitly and users need not call it.
*
* @return Reference to iteration.
*/
Iteration &open();
/**
* @brief Has the iteration been closed?
*
* @return Whether the iteration has been closed.
*/
bool closed() const;
/**
* @brief Has the iteration been parsed yet?
If not, it will contain no structure yet.
*
* @return Whether the iteration has been parsed.
*/
bool parsed() const;
/**
* @brief Has the iteration been closed by the writer?
* Background: Upon calling Iteration::close(), the openPMD API
* will add metadata to the iteration in form of an attribute,
* indicating that the iteration has indeed been closed.
* Useful mainly in streaming context when a reader inquires from
* a writer that it is done writing.
*
* @return Whether the iteration has been explicitly closed (yet) by the
* writer.
*/
[[deprecated("This attribute is no longer set by the openPMD-api.")]] bool
closedByWriter() const;
Container<Mesh> meshes{};
Container<ParticleSpecies> particles{}; // particleSpecies?
virtual ~Iteration() = default;
private:
Iteration();
using Data_t = internal::IterationData;
std::shared_ptr<Data_t> m_iterationData;
inline Data_t const &get() const
{
return *m_iterationData;
}
inline Data_t &get()
{
return *m_iterationData;
}
inline std::shared_ptr<Data_t> getShared()
{
return m_iterationData;
}
inline void setData(std::shared_ptr<Data_t> data)
{
m_iterationData = std::move(data);
Attributable::setData(m_iterationData);
}
void flushFileBased(
std::string const &, IterationIndex_t, internal::FlushParams const &);
void flushGroupBased(IterationIndex_t, internal::FlushParams const &);
void flushVariableBased(IterationIndex_t, internal::FlushParams const &);
void flush(internal::FlushParams const &);
void deferParseAccess(internal::DeferredParseAccess);
/*
* Control flow for runDeferredParseAccess(), readFileBased(),
* readGroupBased() and read_impl():
* runDeferredParseAccess() is called as the entry point.
* File-based and group-based
* iteration layouts need to be parsed slightly differently:
* In file-based iteration layout, each iteration's file also contains
* attributes for the /data group. In group-based layout, those have
* already been parsed during opening of the Series.
* Hence, runDeferredParseAccess() will call either readFileBased() or
* readGroupBased() to
* allow for those different control flows.
* Finally, read_impl() is called which contains the common parsing
* logic for an iteration.
*
* reread() reads again an Iteration that has been previously read.
* Calling it on an Iteration not yet parsed is an error.
*
*/
void reread(std::string const &path);
void readFileBased(
IterationIndex_t,
std::string const &filePath,
std::string const &groupPath,
bool beginStep);
void readGorVBased(
std::string const &groupPath, internal::BeginStep const &beginStep);
void read_impl(std::string const &groupPath);
void readMeshes(std::string const &meshesPath);
void readParticles(std::string const &particlesPath);
/**
* Status after beginning an IO step. Currently includes:
* * The advance status (OK, OVER, RANDOMACCESS)
* * The opened iterations, in case the snapshot attribute is found
*/
struct BeginStepStatus
{
using AvailableIterations_t = std::vector<IterationIndex_t>;
AdvanceStatus stepStatus{};
/*
* If the iteration attribute `snapshot` is present, the value of that
* attribute. Otherwise empty.
*/
AvailableIterations_t iterationsInOpenedStep;
/*
* Most of the time, the AdvanceStatus part of this struct is what we
* need, so let's make it easy to access.
*/
inline operator AdvanceStatus() const
{
return stepStatus;
}
/*
* Support for std::tie()
*/
inline operator std::tuple<AdvanceStatus &, AvailableIterations_t &>()
{
return std::tuple<AdvanceStatus &, AvailableIterations_t &>{
stepStatus, iterationsInOpenedStep};
}
};
/**
* @brief Begin an IO step on the IO file (or file-like object)
* containing this iteration. In case of group-based iteration
* layout, this will be the complete Series.
*
* @return BeginStepStatus
*/
BeginStepStatus beginStep(bool reread);
/*
* Iteration-independent variant for beginStep().
* Useful in group-based iteration encoding where the Iteration will only
* be known after opening the step.
*/
static BeginStepStatus
beginStep(std::optional<Iteration> thisObject, Series &series, bool reread);
/**
* @brief End an IO step on the IO file (or file-like object)
* containing this iteration. In case of group-based iteration
* layout, this will be the complete Series.
*/
void endStep();
/**
* @brief Is a step currently active for this iteration?
*
* In case of group-based iteration layout, this information is global
* (member of the Series object containing this iteration),
* in case of file-based iteration layout, it is local (member of this very
* object).
*/
StepStatus getStepStatus();
/**
* @brief Set step activity status for this iteration.
*
* In case of group-based iteration layout, this information is set
* globally (member of the Series object containing this iteration),
* in case of file-based iteration layout, it is set locally (member of
* this very object).
*/
void setStepStatus(StepStatus);
/**
* @brief Link with parent.
*
* @param w The Writable representing the parent.
*/
virtual void linkHierarchy(Writable &w);
/**
* @brief Access an iteration in read mode that has potentially not been
* parsed yet.
*
*/
void runDeferredParseAccess();
}; // Iteration
extern template float Iteration::time<float>() const;
extern template double Iteration::time<double>() const;
extern template long double Iteration::time<long double>() const;
template <typename T>
inline T Iteration::time() const
{
return this->readFloatingpoint<T>("time");
}
extern template float Iteration::dt<float>() const;
extern template double Iteration::dt<double>() const;
extern template long double Iteration::dt<long double>() const;
template <typename T>
inline T Iteration::dt() const
{
return this->readFloatingpoint<T>("dt");
}
/**
* @brief Subclass of Iteration that knows its own index withing the containing
* Series.
*/
class IndexedIteration : public Iteration
{
friend class StatefulIterator;
friend class LegacyIteratorAdaptor;
public:
using index_t = Iteration::IterationIndex_t;
index_t const iterationIndex;
inline IndexedIteration(std::pair<index_t const, Iteration> pair)
: Iteration(std::move(pair.second)), iterationIndex(pair.first)
{}
private:
template <typename Iteration_t>
IndexedIteration(Iteration_t &&it, index_t index)
: Iteration(std::forward<Iteration_t>(it)), iterationIndex(index)
{}
};
} // namespace openPMD