chombo-discharge
Loading...
Searching...
No Matches
CD_DischargeIOImplem.H
Go to the documentation of this file.
1/* chombo-discharge
2 * Copyright © 2024 SINTEF Energy Research.
3 * Please refer to Copyright.txt and LICENSE in the chombo-discharge root directory.
4 */
5
12#ifndef CD_DischargeIOImplem_H
13#define CD_DischargeIOImplem_H
14
15// Std includes
16#ifdef CH_USE_HDF5
17#include <hdf5.h>
18#endif
19
20// Chombo includes
21#include <ParticleIO.H>
22
23// Our includes
24#include <CD_DischargeIO.H>
25#include <CD_NamespaceHeader.H>
26
27template <size_t M, size_t N>
28void
33 const RealVect a_shift,
34 const Real a_time) noexcept
35{
36#ifdef CH_USE_HDF5
37 CH_TIME("DischargeIO::writeH5Part");
38
39 CH_assert(a_realVars.size() == 0 || a_realVars.size() == M);
40 CH_assert(a_vectVars.size() == 0 || a_vectVars.size() == N);
41
44
45 if (a_realVars.size() == M) {
47
48 for (int i = 0; i < M; i++) {
49 if (realVariables[i] == "") {
50 realVariables[i] = "real-" + std::to_string(i);
51 }
52 }
53 }
54 else {
55 for (int i = 0; i < M; i++) {
56 realVariables[i] = "real-" + std::to_string(i);
57 }
58 }
59
60 if (a_vectVars.size() == N) {
62
63 for (int i = 0; i < N; i++) {
64 if (vectVariables[i] == "") {
65 vectVariables[i] = "vect-" + std::to_string(i);
66 }
67 }
68 }
69 else {
70 for (int i = 0; i < N; i++) {
71 vectVariables[i] = "vect-" + std::to_string(i);
72 }
73 }
74
75 // Figure out the number of particles on each rank
76 const unsigned long long numParticlesLocal = a_particles.getNumberOfValidParticlesLocal();
77 const unsigned long long numParticlesGlobal = a_particles.getNumberOfValidParticlesGlobal();
78
80#ifdef CH_MPI
81 particlesPerRank.resize(numProc(), 0ULL);
82
85 for (int i = 0; i < numProc(); i++) {
86 displ[i] = i;
87 }
89 1,
92 &recv[0],
93 &displ[0],
96#else
97 particlesPerRank.resize(1);
99#endif
100
101 // Set up file access and create the file.
102 hid_t fileAccess = 0;
103#ifdef CH_MPI
106#endif
107
110
111 // Define the top group necessary for the H5Part file format
113
114 // Write the time attribute
118
119 H5Sclose(scal);
120 H5Aclose(attr);
121
122 // Define dataspace dimensions.
123 hsize_t dims[1];
125
126 hid_t fileSpaceID = H5Screate_simple(1, dims, nullptr);
127
128 // Memory space
129 hsize_t memDims[1];
132
133 // Set hyperslabs for file and memory
136
137 hsize_t memStart[1];
138 hsize_t memCount[1];
139
140 memStart[0] = 0;
141 fileStart[0] = 0;
142 for (int i = 0; i < procID(); i++) {
144 }
147
150
151 // Create the ID and positional data sets
155#if CH_SPACEDIM == 3
157#endif
158
159 // Write ID data set
164
165 for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
166
167 const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
168 const DataIterator& dit = dbl.dataIterator();
169
170 const int nbox = dit.size();
171
172 for (int mybox = 0; mybox < nbox; mybox++) {
173 const DataIndex& din = dit[mybox];
174
176
178 id.push_back(static_cast<long long>(lit().particleID()));
179 x.push_back(lit().position()[0] - a_shift[0]);
180 y.push_back(lit().position()[1] - a_shift[1]);
181#if CH_SPACEDIM == 3
182 z.push_back(lit().position()[2] - a_shift[2]);
183#endif
184 }
185 }
186 }
187
191#if CH_SPACEDIM == 3
193#endif
194
195 id.resize(0);
196 x.resize(0);
197 y.resize(0);
198 z.resize(0);
199
200 // Close the ID and positional data sets
204#if CH_SPACEDIM == 3
206#endif
207
208 // Write the M real-variables
209 for (int curVar = 0; curVar < M; curVar++) {
217
219
220 for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
221
222 const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
223 const DataIterator& dit = dbl.dataIterator();
224
225 const int nbox = dit.size();
226
227 for (int mybox = 0; mybox < nbox; mybox++) {
228 const DataIndex& din = dit[mybox];
229
231
233 ds.push_back(lit().getReals()[curVar]);
234 }
235 }
236 }
237
238 // Write and clsoe dataset
241 }
242
243 // Write the N vector variables
244 for (int curVar = 0; curVar < N; curVar++) {
245 for (int dir = 0; dir < SpaceDim; dir++) {
247 if (dir == 0) {
248 varName = vectVariables[curVar] + "-x";
249 }
250 else if (dir == 1) {
251 varName = vectVariables[curVar] + "-y";
252 }
253 else if (dir == 2) {
254 varName = vectVariables[curVar] + "-z";
255 }
256
258 varName.c_str(),
264
266
267 for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
268
269 const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
270 const DataIterator& dit = dbl.dataIterator();
271
272 const int nbox = dit.size();
273
274 for (int mybox = 0; mybox < nbox; mybox++) {
275 const DataIndex& din = dit[mybox];
276
278
280 const RealVect var = lit().getVects()[curVar];
281
282 ds.push_back(var[dir]);
283 }
284 }
285 }
286
287 // Write and close dataset
290 }
291 }
292
293 // Close top group and file
294 H5Gclose(grp);
296#endif
297}
298
299#ifdef CH_USE_HDF5
300template <class P>
301void
302DischargeIO::writeCheckParticlesToHDF(HDF5Handle& a_handle,
304 const std::string& a_dataType)
305{
306 // timer
307 CH_TIMERS("writeParticlesToHDF");
308
309 // grids
310 const BoxLayout& grids = a_particles.getBoxes();
311
312 // loc part per box
314
315 // loc and tot number of particles
316 unsigned long long numLocalParticles = 0;
317
318 // count number of particles per box
319 for (DataIterator di(grids); di.ok(); ++di) {
320 const size_t numItems = a_particles[di].numItems();
321 numLocalParticles += (unsigned long long)numItems;
322 locParticlesPerBox[grids.index(di())] = (unsigned long long)numItems;
323 }
324
326
327#ifdef CH_MPI
329 &particlesPerBox[0],
330 locParticlesPerBox.size(),
332 MPI_SUM,
334 if (result != MPI_SUCCESS) {
335 MayDay::Error("MPI communcation error in ParticleIO");
336 }
337
338#else
339
340 for (int i = 0; i < grids.size(); i++) {
341 particlesPerBox[i] = (unsigned long long)locParticlesPerBox[i];
342 }
343
344#endif
345
347
348 // size of individual objects
349 size_t objSize = P().H5size();
350
351 // the number of components per particle
352 size_t numComps = objSize / sizeof(Real);
353
354 // compute offsets and tot number of particles; order matters
356 unsigned long long totNumParticles = 0;
357 for (int i = 0; i < grids.size(); i++) {
358 offsets.push_back(numComps * totNumParticles);
360 }
361
362 // now store particle info
363 if (totNumParticles == 0) {
364 return;
365 }
366
367 CH_TIMER("writeParticlesToHDF::checkpoint", t_cp);
368 CH_START(t_cp);
369
370 // data size
372
373 // a single dataspace
375
376 // create data type
378
379 //
380 std::string dataname = a_dataType + ":data";
381
382 // open dataset
383#ifdef H516
385#else
386 hid_t dataset = H5Dcreate2(a_handle.groupID(),
387 dataname.c_str(),
388 H5T_type,
389 dataspace,
393#endif
394
395 if (numLocalParticles > 0) {
396 // allocate data buffer where to linearize the particle data
397 const size_t chunkSize = objSize * _CHUNK;
398 char* chunk = new char[chunkSize];
399
400 if (chunk == NULL) {
401 MayDay::Error("WritePart::Error: new returned NULL pointer ");
402 }
403
404 for (DataIterator di(grids); di.ok(); ++di) {
405 size_t offset = offsets[grids.index(di())];
406
407 // particle counter
408 int ip = 0;
409
410 // linearize particle data
411 const List<P>& pList = a_particles[di].listItems();
412
413 for (ListIterator<P> li(pList); li.ok(); ++li) {
414 pList[li].H5linearOut((void*)chunk);
415 chunk += objSize;
416
417 if (++ip % _CHUNK == 0) {
418 // rewind pointer position, write buffered data
419 chunk -= chunkSize;
421 }
422 }
423
424 // write our residual particles
425 const size_t nResidual = pList.length() % _CHUNK;
426 if (nResidual > 0) {
427 // rewind pointer position and write buffered data
428 chunk -= (nResidual * objSize);
430 }
431 }
432
433 // free buffer
434 delete[] chunk;
435 chunk = NULL;
436 }
437
438 // done
441
442 // stop timer
443 CH_STOP(t_cp);
444}
445#endif
446
447#ifdef CH_USE_HDF5
448template <class P>
449void
450DischargeIO::readCheckParticlesFromHDF(HDF5Handle& a_handle,
452 const std::string& a_dataType)
453{
454 // timer
455 CH_TIMERS("readParticlesFromHDF");
456
457 // number of particles on each box
459
460 // grids
463
464 // load balancing should be handled outside
465 const BoxLayout& bl = a_particles.getBoxes();
466
467 // size of individual objects
468 size_t objSize = P().H5size();
469
470 // the number of components per particle
471 size_t numComps = objSize / sizeof(Real);
472
473 // compute offsets and tot number of particles; order matters
475 unsigned long long totNumParticles = 0;
476 for (int i = 0; i < grids.size(); i++) {
477 offsets.push_back(numComps * totNumParticles);
479 }
480
481 // now read in particle data
482 if (totNumParticles == 0) {
483 return;
484 }
485
486 CH_TIMER("readParticlesFromHDF::checkpoint", t_cp);
487 CH_START(t_cp);
488
489 // P object
490 P p;
491
492 // data type
494
495 //
496 std::string dataname = a_dataType + ":data";
497
498 // one single dataset
499#ifdef H516
500 hid_t dataset = H5Dopen(a_handle.groupID(), dataname.c_str());
501#else
502 hid_t dataset = H5Dopen2(a_handle.groupID(), dataname.c_str(), H5P_DEFAULT);
503#endif
504
506
507 // read in data relative to this proc in small chuncks
508 const size_t chunkSize = objSize * _CHUNK;
509
510 // allocate data buffer to read in linearized particle data chunks
511 char* chunk = new char[chunkSize];
512
513 for (DataIterator di(bl); di.ok(); ++di) {
514 size_t boxData = numComps * particlesPerBox[bl.index(di())];
515 size_t offset = offsets[bl.index(di())];
516
517 List<P>& items = a_particles[di].listItems();
518
519 size_t dataIn = 0;
520 while (dataIn < boxData) {
521 // read data chunk of the right size
522 int size = ((boxData - dataIn) >= (chunkSize / sizeof(Real))) ? chunkSize / sizeof(Real) : boxData - dataIn;
524
525 // list to store the particle data from the HDF5 file
526 for (int ip = 0; ip < size / numComps; ip++) {
527 p.H5linearIn(chunk);
528 chunk += objSize;
529
530 // assign to data holder
531 items.add(p);
532 }
533 dataIn += size;
534 chunk -= size * sizeof(Real);
535 }
536 }
537
538 // free alllocated memory
539 delete[] chunk;
540 chunk = NULL;
541
542 // done with this component
545
546 // stop timer
547 CH_STOP(t_cp);
548}
549#endif
550
551#include <CD_NamespaceFooter.H>
552
553#endif
Silly, but useful functions that override standard Chombo HDF5 IO.
Templated class for holding particles on an AMR hierarchy with particle remapping.
Definition CD_ParticleContainer.H:51
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:37
TracerParticleSolver()
Default constructor.
Definition CD_TracerParticleSolverImplem.H:25
void writeH5Part(const std::string a_filename, const ParticleContainer< GenericParticle< M, N > > &a_particles, const std::vector< std::string > a_realVars=std::vector< std::string >(), const std::vector< std::string > a_vectVars=std::vector< std::string >(), const RealVect a_shift=RealVect::Zero, const Real a_time=0.0) noexcept
A shameless copy of Chombo's writeEBHDF5 but including the lower-left corner of the physical domain a...
Definition CD_DischargeIOImplem.H:29