openPMD-api
PatchRecordComponent.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/auxiliary/ShareRawInternal.hpp"
24 #include "openPMD/backend/BaseRecordComponent.hpp"
25 
26 #include <memory>
27 #include <sstream>
28 #include <stdexcept>
29 #include <string>
30 #include <unordered_map>
31 
32 // expose private and protected members for invasive testing
33 #ifndef OPENPMD_private
34 #define OPENPMD_private private:
35 #endif
36 
37 namespace openPMD
38 {
39 namespace internal
40 {
42  {
43  public:
47  std::queue<IOTask> m_chunks;
48 
51 
53  operator=(PatchRecordComponentData const &) = delete;
55  operator=(PatchRecordComponentData &&) = delete;
56 
58  };
59 } // namespace internal
60 
65 {
66  template <typename T, typename T_key, typename T_container>
67  friend class Container;
68  template <typename>
69  friend class BaseRecord;
70  friend class ParticlePatches;
71  friend class PatchRecord;
72  friend class ParticleSpecies;
74 
75 public:
76  PatchRecordComponent &setUnitSI(double);
77 
78  PatchRecordComponent &resetDataset(Dataset);
79 
80  uint8_t getDimensionality() const;
81  Extent getExtent() const;
82 
83  template <typename T>
84  std::shared_ptr<T> load();
85 
86  template <typename T>
87  void load(std::shared_ptr<T>);
88 
89  template <typename T>
90  void load(std::shared_ptr<T[]>);
91 
92  template <typename T>
93  void loadRaw(T *);
94 
95  template <typename T>
96  void store(uint64_t idx, T);
97 
98  // clang-format off
99 OPENPMD_private
100  // clang-format on
101 
102  void flush(std::string const &, internal::FlushParams const &);
103  void read();
104 
113  bool dirtyRecursive() const;
114 
115  std::shared_ptr<internal::PatchRecordComponentData>
116  m_patchRecordComponentData{new internal::PatchRecordComponentData()};
117 
119 
120  // clang-format off
121 OPENPMD_protected
122  // clang-format on
123 
124  PatchRecordComponent(std::shared_ptr<internal::PatchRecordComponentData>);
125 
126  inline internal::PatchRecordComponentData const &get() const
127  {
128  return *m_patchRecordComponentData;
129  }
130 
132  {
133  return *m_patchRecordComponentData;
134  }
135 
136  inline void
137  setData(std::shared_ptr<internal::PatchRecordComponentData> data)
138  {
139  m_patchRecordComponentData = std::move(data);
140  BaseRecordComponent::setData(m_patchRecordComponentData);
141  }
142 }; // PatchRecordComponent
143 
144 template <typename T>
145 inline std::shared_ptr<T> PatchRecordComponent::load()
146 {
147  uint64_t numPoints = getExtent()[0];
148 #if (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 11000) || \
149  (defined(__apple_build_version__) && __clang_major__ < 14)
150  auto newData =
151  std::shared_ptr<T>(new T[numPoints], [](T *p) { delete[] p; });
152  load(newData);
153  return newData;
154 #else
155  auto newData = std::shared_ptr<T[]>(new T[numPoints]);
156  load(newData);
157  return std::static_pointer_cast<T>(std::move(newData));
158 #endif
159 }
160 
161 template <typename T>
162 inline void PatchRecordComponent::load(std::shared_ptr<T> data)
163 {
164  Datatype dtype = determineDatatype<T>();
165  if (dtype != getDatatype())
166  throw std::runtime_error(
167  "Type conversion during particle patch loading not yet "
168  "implemented");
169 
170  if (!data)
171  throw std::runtime_error(
172  "Unallocated pointer passed during ParticlePatch loading.");
173 
174  uint64_t numPoints = getExtent()[0];
175 
177 
179  dRead.offset = {0};
180  dRead.extent = {numPoints};
181  dRead.dtype = getDatatype();
182  dRead.data = std::static_pointer_cast<void>(data);
183  auto &rc = get();
184  rc.m_chunks.push(IOTask(this, dRead));
185 }
186 
187 template <typename T>
188 inline void PatchRecordComponent::load(std::shared_ptr<T[]> data)
189 {
190  load(std::static_pointer_cast<T>(std::move(data)));
191 }
192 
193 template <typename T>
194 inline void PatchRecordComponent::loadRaw(T *data)
195 {
196  load<T>(auxiliary::shareRaw(data));
197 }
198 
199 template <typename T>
200 inline void PatchRecordComponent::store(uint64_t idx, T data)
201 {
202  Datatype dtype = determineDatatype<T>();
203  if (dtype != getDatatype())
204  {
205  std::ostringstream oss;
206  oss << "Datatypes of patch data (" << dtype << ") and dataset ("
207  << getDatatype() << ") do not match.";
208  throw std::runtime_error(oss.str());
209  }
210 
211  Extent dse = getExtent();
212  if (dse[0] - 1u < idx)
213  throw std::runtime_error(
214  "Index does not reside inside patch (no. patches: " +
215  std::to_string(dse[0]) + " - index: " + std::to_string(idx) + ")");
216 
218  dWrite.offset = {idx};
219  dWrite.extent = {1};
220  dWrite.dtype = dtype;
221  dWrite.data = std::make_shared<T>(data);
222  auto &rc = get();
223  rc.m_chunks.push(IOTask(this, std::move(dWrite)));
224 }
225 } // namespace openPMD
Definition: ParticlePatches.hpp:31
Definition: Dataset.hpp:35
Self-contained description of a single IO operation.
Definition: IOTask.hpp:695
Definition: PatchRecord.hpp:31
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:45
Definition: PatchRecordComponent.hpp:41
Public definitions of openPMD-api.
Definition: BaseRecord.hpp:58
Parameters recursively passed through the openPMD hierarchy when flushing.
Definition: AbstractIOHandler.hpp:84
std::queue< IOTask > m_chunks
Chunk reading/writing requests on the contained dataset.
Definition: PatchRecordComponent.hpp:47
Definition: ParticleSpecies.hpp:33
Definition: PatchRecordComponent.hpp:64
Map-like container that enforces openPMD requirements and handles IO.
Definition: Container.hpp:131
Definition: BaseRecordComponent.hpp:36
Definition: BaseRecordComponent.hpp:62