chombo-discharge
Loading...
Searching...
No Matches
CD_DischargeIOImplem.H
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021-2026 SINTEF Energy Research
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
13#ifndef CD_DISCHARGEIOIMPLEM_H
14#define CD_DISCHARGEIOIMPLEM_H
15
16// Std includes
17#ifdef CH_USE_HDF5
18#include <hdf5.h>
19#endif
20
21// Chombo includes
22#include <ParticleIO.H>
23
24// Our includes
25#include <CD_DischargeIO.H>
26#include <CD_NamespaceHeader.H>
27
28template <size_t M, size_t N>
29void
34 const RealVect a_shift,
35 const Real a_time) noexcept
36{
37#ifdef CH_USE_HDF5
38 CH_TIME("DischargeIO::writeH5Part");
39
40 CH_assert(a_realVars.size() == 0 || a_realVars.size() == M);
41 CH_assert(a_vectVars.size() == 0 || a_vectVars.size() == N);
42
45
46 if (a_realVars.size() == M) {
48
49 for (int i = 0; i < M; i++) {
50 if (realVariables[i] == "") {
51 realVariables[i] = "real-" + std::to_string(i);
52 }
53 }
54 }
55 else {
56 for (int i = 0; i < M; i++) {
57 realVariables[i] = "real-" + std::to_string(i);
58 }
59 }
60
61 if (a_vectVars.size() == N) {
63
64 for (int i = 0; i < N; i++) {
65 if (vectVariables[i] == "") {
66 vectVariables[i] = "vect-" + std::to_string(i);
67 }
68 }
69 }
70 else {
71 for (int i = 0; i < N; i++) {
72 vectVariables[i] = "vect-" + std::to_string(i);
73 }
74 }
75
76 // Figure out the number of particles on each rank
77 const unsigned long long numParticlesLocal = a_particles.getNumberOfValidParticlesLocal();
78 const unsigned long long numParticlesGlobal = a_particles.getNumberOfValidParticlesGlobal();
79
81#ifdef CH_MPI
82 particlesPerRank.resize(numProc(), 0ULL);
83
86 for (int i = 0; i < numProc(); i++) {
87 displ[i] = i;
88 }
90 1,
93 &recv[0],
94 &displ[0],
97#else
98 particlesPerRank.resize(1);
100#endif
101
102 // Set up file access and create the file.
103 hid_t fileAccess = 0;
104#ifdef CH_MPI
107#endif
108
110#ifdef CH_MPI
112#endif
113
114 // Define the top group necessary for the H5Part file format
116
117 // Write the time attribute
122
123 H5Sclose(scal);
124
125 // Define dataspace dimensions.
126 hsize_t dims[1];
128
129 hid_t fileSpaceID = H5Screate_simple(1, dims, nullptr);
130
131 // Memory space
132 hsize_t memDims[1];
135
136 // Set hyperslabs for file and memory
139
140 hsize_t memStart[1];
141 hsize_t memCount[1];
142
143 memStart[0] = 0;
144 fileStart[0] = 0;
145 for (int i = 0; i < procID(); i++) {
147 }
150
153
154 // Create the ID and positional data sets
158#if CH_SPACEDIM == 3
160#endif
161
162 // Write ID data set
167
168 for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
169
170 const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
171 const DataIterator& dit = dbl.dataIterator();
172
173 const int nbox = dit.size();
174
175 for (int mybox = 0; mybox < nbox; mybox++) {
176 const DataIndex& din = dit[mybox];
177
179
181 id.push_back(static_cast<long long>(lit().particleID()));
182 x.push_back(lit().position()[0] - a_shift[0]);
183 y.push_back(lit().position()[1] - a_shift[1]);
184#if CH_SPACEDIM == 3
185 z.push_back(lit().position()[2] - a_shift[2]);
186#endif
187 }
188 }
189 }
190
194#if CH_SPACEDIM == 3
196#endif
197
198 id.resize(0);
199 x.resize(0);
200 y.resize(0);
201 z.resize(0);
202
203 // Close the ID and positional data sets
207#if CH_SPACEDIM == 3
209#endif
210
211 // Write the M real-variables
212 for (int curVar = 0; curVar < M; curVar++) {
220
222
223 for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
224
225 const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
226 const DataIterator& dit = dbl.dataIterator();
227
228 const int nbox = dit.size();
229
230 for (int mybox = 0; mybox < nbox; mybox++) {
231 const DataIndex& din = dit[mybox];
232
234
236 ds.push_back(lit().getReals()[curVar]);
237 }
238 }
239 }
240
241 // Write and close dataset
244 }
245
246 // Write the N vector variables
247 for (int curVar = 0; curVar < N; curVar++) {
248 for (int dir = 0; dir < SpaceDim; dir++) {
250 if (dir == 0) {
251 varName = vectVariables[curVar] + "-x";
252 }
253 else if (dir == 1) {
254 varName = vectVariables[curVar] + "-y";
255 }
256 else if (dir == 2) {
257 varName = vectVariables[curVar] + "-z";
258 }
259
261 varName.c_str(),
267
269
270 for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
271
272 const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
273 const DataIterator& dit = dbl.dataIterator();
274
275 const int nbox = dit.size();
276
277 for (int mybox = 0; mybox < nbox; mybox++) {
278 const DataIndex& din = dit[mybox];
279
281
283 const RealVect var = lit().getVects()[curVar];
284
285 ds.push_back(var[dir]);
286 }
287 }
288 }
289
290 // Write and close dataset
293 }
294 }
295
296 // Close top group and file
297 H5Gclose(grp);
299#endif
300}
301
302#ifdef CH_USE_HDF5
303template <class P>
304void
305DischargeIO::writeCheckParticlesToHDF(HDF5Handle& a_handle,
307 const std::string& a_dataType)
308{
309 // timer
310 CH_TIMERS("writeParticlesToHDF");
311
312 // grids
313 const BoxLayout& grids = a_particles.getBoxes();
314
315 // loc part per box
317
318 // loc and tot number of particles
319 unsigned long long numLocalParticles = 0;
320
321 // count number of particles per box
322 for (DataIterator di(grids); di.ok(); ++di) {
323 const size_t numItems = a_particles[di].numItems();
324 numLocalParticles += (unsigned long long)numItems;
325 locParticlesPerBox[grids.index(di())] = (unsigned long long)numItems;
326 }
327
329
330#ifdef CH_MPI
332 &particlesPerBox[0],
333 locParticlesPerBox.size(),
335 MPI_SUM,
337 if (result != MPI_SUCCESS) {
338 MayDay::Error("MPI communication error in ParticleIO");
339 }
340
341#else
342
343 for (int i = 0; i < grids.size(); i++) {
344 particlesPerBox[i] = (unsigned long long)locParticlesPerBox[i];
345 }
346
347#endif
348
350
351 // size of individual objects
352 size_t objSize = P().H5size();
353
354 // the number of components per particle
355 size_t numComps = objSize / sizeof(Real);
356
357 // compute offsets and tot number of particles; order matters
359 unsigned long long totNumParticles = 0;
360 for (int i = 0; i < grids.size(); i++) {
361 offsets.push_back(numComps * totNumParticles);
363 }
364
365 // now store particle info
366 if (totNumParticles == 0) {
367 return;
368 }
369
370 CH_TIMER("writeParticlesToHDF::checkpoint", t_cp);
371 CH_START(t_cp);
372
373 // data size
375
376 // a single dataspace
378
379 // create data type
381
382 //
383 std::string dataname = a_dataType + ":data";
384
385 // open dataset
386#ifdef H516
388#else
389 hid_t dataset = H5Dcreate2(a_handle.groupID(),
390 dataname.c_str(),
391 H5T_type,
392 dataspace,
396#endif
397
398 if (numLocalParticles > 0) {
399 // allocate data buffer where to linearize the particle data
400 const size_t chunkSize = objSize * _CHUNK;
401 char* const chunkBase = new char[chunkSize];
402 char* chunk = chunkBase;
403
404 if (chunkBase == nullptr) {
405 MayDay::Error("WritePart::Error: new returned NULL pointer ");
406 }
407
408 for (DataIterator di(grids); di.ok(); ++di) {
409 size_t offset = offsets[grids.index(di())];
410
411 // particle counter
412 int ip = 0;
413
414 // linearize particle data
415 const List<P>& pList = a_particles[di].listItems();
416
417 for (ListIterator<P> li(pList); li.ok(); ++li) {
418 pList[li].H5linearOut((void*)chunk);
419 chunk += objSize;
420
421 if (++ip % _CHUNK == 0) {
422 // rewind pointer position, write buffered data
423 chunk -= chunkSize;
425 }
426 }
427
428 // write our residual particles
429 const size_t nResidual = pList.length() % _CHUNK;
430 if (nResidual > 0) {
431 // rewind pointer position and write buffered data
432 chunk -= (nResidual * objSize);
434 }
435
437 }
438
439 // free buffer
440 delete[] chunkBase;
441 }
442
443 // done
446
447 // stop timer
448 CH_STOP(t_cp);
449}
450#endif
451
452#ifdef CH_USE_HDF5
453template <class P>
454void
455DischargeIO::readCheckParticlesFromHDF(HDF5Handle& a_handle,
457 const std::string& a_dataType)
458{
459 // timer
460 CH_TIMERS("readParticlesFromHDF");
461
462 // number of particles on each box
464
465 // grids
468
469 // load balancing should be handled outside
470 const BoxLayout& bl = a_particles.getBoxes();
471
472 // size of individual objects
473 size_t objSize = P().H5size();
474
475 // the number of components per particle
476 size_t numComps = objSize / sizeof(Real);
477
478 // compute offsets and tot number of particles; order matters
480 unsigned long long totNumParticles = 0;
481 for (int i = 0; i < grids.size(); i++) {
482 offsets.push_back(numComps * totNumParticles);
484 }
485
486 // now read in particle data
487 if (totNumParticles == 0) {
488 return;
489 }
490
491 CH_TIMER("readParticlesFromHDF::checkpoint", t_cp);
492 CH_START(t_cp);
493
494 // P object
495 P p;
496
497 // data type
499
500 //
501 std::string dataname = a_dataType + ":data";
502
503 // one single dataset
504#ifdef H516
505 hid_t dataset = H5Dopen(a_handle.groupID(), dataname.c_str());
506#else
507 hid_t dataset = H5Dopen2(a_handle.groupID(), dataname.c_str(), H5P_DEFAULT);
508#endif
509
511
512 // read in data relative to this proc in small chunks
513 const size_t chunkSize = objSize * _CHUNK;
514
515 // allocate data buffer to read in linearized particle data chunks
516 char* chunk = new char[chunkSize];
517
518 for (DataIterator di(bl); di.ok(); ++di) {
519 size_t boxData = numComps * particlesPerBox[bl.index(di())];
520 size_t offset = offsets[bl.index(di())];
521
522 List<P>& items = a_particles[di].listItems();
523
524 size_t dataIn = 0;
525 while (dataIn < boxData) {
526 // read data chunk of the right size
527 int size = ((boxData - dataIn) >= (chunkSize / sizeof(Real))) ? chunkSize / sizeof(Real) : boxData - dataIn;
529
530 // list to store the particle data from the HDF5 file
531 for (int ip = 0; ip < size / numComps; ip++) {
532 p.H5linearIn(chunk);
533 chunk += objSize;
534
535 // assign to data holder
536 items.add(p);
537 }
538 dataIn += size;
539 chunk -= size * sizeof(Real);
540 }
541 }
542
543 // free allocated memory
544 delete[] chunk;
545 chunk = NULL;
546
547 // done with this component
550
551 // stop timer
552 CH_STOP(t_cp);
553}
554#endif
555
556#include <CD_NamespaceFooter.H>
557
558#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:52
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:38
TracerParticleSolver()
Default constructor.
Definition CD_TracerParticleSolverImplem.H:26
void writeH5Part(std::string a_filename, const ParticleContainer< GenericParticle< M, N > > &a_particles, std::vector< std::string > a_realVars, std::vector< std::string > a_vectVars, RealVect a_shift, Real a_time) noexcept
Write a particle container to an H5Part file. Good for quick and dirty visualization of particles.
Definition CD_DischargeIOImplem.H:30