openPMD-api
RecordComponent.hpp
1 /* Copyright 2017-2021 Fabian Koller, Axel Huebl and Franz Poeschel
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/Dataset.hpp"
24 #include "openPMD/Datatype.hpp"
25 #include "openPMD/auxiliary/ShareRaw.hpp"
26 #include "openPMD/auxiliary/TypeTraits.hpp"
27 #include "openPMD/auxiliary/UniquePtr.hpp"
28 #include "openPMD/backend/BaseRecordComponent.hpp"
29 
30 #include <array>
31 #include <cmath>
32 #include <limits>
33 #include <memory>
34 #include <queue>
35 #include <sstream>
36 #include <stdexcept>
37 #include <string>
38 #include <type_traits>
39 #include <utility>
40 #include <vector>
41 
42 // expose private and protected members for invasive testing
43 #ifndef OPENPMD_protected
44 #define OPENPMD_protected protected:
45 #endif
46 
47 namespace openPMD
48 {
49 
50 template <typename T>
51 class DynamicMemoryView;
52 
53 class RecordComponent;
54 
55 namespace internal
56 {
58  {
59  public:
61 
62  RecordComponentData(RecordComponentData const &) = delete;
64 
65  RecordComponentData &operator=(RecordComponentData const &) = delete;
66  RecordComponentData &operator=(RecordComponentData &&) = delete;
67 
71  std::queue<IOTask> m_chunks;
72 
73  void push_chunk(IOTask &&task);
88  std::string m_name;
95  bool m_isEmpty = false;
100  bool m_hasBeenExtended = false;
101 
102  void reset() override
103  {
104  BaseRecordComponentData::reset();
105  m_chunks = std::queue<IOTask>();
106  m_constantValue = -1;
107  m_name = std::string();
108  m_isEmpty = false;
109  m_hasBeenExtended = false;
110  }
111  };
112  template <typename, typename>
113  class BaseRecordData;
114 } // namespace internal
115 
116 template <typename>
117 class BaseRecord;
118 
120 {
121  template <typename T, typename T_key, typename T_container>
122  friend class Container;
123  friend class Iteration;
124  friend class ParticleSpecies;
125  template <typename>
126  friend class BaseRecord;
127  template <typename, typename>
128  friend class internal::BaseRecordData;
129  friend class Record;
130  friend class Mesh;
131  template <typename>
132  friend class DynamicMemoryView;
133  friend class internal::RecordComponentData;
134  friend class MeshRecordComponent;
135 
136 public:
137  enum class Allocation
138  {
139  USER,
140  API,
141  AUTO
142  }; // Allocation
143 
152 
153  RecordComponent &setUnitSI(double);
154 
174 
175  uint8_t getDimensionality() const;
176  Extent getExtent() const;
177 
186  template <typename T>
188 
197  template <typename T>
198  RecordComponent &makeEmpty(uint8_t dimensions);
199 
208  RecordComponent &makeEmpty(Datatype dt, uint8_t dimensions);
209 
217  bool empty() const;
218 
226  template <typename T>
227  std::shared_ptr<T> loadChunk(Offset = {0u}, Extent = {-1u});
228 
229  using shared_ptr_dataset_types = auxiliary::detail::
230  map_variant<auxiliary::detail::as_shared_pointer, dataset_types>::type;
231 
242  shared_ptr_dataset_types loadChunkVariant(Offset = {0u}, Extent = {-1u});
243 
265  template <typename T>
266  void loadChunk(std::shared_ptr<T> data, Offset offset, Extent extent);
267 
284  template <typename T>
285  void loadChunk(std::shared_ptr<T[]> data, Offset offset, Extent extent);
286 
302  template <typename T>
303  void loadChunkRaw(T *data, Offset offset, Extent extent);
304 
323  template <typename T>
324  void storeChunk(std::shared_ptr<T> data, Offset offset, Extent extent);
325 
335  template <typename T>
336  void storeChunk(std::shared_ptr<T[]> data, Offset offset, Extent extent);
337 
350  template <typename T>
351  void storeChunk(UniquePtrWithLambda<T> data, Offset offset, Extent extent);
352 
365  template <typename T, typename Del>
366  void storeChunk(std::unique_ptr<T, Del> data, Offset offset, Extent extent);
367 
380  template <typename T>
381  void storeChunkRaw(T *data, Offset offset, Extent extent);
382 
398  template <typename T_ContiguousContainer>
399  typename std::enable_if_t<
400  auxiliary::IsContiguousContainer_v<T_ContiguousContainer>>
402  T_ContiguousContainer &data,
403  Offset offset = {0u},
404  Extent extent = {-1u});
405 
439  template <typename T, typename F>
440  DynamicMemoryView<T>
441  storeChunk(Offset offset, Extent extent, F &&createBuffer);
442 
447  template <typename T>
449 
480  template <typename Visitor, typename... Args>
481  auto visit(Args &&...args) -> decltype(Visitor::template call<char>(
482  std::declval<RecordComponent &>(),
483  std::forward<Args>(args)...));
484 
485  static constexpr char const *const SCALAR = "\vScalar";
486 
487 protected:
488  void flush(std::string const &, internal::FlushParams const &);
489  void read(bool require_unit_si);
490 
491 private:
499 
500  void storeChunk(
501  auxiliary::WriteBuffer buffer, Datatype datatype, Offset o, Extent e);
502 
503  // clang-format off
504 OPENPMD_protected
505  // clang-format on
506 
508  std::shared_ptr<Data_t> m_recordComponentData;
509 
510  RecordComponent();
512 
513  inline Data_t const &get() const
514  {
515  // cannot call this in the const overload
516  // datasetDefined(*m_recordComponentData);
517  return *m_recordComponentData;
518  }
519 
520  inline Data_t &get()
521  {
522  setDatasetDefined(*m_recordComponentData);
523  return *m_recordComponentData;
524  }
525 
526  inline void setData(std::shared_ptr<internal::RecordComponentData> data)
527  {
528  m_recordComponentData = std::move(data);
529  BaseRecordComponent::setData(m_recordComponentData);
530  }
531 
532  void readBase(bool require_unit_si);
533 
534  template <typename T>
535  void verifyChunk(Offset const &, Extent const &) const;
536 
537  void verifyChunk(Datatype, Offset const &, Extent const &) const;
538 }; // RecordComponent
539 
540 } // namespace openPMD
541 
542 #include "RecordComponent.tpp"
Variant datatype supporting at least all formats for attributes specified in the openPMD standard.
Definition: Attribute.hpp:56
Definition: BaseRecordComponent.hpp:81
Base class for any type of record (e.g.
Definition: BaseRecord.hpp:224
Map-like container that enforces openPMD requirements and handles IO.
Definition: Container.hpp:104
Definition: Dataset.hpp:38
A view into a buffer that might be reallocated at some points and thus has changing base pointers ove...
Definition: Span.hpp:97
Self-contained description of a single IO operation.
Definition: IOTask.hpp:670
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:127
Container for N-dimensional, homogeneous Records.
Definition: Mesh.hpp:41
Definition: MeshRecordComponent.hpp:36
Definition: ParticleSpecies.hpp:34
Definition: RecordComponent.hpp:120
void loadChunk(std::shared_ptr< T[]> data, Offset offset, Extent extent)
Load a chunk of data into pre-allocated memory, array version.
RecordComponent & makeEmpty(uint8_t dimensions)
Create a dataset with zero extent in each dimension.
void storeChunk(UniquePtrWithLambda< T > data, Offset offset, Extent extent)
Store a chunk of data from a chunk of memory, unique pointer version.
DynamicMemoryView< T > storeChunk(Offset offset, Extent extent, F &&createBuffer)
Overload of storeChunk() that lets the openPMD API allocate a buffer.
void loadChunk(std::shared_ptr< T > data, Offset offset, Extent extent)
Load a chunk of data into pre-allocated memory.
virtual RecordComponent & resetDataset(Dataset)
Declare the dataset's type and extent.
Definition: RecordComponent.cpp:84
auto visit(Args &&...args) -> decltype(Visitor::template call< char >(std::declval< RecordComponent & >(), std::forward< Args >(args)...))
Run a template functor on the type of the record component, similar to std::visit().
bool empty() const
Returns true if this is an empty record component.
Definition: RecordComponent.cpp:229
std::enable_if_t< auxiliary::IsContiguousContainer_v< T_ContiguousContainer > > storeChunk(T_ContiguousContainer &data, Offset offset={0u}, Extent extent={-1u})
Store a chunk of data from a contiguous container.
void storeChunk(std::shared_ptr< T > data, Offset offset, Extent extent)
Store a chunk of data from a chunk of memory.
shared_ptr_dataset_types loadChunkVariant(Offset={0u}, Extent={-1u})
std::variant-based version of allocating loadChunk<T>(Offset, Extent)
Definition: RecordComponent.cpp:560
void storeChunk(std::unique_ptr< T, Del > data, Offset offset, Extent extent)
Store a chunk of data from a chunk of memory, unique pointer version.
void storeChunkRaw(T *data, Offset offset, Extent extent)
Store a chunk of data from a chunk of memory, raw pointer version.
std::shared_ptr< T > loadChunk(Offset={0u}, Extent={-1u})
Load and allocate a chunk of data.
void storeChunk(std::shared_ptr< T[]> data, Offset offset, Extent extent)
Store a chunk of data from a chunk of memory, array version.
void loadChunkRaw(T *data, Offset offset, Extent extent)
Load a chunk of data into pre-allocated memory, raw pointer version.
RecordComponent & makeConstant(T)
Create a dataset with regular extent and constant value.
DynamicMemoryView< T > storeChunk(Offset, Extent)
Overload of span-based storeChunk() that uses operator new() to create a buffer.
Definition: Record.hpp:33
Unique Pointer class that uses a dynamic destructor type.
Definition: UniquePtr.hpp:80
Definition: Attributable.hpp:57
Definition: BaseRecordComponent.hpp:39
Definition: BaseRecord.hpp:52
Definition: RecordComponent.hpp:58
bool m_hasBeenExtended
User has extended the dataset, but the EXTEND task must yet be flushed to the backend.
Definition: RecordComponent.hpp:100
std::queue< IOTask > m_chunks
Chunk reading/writing requests on the contained dataset.
Definition: RecordComponent.hpp:71
Attribute m_constantValue
Stores the value for constant record components.
Definition: RecordComponent.hpp:78
bool m_isEmpty
True if this component is an empty dataset, i.e.
Definition: RecordComponent.hpp:95
std::string m_name
The same std::string that the parent class would pass as parameter to RecordComponent::flush().
Definition: RecordComponent.hpp:88
Public definitions of openPMD-api.
Definition: Date.cpp:29
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:51
Definition: Attributable.hpp:125
Definition: Memory.hpp:175
Parameters recursively passed through the openPMD hierarchy when flushing.
Definition: AbstractIOHandler.hpp:86