3 #include <openPMD/openPMD.hpp> 6 #define DEBUG_START(_METHOD_) \ 7 std::cout << "[DEBUG][openPMD_io][" << _METHOD_ << "][START] " << std::endl; 8 #define DEBUG_END(_METHOD_) \ 9 std::cout << "[DEBUG][openPMD_io][" << _METHOD_ << "][END] " << std::endl; 10 #define DEBUG_INFO(_METHOD_, _MSG_) \ 11 std::cout << "[DEBUG][openPMD_io][" << _METHOD_ << "][INFO] " << _MSG_ << std::endl; 13 #define DEBUG_START(_METHOD) 14 #define DEBUG_END(_METHOD_) 15 #define DEBUG_INFO(_METHOD_, _MSG_) 28 constexpr
size_t CHUNK_SIZE = 3;
37 std::string mc_code_version, std::string instrument_name,
38 std::string name_current_component):
41 _mc_code_name(mc_code_name),
42 _mc_code_version(mc_code_version),
43 _instrument_name(instrument_name),
44 _name_current_component(name_current_component),
52 raytracing::openPMD_io::init_ray_prop(std::string name, openPMD::Dataset& dataset,
bool isScalar,
53 std::map<openPMD::UnitDimension, double>
const& dims,
55 auto rays = rays_pmd();
57 rays[name].setUnitDimension(dims);
60 rays[name][openPMD::RecordComponent::SCALAR].resetDataset(dataset);
61 rays[name][openPMD::RecordComponent::SCALAR].setUnitSI(unitSI);
64 for (
auto dim : {
"x",
"y",
"z"}) {
65 rays[name][dim].resetDataset(dataset);
66 rays[name][dim].setUnitSI(unitSI);
82 _max_allowed_rays = n_rays;
85 DEBUG_START(
"INIT_RAYS")
87 auto rays = rays_pmd(particle_species);
90 openPMD::Dataset dataset_single_float =
91 openPMD::Dataset(openPMD::Datatype::FLOAT, openPMD::Extent{1});
92 init_ray_prop(
"directionOfGravity", dataset_single_float,
false);
93 init_ray_prop(
"horizontalCoordinate", dataset_single_float,
false);
94 init_ray_prop(
"mass", dataset_single_float,
true, {{openPMD::UnitDimension::M, 1.}});
96 rays.setAttribute(
"speciesType", particle_species);
97 rays.setAttribute(
"PDGID", particle_species);
98 rays.setAttribute(
"numParticles", 0);
100 openPMD::Dataset dataset_float =
101 openPMD::Dataset(openPMD::Datatype::FLOAT, openPMD::Extent{n_rays});
102 openPMD::Dataset dataset_int =
103 openPMD::Dataset(openPMD::Datatype::INT, openPMD::Extent{n_rays});
104 openPMD::Dataset dataset_ulongint =
105 openPMD::Dataset(openPMD::Datatype::ULONGLONG, openPMD::Extent{n_rays});
107 init_ray_prop(
"position", dataset_float,
false, {{openPMD::UnitDimension::L, 1.}}, 1e-2);
108 init_ray_prop(
"direction", dataset_float,
false);
110 init_ray_prop(
"nonPhotonPolarization", dataset_float,
false);
111 init_ray_prop(
"photonSPolarizationAmplitude", dataset_float,
false);
112 init_ray_prop(
"photonSPolarizationPhase", dataset_float,
true);
113 init_ray_prop(
"photonPPolarizationAmplitude", dataset_float,
false);
114 init_ray_prop(
"photonPPolarizationPhase", dataset_float,
true);
116 init_ray_prop(
"wavelength", dataset_float,
true, {{openPMD::UnitDimension::L, 1}},
118 init_ray_prop(
"weight", dataset_float,
true);
119 init_ray_prop(
"rayTime", dataset_float,
true, {{openPMD::UnitDimension::T, 1.}}, 1e-3);
121 init_ray_prop(
"id", dataset_ulongint,
true);
122 init_ray_prop(
"particleStatus", dataset_int,
true);
124 DEBUG_END(
"INIT_RAYS")
131 std::string filename = _name;
133 _series = std::unique_ptr<openPMD::Series>(
134 new openPMD::Series(filename, openPMD::Access::CREATE));
136 _series->setAuthor(
"openPMD raytracing API");
143 DEBUG_INFO(
"init_write",
"Filename: " << filename)
145 auto i = iter_pmd(iter);
155 DEBUG_INFO(
"init_write",
"Iter: " << _iter)
159 init_rays(particle_species, n_rays, iter);
166 DEBUG_INFO(
"init_write",
"flush done")
170 template <
typename T>
172 save_write_single(openPMD::ParticleSpecies& rays, std::string field, std::string record,
174 openPMD::Extent& extent) {
175 rays[field][record].storeChunk(openPMD::shareRaw(rec.vals()), offset, extent);
176 rays[field][record].setAttribute(
"minValue", rec.min());
177 rays[field][record].setAttribute(
"maxValue", rec.max());
183 if (_rays.size() == 0)
return;
185 DEBUG_INFO(
"save_write",
186 "Number of saved rays: " << _rays.size() <<
"\t" << _rays._x.vals().size())
188 auto rays = rays_pmd();
191 if (_nrays + _rays.size() > _max_allowed_rays)
192 throw std::runtime_error(
"Maximum number of foreseen rays reached, stopping");
196 assert(_nrays == _offset[0]);
198 _nrays += _rays.size();
200 openPMD::Extent extent = {_rays.size()};
202 save_write_single(rays,
"position",
"x", _rays._x, _offset, extent);
203 save_write_single(rays,
"position",
"y", _rays._y, _offset, extent);
204 save_write_single(rays,
"position",
"z", _rays._z, _offset, extent);
206 save_write_single(rays,
"direction",
"x", _rays._dx, _offset, extent);
207 save_write_single(rays,
"direction",
"y", _rays._dy, _offset, extent);
208 save_write_single(rays,
"direction",
"z", _rays._dz, _offset, extent);
210 save_write_single(rays,
"nonPhotonPolarization",
"x", _rays._sx, _offset, extent);
211 save_write_single(rays,
"nonPhotonPolarization",
"y", _rays._sy, _offset, extent);
212 save_write_single(rays,
"nonPhotonPolarization",
"z", _rays._sz, _offset, extent);
214 save_write_single(rays,
"photonSPolarizationAmplitude",
"x", _rays._sPolAx, _offset,
216 save_write_single(rays,
"photonSPolarizationAmplitude",
"y", _rays._sPolAy, _offset,
218 save_write_single(rays,
"photonSPolarizationAmplitude",
"z", _rays._sPolAz, _offset,
220 save_write_single(rays,
"photonSPolarizationPhase", openPMD::RecordComponent::SCALAR,
221 _rays._sPolPh, _offset, extent);
223 save_write_single(rays,
"photonPPolarizationAmplitude",
"x", _rays._pPolAx, _offset,
225 save_write_single(rays,
"photonPPolarizationAmplitude",
"y", _rays._pPolAy, _offset,
227 save_write_single(rays,
"photonPPolarizationAmplitude",
"z", _rays._pPolAz, _offset,
229 save_write_single(rays,
"photonPPolarizationPhase", openPMD::RecordComponent::SCALAR,
230 _rays._pPolPh, _offset, extent);
232 save_write_single(rays,
"rayTime", openPMD::RecordComponent::SCALAR, _rays._time, _offset,
234 save_write_single(rays,
"wavelength", openPMD::RecordComponent::SCALAR, _rays._wavelength,
236 save_write_single(rays,
"weight", openPMD::RecordComponent::SCALAR, _rays._weight, _offset,
239 save_write_single(rays,
"id", openPMD::RecordComponent::SCALAR, _rays._id, _offset, extent);
240 save_write_single(rays,
"particleStatus", openPMD::RecordComponent::SCALAR, _rays._status,
243 rays.setAttribute(
"numParticles", _nrays);
248 for (
size_t i = 0; i < extent.size(); ++i)
249 _offset[i] += extent[i];
254 template <
typename T>
256 read_single(openPMD::ParticleSpecies& rays, std::string field, std::string record,
258 openPMD::Extent& chunk_size) {
260 auto data = rays[field][record];
261 rec.vals().reserve(chunk_size[0]);
262 rec.vals().resize(chunk_size[0]);
263 data.loadChunk<T>(openPMD::shareRaw(rec.vals()), offset,
278 raytracing::openPMD_io::load_chunk(
void) {
281 auto rays = rays_pmd();
282 DEBUG_START(
"load_chunk")
284 unsigned
long long int remaining = _nrays - _offset[0];
285 openPMD::Extent chunk_size = {remaining > raytracing::CHUNK_SIZE ? raytracing::CHUNK_SIZE
287 DEBUG_INFO(
"load_chunk",
288 _nrays <<
"\t" << _offset[0] <<
"\t" << remaining <<
"\t" << chunk_size[0])
289 DEBUG_INFO(
"load_chunk",
290 " Loading chunk of size " << chunk_size[0] <<
"; file contains " << _nrays)
296 read_single(rays,
"position",
"x", _rays._x, _offset, chunk_size);
297 read_single(rays,
"position",
"y", _rays._y, _offset, chunk_size);
298 read_single(rays,
"position",
"z", _rays._z, _offset, chunk_size);
300 read_single(rays,
"direction",
"x", _rays._dx, _offset, chunk_size);
301 read_single(rays,
"direction",
"y", _rays._dy, _offset, chunk_size);
302 read_single(rays,
"direction",
"z", _rays._dz, _offset, chunk_size);
304 read_single(rays,
"nonPhotonPolarization",
"x", _rays._sx, _offset, chunk_size);
305 read_single(rays,
"nonPhotonPolarization",
"y", _rays._sy, _offset, chunk_size);
306 read_single(rays,
"nonPhotonPolarization",
"z", _rays._sz, _offset, chunk_size);
308 read_single(rays,
"photonSPolarizationAmplitude",
"x", _rays._sPolAx, _offset, chunk_size);
309 read_single(rays,
"photonSPolarizationAmplitude",
"y", _rays._sPolAy, _offset, chunk_size);
310 read_single(rays,
"photonSPolarizationAmplitude",
"z", _rays._sPolAz, _offset, chunk_size);
311 read_single(rays,
"photonSPolarizationPhase", openPMD::RecordComponent::SCALAR,
312 _rays._sPolPh, _offset, chunk_size);
314 read_single(rays,
"photonPPolarizationAmplitude",
"x", _rays._pPolAx, _offset, chunk_size);
315 read_single(rays,
"photonPPolarizationAmplitude",
"y", _rays._pPolAy, _offset, chunk_size);
316 read_single(rays,
"photonPPolarizationAmplitude",
"z", _rays._pPolAz, _offset, chunk_size);
317 read_single(rays,
"photonPPolarizationPhase", openPMD::RecordComponent::SCALAR,
318 _rays._pPolPh, _offset, chunk_size);
320 read_single(rays,
"rayTime", openPMD::RecordComponent::SCALAR, _rays._time, _offset,
322 read_single(rays,
"wavelength", openPMD::RecordComponent::SCALAR, _rays._wavelength,
323 _offset, chunk_size);
324 read_single(rays,
"weight", openPMD::RecordComponent::SCALAR, _rays._weight, _offset,
327 read_single(rays,
"id", openPMD::RecordComponent::SCALAR, _rays._id, _offset, chunk_size);
328 read_single(rays,
"particleStatus", openPMD::RecordComponent::SCALAR, _rays._status,
329 _offset, chunk_size);
331 _rays.size(chunk_size[0]);
332 DEBUG_INFO(
"load_chunk",
"Before flush")
334 DEBUG_INFO("load_chunk", "After flush")
337 for (
size_t i = 0; i < chunk_size.size(); ++i)
338 _offset[i] += chunk_size[i];
339 DEBUG_END("load_chunk")
342 unsigned long long int 344 unsigned long long int n_rays,
unsigned int repeat) {
350 std::string filename = _name;
353 _series = std::unique_ptr<openPMD::Series>(
new openPMD::Series(
355 openPMD::Access::READ_ONLY));
358 std::cout <<
"File information: " << filename << std::endl;
359 if (_series->containsAttribute(
"author"))
360 std::cout <<
" Author : " << _series->author() << std::endl;
361 std::cout <<
" Filename: " << filename << std::endl;
362 std::cout <<
" Number of iterations: " << _series->iterations.size() << std::endl;
364 if (_series->iterations.size() == 0)
365 std::cout <<
" ERROR, no iterations found in openPMD series" << std::endl;
372 auto i = iter_pmd(_iter);
374 auto rays = rays_pmd(particle_species);
375 _nrays = rays.getAttribute(
"numParticles").get<
unsigned long long int>();
376 std::cout <<
"numParticles: " << _nrays << std::endl;
377 if (n_rays > _nrays) {
378 std::cerr <<
"[ERROR] Requested a number of rays that is not available in " 382 throw std::runtime_error(
"ERROR");
385 std::cout <<
"[WARNING] Requested " << n_rays
386 <<
", while available in file: " << _nrays << std::endl;
395 if (_rays.size() == CHUNK_SIZE) {
397 DEBUG_INFO(
"trace_write",
398 "Reached CHUNK_SIZE:\toff=" << _offset[0] <<
"\tsize=" << _rays.size()
399 <<
"\tmax=" << _max_allowed_rays)
404 _rays.push(this_ray);
410 DEBUG_INFO(
"trace_read",
"---- i_repeat=" << _i_repeat <<
"\tn_repeat=" << _n_repeat
411 <<
"\tis_chunk_finished=" << std::boolalpha
412 << _rays.is_chunk_finished())
413 if (_i_repeat++ == 0) {
414 if (_rays.is_chunk_finished()) { load_chunk(); }
415 _last_ray = _rays.pop();
417 if (_i_repeat >= _n_repeat) _i_repeat = 0;
419 DEBUG_INFO(
"trace_read",
"Ray: " << _last_ray)
424 raytracing::openPMD_io::set_gravity_direction(
float x,
float y,
float z) {
425 auto rays = rays_pmd();
426 openPMD::Offset offset = {0};
427 openPMD::Extent extent = {1};
428 rays[
"directionOfGravity"][
"x"].storeChunk(openPMD::shareRaw(&x), offset, extent);
429 rays[
"directionOfGravity"][
"y"].storeChunk(openPMD::shareRaw(&y), offset, extent);
430 rays[
"directionOfGravity"][
"z"].storeChunk(openPMD::shareRaw(&z), offset, extent);
435 raytracing::openPMD_io::get_gravity_direction(
float* x,
float* y,
float* z) {
436 auto rays = rays_pmd();
437 auto xx = rays[
"directionOfGravity"][
"x"].loadChunk<
float>();
438 auto yy = rays[
"directionOfGravity"][
"y"].loadChunk<
float>();
439 auto zz = rays[
"directionOfGravity"][
"z"].loadChunk<
float>();
448 raytracing::openPMD_io::get_horizontal_direction(
float* x,
float* y,
float* z) {
449 auto rays = rays_pmd();
450 auto xx = rays[
"horizontalCoordinate"][
"x"].loadChunk<
float>();
451 auto yy = rays[
"horizontalCoordinate"][
"y"].loadChunk<
float>();
452 auto zz = rays[
"horizontalCoordinate"][
"z"].loadChunk<
float>();
I/O API for the ray trace extension of the openPMD format.
void init_write(std::string particle_species, unsigned long long int n_rays, unsigned int iter=1)
initializes the "series" object from the openPMD API in WRITE MODE
template utility class to simplify implementation It is a vector that also stores min and max values ...
Generic ray, containing all the ray information being stored by the API into the openPMD file...
defines the maximum number of rays that can be stored in memory before dumping to file ...
void trace_write(Ray this_ray)
save ray properties for further writing to file by save_write()
void init_rays(std::string particle_species, unsigned long long int n_rays, unsigned int iter)
declare the ray particle species in the file
Ray trace_read(void)
Read rays from file and returns the next in the list.
void save_write(void)
Flushes the output to file before closing it.
openPMD_io(const std::string &filename, const std::string mc_code_name="", const std::string mc_code_version="", const std::string instrument_name="", const std::string name_current_component="")
constructor