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