openPMD-api
 
Loading...
Searching...
No Matches
PatchRecordComponent.hpp
1/* Copyright 2017-2025 Fabian Koller, Axel Huebl, 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/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
39namespace 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
57public:
65 PatchRecordComponent(BaseRecord<PatchRecordComponent> const &);
66
67 PatchRecordComponent &setUnitSI(double);
68
69 uint8_t getDimensionality() const;
70 Extent getExtent() const;
71
72 template <typename T>
73 std::shared_ptr<T> load();
74
75 template <typename T>
76 void load(std::shared_ptr<T>);
77
78 template <typename T>
79 void load(std::shared_ptr<T[]>);
80
81 template <typename T>
82 void loadRaw(T *);
83
84 template <typename T>
85 void store(uint64_t idx, T);
86
87 template <typename T>
88 void store(T);
89
90 // clang-format off
91OPENPMD_private
92 // clang-format on
93
94 using RecordComponent::flush;
95
96 // clang-format off
97OPENPMD_protected
98 // clang-format on
99
102}; // PatchRecordComponent
103
104template <typename T>
105inline std::shared_ptr<T> PatchRecordComponent::load()
106{
107 uint64_t numPoints = getExtent()[0];
108#if (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 11000) || \
109 (defined(__apple_build_version__) && __clang_major__ < 14)
110 auto newData =
111 std::shared_ptr<T>(new T[numPoints], [](T *p) { delete[] p; });
112 load(newData);
113 return newData;
114#else
115 auto newData = std::shared_ptr<T[]>(new T[numPoints]);
116 load(newData);
117 return std::static_pointer_cast<T>(std::move(newData));
118#endif
119}
120
121template <typename T>
122inline void PatchRecordComponent::load(std::shared_ptr<T> data)
123{
124 Datatype dtype = determineDatatype<T>();
125 if (dtype != getDatatype())
126 throw std::runtime_error(
127 "Type conversion during particle patch loading not yet "
128 "implemented");
129
130 if (!data)
131 throw std::runtime_error(
132 "Unallocated pointer passed during ParticlePatch loading.");
133
134 uint64_t numPoints = getExtent()[0];
135
137
139 dRead.offset = {0};
140 dRead.extent = {numPoints};
141 dRead.dtype = getDatatype();
142 dRead.data = std::static_pointer_cast<void>(data);
143 auto &rc = get();
144 rc.push_chunk(IOTask(this, dRead));
145}
146
147template <typename T>
148inline void PatchRecordComponent::load(std::shared_ptr<T[]> data)
149{
150 load(std::static_pointer_cast<T>(std::move(data)));
151}
152
153template <typename T>
154inline void PatchRecordComponent::loadRaw(T *data)
155{
156 load<T>(auxiliary::shareRaw(data));
157}
158
159template <typename T>
160inline void PatchRecordComponent::store(uint64_t idx, T data)
161{
162 Datatype dtype = determineDatatype<T>();
163 if (dtype != getDatatype())
164 {
165 std::ostringstream oss;
166 oss << "Datatypes of patch data (" << dtype << ") and dataset ("
167 << getDatatype() << ") do not match.";
168 throw std::runtime_error(oss.str());
169 }
170
171 Extent dse = getExtent();
172 if (dse[0] - 1u < idx)
173 throw std::runtime_error(
174 "Index does not reside inside patch (no. patches: " +
175 std::to_string(dse[0]) + " - index: " + std::to_string(idx) + ")");
176
177 Parameter<Operation::WRITE_DATASET> dWrite;
178 dWrite.offset = {idx};
179 dWrite.extent = {1};
180 dWrite.dtype = dtype;
181 dWrite.data = std::make_shared<T>(data);
182 auto &rc = get();
183 rc.push_chunk(IOTask(this, std::move(dWrite)));
184}
185
186template <typename T>
187inline void PatchRecordComponent::store(T data)
188{
189 Datatype dtype = determineDatatype<T>();
190 if (dtype != getDatatype())
191 {
192 std::ostringstream oss;
193 oss << "Datatypes of patch data (" << dtype << ") and dataset ("
194 << getDatatype() << ") do not match.";
195 throw std::runtime_error(oss.str());
196 }
197
198 if (!joinedDimension().has_value())
199 {
200 throw error::WrongAPIUsage(
201 "[PatchRecordComponent::store] API call without explicit "
202 "specification of index only allowed when a joined dimension is "
203 "specified.");
204 }
205
206 Parameter<Operation::WRITE_DATASET> dWrite;
207 dWrite.offset = {};
208 dWrite.extent = {1};
209 dWrite.dtype = dtype;
210 dWrite.data = std::make_shared<T>(data);
211 auto &rc = get();
212 rc.push_chunk(IOTask(this, std::move(dWrite)));
213}
214} // namespace openPMD
Self-contained description of a single IO operation.
Definition IOTask.hpp:836
PatchRecordComponent(BaseRecord< PatchRecordComponent > const &)
Avoid object slicing when using a Record as a scalar Record Component.
Definition PatchRecordComponent.cpp:55
RecordComponent(BaseRecord< RecordComponent > const &)
Avoid object slicing when using a Record as a scalar Record Component.
Definition RecordComponent.cpp:190
Definition BaseRecord.hpp:52
Public definitions of openPMD-api.
Definition Date.cpp:29
@ T
time
Definition UnitDimension.hpp:41
Datatype
Concrete datatype of an object available at runtime.
Definition Datatype.hpp:51
Definition Attributable.hpp:251
Typesafe description of all required arguments for a specified Operation.
Definition IOTask.hpp:148