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/Error.hpp"
24 #include "openPMD/RecordComponent.hpp"
25 #include "openPMD/auxiliary/ShareRawInternal.hpp"
26 #include "openPMD/backend/BaseRecordComponent.hpp"
27 
28 #include <memory>
29 #include <sstream>
30 #include <stdexcept>
31 #include <string>
32 #include <unordered_map>
33 
34 // expose private and protected members for invasive testing
35 #ifndef OPENPMD_private
36 #define OPENPMD_private private:
37 #endif
38 
39 namespace openPMD
40 {
41 
46 {
47  template <typename T, typename T_key, typename T_container>
48  friend class Container;
49  template <typename>
50  friend class BaseRecord;
51  template <typename, typename>
52  friend class internal::BaseRecordData;
53  friend class ParticlePatches;
54  friend class PatchRecord;
55  friend class ParticleSpecies;
56 
57 public:
66 
67  PatchRecordComponent &setUnitSI(double);
68 
70 
71  uint8_t getDimensionality() const;
72  Extent getExtent() const;
73 
74  template <typename T>
75  std::shared_ptr<T> load();
76 
77  template <typename T>
78  void load(std::shared_ptr<T>);
79 
80  template <typename T>
81  void load(std::shared_ptr<T[]>);
82 
83  template <typename T>
84  void loadRaw(T *);
85 
86  template <typename T>
87  void store(uint64_t idx, T);
88 
89  template <typename T>
90  void store(T);
91 
92  // clang-format off
93 OPENPMD_private
94  // clang-format on
95 
96  using RecordComponent::flush;
97 
98  // clang-format off
99 OPENPMD_protected
100  // clang-format on
101 
104 }; // PatchRecordComponent
105 
106 template <typename T>
107 inline std::shared_ptr<T> PatchRecordComponent::load()
108 {
109  uint64_t numPoints = getExtent()[0];
110 #if (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 11000) || \
111  (defined(__apple_build_version__) && __clang_major__ < 14)
112  auto newData =
113  std::shared_ptr<T>(new T[numPoints], [](T *p) { delete[] p; });
114  load(newData);
115  return newData;
116 #else
117  auto newData = std::shared_ptr<T[]>(new T[numPoints]);
118  load(newData);
119  return std::static_pointer_cast<T>(std::move(newData));
120 #endif
121 }
122 
123 template <typename T>
124 inline void PatchRecordComponent::load(std::shared_ptr<T> data)
125 {
126  Datatype dtype = determineDatatype<T>();
127  if (dtype != getDatatype())
128  throw std::runtime_error(
129  "Type conversion during particle patch loading not yet "
130  "implemented");
131 
132  if (!data)
133  throw std::runtime_error(
134  "Unallocated pointer passed during ParticlePatch loading.");
135 
136  uint64_t numPoints = getExtent()[0];
137 
139 
141  dRead.offset = {0};
142  dRead.extent = {numPoints};
143  dRead.dtype = getDatatype();
144  dRead.data = std::static_pointer_cast<void>(data);
145  auto &rc = get();
146  rc.push_chunk(IOTask(this, dRead));
147 }
148 
149 template <typename T>
150 inline void PatchRecordComponent::load(std::shared_ptr<T[]> data)
151 {
152  load(std::static_pointer_cast<T>(std::move(data)));
153 }
154 
155 template <typename T>
156 inline void PatchRecordComponent::loadRaw(T *data)
157 {
158  load<T>(auxiliary::shareRaw(data));
159 }
160 
161 template <typename T>
162 inline void PatchRecordComponent::store(uint64_t idx, T data)
163 {
164  Datatype dtype = determineDatatype<T>();
165  if (dtype != getDatatype())
166  {
167  std::ostringstream oss;
168  oss << "Datatypes of patch data (" << dtype << ") and dataset ("
169  << getDatatype() << ") do not match.";
170  throw std::runtime_error(oss.str());
171  }
172 
173  Extent dse = getExtent();
174  if (dse[0] - 1u < idx)
175  throw std::runtime_error(
176  "Index does not reside inside patch (no. patches: " +
177  std::to_string(dse[0]) + " - index: " + std::to_string(idx) + ")");
178 
179  Parameter<Operation::WRITE_DATASET> dWrite;
180  dWrite.offset = {idx};
181  dWrite.extent = {1};
182  dWrite.dtype = dtype;
183  dWrite.data = std::make_shared<T>(data);
184  auto &rc = get();
185  rc.push_chunk(IOTask(this, std::move(dWrite)));
186 }
187 
188 template <typename T>
189 inline void PatchRecordComponent::store(T data)
190 {
191  Datatype dtype = determineDatatype<T>();
192  if (dtype != getDatatype())
193  {
194  std::ostringstream oss;
195  oss << "Datatypes of patch data (" << dtype << ") and dataset ("
196  << getDatatype() << ") do not match.";
197  throw std::runtime_error(oss.str());
198  }
199 
200  if (!joinedDimension().has_value())
201  {
202  throw error::WrongAPIUsage(
203  "[PatchRecordComponent::store] API call without explicit "
204  "specification of index only allowed when a joined dimension is "
205  "specified.");
206  }
207 
208  Parameter<Operation::WRITE_DATASET> dWrite;
209  dWrite.offset = {};
210  dWrite.extent = {1};
211  dWrite.dtype = dtype;
212  dWrite.data = std::make_shared<T>(data);
213  auto &rc = get();
214  rc.push_chunk(IOTask(this, std::move(dWrite)));
215 }
216 } // namespace openPMD
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
Self-contained description of a single IO operation.
Definition: IOTask.hpp:670
Definition: ParticlePatches.hpp:32
Definition: ParticleSpecies.hpp:34
Definition: PatchRecordComponent.hpp:46
PatchRecordComponent & resetDataset(Dataset) override
Declare the dataset's type and extent.
Definition: PatchRecordComponent.cpp:37
Definition: PatchRecord.hpp:32
Definition: RecordComponent.hpp:120
Definition: BaseRecord.hpp:52
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