Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_WriteBinaryParticleDataHDF5.H
Go to the documentation of this file.
1#ifndef AMREX_WRITE_BINARY_PARTICLE_DATA_HDF5_H
2#define AMREX_WRITE_BINARY_PARTICLE_DATA_HDF5_H
3
4#include <iterator>
5
13namespace amrex {
14
25static int CreateWriteHDF5Attr(hid_t loc, const char *name, hsize_t n, void *data, hid_t dtype)
26{
27 herr_t ret;
28 hid_t attr, attr_space;
29 hsize_t dims = n;
30
31 attr_space = H5Screate_simple(1, &dims, NULL);
32
33 attr = H5Acreate(loc, name, dtype, attr_space, H5P_DEFAULT, H5P_DEFAULT);
34 if (attr < 0) {
35 amrex::Print() << " Error with H5Acreate [" << name << "]\n";
36 H5Sclose(attr_space);
37 return -1;
38 }
39
40 ret = H5Awrite(attr, dtype, (void*)data);
41 if (ret < 0) {
42 amrex::Print() << " Error with H5Awrite [" << name << "]\n";
43 H5Sclose(attr_space);
44 H5Aclose(attr);
45 return -1;
46 }
47 H5Sclose(attr_space);
48 H5Aclose(attr);
49 return 1;
50}
51
60static int CreateWriteHDF5AttrString(hid_t loc, const char *name, const char* str)
61{
62 hid_t attr, atype, space;
63 herr_t ret;
64
65 AMREX_ASSERT(name);
66 AMREX_ASSERT(str);
67
68 space = H5Screate(H5S_SCALAR);
69 atype = H5Tcopy(H5T_C_S1);
70 H5Tset_size(atype, strlen(str)+1);
71 H5Tset_strpad(atype,H5T_STR_NULLTERM);
72 attr = H5Acreate(loc, name, atype, space, H5P_DEFAULT, H5P_DEFAULT);
73 if (attr < 0) {
74 amrex::Print() << " Error with H5Acreate [" << name << "]\n";
75 return -1;
76 }
77
78 ret = H5Awrite(attr, atype, str);
79 if (ret < 0) {
80 amrex::Print() << " Error with H5Awrite [" << name << "]\n";
81 return -1;
82 }
83
84 H5Tclose(atype);
85 H5Sclose(space);
86 H5Aclose(attr);
87
88 return 1;
89}
90
100static int ReadHDF5Attr(hid_t loc, const char *name, void *data, hid_t dtype)
101{
102 herr_t ret;
103 hid_t attr;
104
105 attr = H5Aopen(loc, name, H5P_DEFAULT);
106 if (attr < 0) {
107 amrex::Print() << " Error with H5Aopen [" << name << "]\n";
108 return -1;
109 }
110
111 ret = H5Aread(attr, dtype, data);
112 if (ret < 0) {
113 amrex::Print() << " Error with H5Aread [" << name << "]\n";
114 return -1;
115 }
116 H5Aclose(attr);
117 return 1;
118}
119
120#ifdef AMREX_USE_MPI
127static void SetHDF5fapl(hid_t fapl, MPI_Comm comm)
128#else
134static void SetHDF5fapl(hid_t fapl)
135#endif
136{
137#ifdef AMREX_USE_MPI
138 H5Pset_fapl_mpio(fapl, comm, MPI_INFO_NULL);
139
140 // Alignment and metadata block size
141 int alignment = 16 * 1024 * 1024;
142 int blocksize = 4 * 1024 * 1024;
143 H5Pset_alignment(fapl, alignment, alignment);
144 H5Pset_meta_block_size(fapl, blocksize);
145
146 // Collective metadata ops
147 H5Pset_coll_metadata_write(fapl, true);
148 H5Pset_all_coll_metadata_ops(fapl, true);
149
150 // Defer cache flush
151 H5AC_cache_config_t cache_config;
152 cache_config.version = H5AC__CURR_CACHE_CONFIG_VERSION;
153 H5Pget_mdc_config(fapl, &cache_config);
154 cache_config.set_initial_size = 1;
155 cache_config.initial_size = 16 * 1024 * 1024;
156 cache_config.evictions_enabled = 0;
157 cache_config.incr_mode = H5C_incr__off;
158 cache_config.flash_incr_mode = H5C_flash_incr__off;
159 cache_config.decr_mode = H5C_decr__off;
160 H5Pset_mdc_config (fapl, &cache_config);
161#else
162 H5Pset_fapl_sec2(fapl);
163#endif
164
165}
183template <class PC, class F>
184requires (IsParticleContainer<PC>::value)
185void WriteHDF5ParticleDataSync (PC const& pc,
186 const std::string& dir, const std::string& name,
187 const Vector<int>& write_real_comp,
188 const Vector<int>& write_int_comp,
189 const Vector<std::string>& real_comp_names,
190 const Vector<std::string>& int_comp_names,
191 const std::string& compression,
192 F&& f, bool is_checkpoint)
193{
194 BL_PROFILE("WriteHDF5ParticleDataSync()");
195 AMREX_ASSERT(pc.OK());
196
197 AMREX_ASSERT(sizeof(typename PC::ParticleType::RealType) == 4 ||
198 sizeof(typename PC::ParticleType::RealType) == 8);
199
200 constexpr int NStructReal = PC::NStructReal;
201 constexpr int NStructInt = PC::NStructInt;
202
203 const int NProcs = ParallelDescriptor::NProcs();
204 const int IOProcNumber = ParallelDescriptor::IOProcessorNumber();
205
206 {
207 int nrc = PC::ParticleType::is_soa_particle ?
208 pc.NumRealComps() + NStructReal - AMREX_SPACEDIM : pc.NumRealComps() + NStructReal;
209 AMREX_ALWAYS_ASSERT(std::ssize(real_comp_names) == nrc);
210 }
211 AMREX_ALWAYS_ASSERT( int_comp_names.size() == pc.NumIntComps() + NStructInt);
212
213#ifdef AMREX_USE_HDF5_ASYNC
214 // For HDF5 async VOL, block and wait previous tasks have all completed
215 if (es_par_g != 0)
216 async_vol_es_wait_particle();
217 else {
218 ExecOnFinalize(async_vol_es_wait_close_particle);
219 es_par_g = H5EScreate();
220 }
221#endif
222
223 std::string pdir = dir;
224 if ( ! pdir.empty() && pdir[pdir.size()-1] != '/') { pdir += '/'; }
225 pdir += name;
226
227 if ( ! pc.GetLevelDirectoriesCreated()) {
229 {
230 if ( ! amrex::UtilCreateDirectory(pdir, 0755))
231 {
233 }
234 }
236 }
237
238 /* std::ofstream HdrFile; */
239 hid_t fid, grp, fapl, comp_dtype;
240 int status;
241
242 Long nparticles = 0;
243 Long maxnextid;
244
245 comp_dtype = H5Tcreate (H5T_COMPOUND, 2 * AMREX_SPACEDIM * sizeof(int));
246 if (1 == AMREX_SPACEDIM) {
247 H5Tinsert (comp_dtype, "lo_i", 0 * sizeof(int), H5T_NATIVE_INT);
248 H5Tinsert (comp_dtype, "hi_i", 1 * sizeof(int), H5T_NATIVE_INT);
249 }
250 else if (2 == AMREX_SPACEDIM) {
251 H5Tinsert (comp_dtype, "lo_i", 0 * sizeof(int), H5T_NATIVE_INT);
252 H5Tinsert (comp_dtype, "lo_j", 1 * sizeof(int), H5T_NATIVE_INT);
253 H5Tinsert (comp_dtype, "hi_i", 2 * sizeof(int), H5T_NATIVE_INT);
254 H5Tinsert (comp_dtype, "hi_j", 3 * sizeof(int), H5T_NATIVE_INT);
255 }
256 else if (3 == AMREX_SPACEDIM) {
257 H5Tinsert (comp_dtype, "lo_i", 0 * sizeof(int), H5T_NATIVE_INT);
258 H5Tinsert (comp_dtype, "lo_j", 1 * sizeof(int), H5T_NATIVE_INT);
259 H5Tinsert (comp_dtype, "lo_k", 2 * sizeof(int), H5T_NATIVE_INT);
260 H5Tinsert (comp_dtype, "hi_i", 3 * sizeof(int), H5T_NATIVE_INT);
261 H5Tinsert (comp_dtype, "hi_j", 4 * sizeof(int), H5T_NATIVE_INT);
262 H5Tinsert (comp_dtype, "hi_k", 5 * sizeof(int), H5T_NATIVE_INT);
263 }
264
265 // evaluate f for every particle to determine which ones to output
266 Vector<std::map<std::pair<int, int>, typename PC::IntVector > >
267 particle_io_flags(pc.GetParticles().size());
268 for (int lev = 0; lev < std::ssize(pc.GetParticles()); lev++)
269 {
270 const auto& pmap = pc.GetParticles(lev);
271 for (const auto& kv : pmap)
272 {
273 auto& flags = particle_io_flags[lev][kv.first];
274 particle_detail::fillFlags(flags, kv.second, f);
275 }
276 }
277
279
280 if(pc.GetUsePrePost())
281 {
282 nparticles = pc.GetNParticlesPrePost();
283 maxnextid = pc.GetMaxNextIDPrePost();
284 }
285 else
286 {
287 nparticles = particle_detail::countFlags(particle_io_flags, pc);
288 maxnextid = PC::ParticleType::NextID();
289 ParallelDescriptor::ReduceLongSum(nparticles, IOProcNumber);
290 PC::ParticleType::NextID(maxnextid);
291 ParallelDescriptor::ReduceLongMax(maxnextid, IOProcNumber);
292 }
293
294 std::string HDF5FileName = pdir;
295 if ( ! HDF5FileName.empty() && HDF5FileName[HDF5FileName.size()-1] != '/')
296 HDF5FileName += '/';
297
298 HDF5FileName += name;
299 HDF5FileName += ".h5";
300 pc.HdrFileNamePrePost = HDF5FileName;
301
302 BL_PROFILE_VAR("H5FileCreate", h5fg);
303
305 {
306 int set_stripe = 0;
307 char setstripe[1024];
308 int stripe_count = 128;
309 int stripe_size = 1;
310 char *stripe_count_str = getenv("HDF5_STRIPE_COUNT");
311 char *stripe_size_str = getenv("HDF5_STRIPE_SIZE");
312 if (stripe_count_str) {
313 stripe_count = atoi(stripe_count_str);
314 set_stripe = 1;
315 }
316 if (stripe_size_str) {
317 stripe_size = atoi(stripe_size_str);
318 set_stripe = 1;
319 }
320 if (set_stripe == 1) {
321 snprintf(setstripe, sizeof setstripe, "lfs setstripe -c %d -S %dm %s", stripe_count, stripe_size, pdir.c_str());
322 std::cout << "Setting stripe parameters for HDF5 output: " << setstripe << std::endl;
323 amrex::ignore_unused(std::system(setstripe));
324 }
325
326 fid = H5Fcreate(HDF5FileName.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
327 if (fid < 0) { amrex::FileOpenFailed(HDF5FileName.c_str()); }
328
329 //
330 // First thing written is our Checkpoint/Restart version string.
331 // We append "_single" or "_double" to the version string indicating
332 // whether we're using "float" or "double" floating point data in the
333 // particles so that we can Restart from the checkpoint files.
334 //
335 std::string versionName = is_checkpoint ? PC::CheckpointVersion() : PC::PlotfileVersion();
336 if (sizeof(typename PC::ParticleType::RealType) == 4) {
337 versionName += "_single";
338 } else {
339 versionName += "_double";
340 }
341
342 CreateWriteHDF5AttrString(fid, "version_name", versionName.c_str());
343
344 int num_output_real = 0;
345 for (int i = 0; i < std::ssize(write_real_comp); ++i) {
346 if (write_real_comp[i]) { ++num_output_real; }
347 }
348
349 int num_output_int = 0;
350 for (int i = 0; i < pc.NumIntComps() + NStructInt; ++i) {
351 if (write_int_comp[i]) { ++num_output_int; }
352 }
353
354 // AMREX_SPACEDIM and N for sanity checking.
355 int ndim = AMREX_SPACEDIM;
356 grp = H5Gcreate(fid, "Chombo_global", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
357 CreateWriteHDF5Attr(grp, "SpaceDim", 1, &ndim, H5T_NATIVE_INT);
358 H5Gclose(grp);
359
360 // The number of extra real parameters
361 int ncomp = num_output_real + num_output_int;
362 CreateWriteHDF5Attr(fid, "num_component", 1, &ncomp, H5T_NATIVE_INT);
363 CreateWriteHDF5Attr(fid, "num_component_real", 1, &num_output_real, H5T_NATIVE_INT);
364
365 char comp_name[128];
366
367 // Real component names
368 int real_comp_count = AMREX_SPACEDIM; // position values
369
370 for (int i = 0; i < std::ssize(write_real_comp); ++i ) {
371 if (write_real_comp[i]) {
372 /* HdrFile << real_comp_names[i] << '\n'; */
373 snprintf(comp_name, sizeof comp_name, "real_component_%d", real_comp_count);
374 CreateWriteHDF5AttrString(fid, comp_name, real_comp_names[i].c_str());
375 ++real_comp_count;
376 }
377 }
378
379 // The number of extra int parameters
380 CreateWriteHDF5Attr(fid, "num_component_int", 1, &num_output_int, H5T_NATIVE_INT);
381
382 // int component names
383 int int_comp_count = 2;
384
385 for (int i = 0; i < NStructInt + pc.NumIntComps(); ++i ) {
386 if (write_int_comp[i]) {
387 snprintf(comp_name, sizeof comp_name, "int_component_%d", int_comp_count);
388 CreateWriteHDF5AttrString(fid, comp_name, int_comp_names[i].c_str());
389 ++int_comp_count;
390 }
391 }
392
393 // The total number of particles.
394 CreateWriteHDF5Attr(fid, "nparticles", 1, &nparticles, H5T_NATIVE_LLONG);
395
396 // The value of nextid that we need to restore on restart.
397 CreateWriteHDF5Attr(fid, "maxnextid", 1, &maxnextid, H5T_NATIVE_LLONG);
398
399 // Then the finest level of the AMR hierarchy.
400 int finest_level = pc.finestLevel();
401 CreateWriteHDF5Attr(fid, "finest_level", 1, &finest_level, H5T_NATIVE_INT);
402
403 char level_name[128];
404 int ngrids;
405
406 hid_t dcpl_id = H5Pcreate(H5P_DATASET_CREATE);
407 H5Pset_fill_time(dcpl_id, H5D_FILL_TIME_NEVER);
408
409 for (int lev = 0; lev <= finest_level; ++lev) {
410 snprintf(level_name, sizeof level_name, "level_%d", lev);
411
412 grp = H5Gcreate(fid, level_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
413 if (grp < 0) {
414 std::cout << "H5Gcreate [" << level_name << "] failed!" << std::endl;
415 continue;
416 }
417
418 // Then the number of grids at each level.
419 ngrids = pc.ParticleBoxArray(lev).size();
420 CreateWriteHDF5Attr(grp, "ngrids", 1, &ngrids, H5T_NATIVE_INT);
421
422 /* int ratio = 1; */
423 /* CreateWriteHDF5Attr(grp, "ref_ratio", 1, &ratio); */
424
425 int mfs_size = 2 * AMREX_SPACEDIM;
426 hsize_t mfs_dim = (hsize_t)ngrids;
427
428 hid_t mfs_dset_space = H5Screate_simple(1, &mfs_dim, NULL);
429 hid_t mfs_dset= H5Dcreate(grp, "boxes", comp_dtype, mfs_dset_space, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
430
431 Vector<int> vbox(ngrids * mfs_size);
432 for(int j = 0; j < pc.ParticleBoxArray(lev).size(); ++j) {
433 for(int i = 0; i < AMREX_SPACEDIM; ++i) {
434 vbox[(j * mfs_size) + i] = pc.ParticleBoxArray(lev)[j].smallEnd(i);
435 vbox[(j * mfs_size) + i + AMREX_SPACEDIM] = pc.ParticleBoxArray(lev)[j].bigEnd(i);
436 }
437 }
438
439 status = H5Dwrite(mfs_dset, comp_dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &(vbox[0]));
440 if (status < 0) {
441 std::string msg("ParticleContainer::WriteHDF5ParticleDataSync(): unable to write boxes dataset");
442 amrex::Abort(msg.c_str());
443 }
444
445 H5Sclose(mfs_dset_space);
446 H5Dclose(mfs_dset);
447
448 H5Gclose(grp);
449 }
450 H5Pclose(dcpl_id);
451 H5Fclose(fid);
452 }
453
456
457 // We want to write the data out in parallel.
458 // We'll allow up to nOutFiles active writers at a time.
459 int nOutFiles(-1);
460
461 ParmParse pp("particles");
462 pp.query("particles_nfiles",nOutFiles);
463 if(nOutFiles == -1) nOutFiles = NProcs;
464 /* nOutFiles = std::max(1, std::min(nOutFiles,NProcs)); */
465 pc.nOutFilesPrePost = nOutFiles;
466
467 fapl = H5Pcreate (H5P_FILE_ACCESS);
468#ifdef AMREX_USE_MPI
470#else
471 SetHDF5fapl(fapl);
472#endif
473
474#ifdef AMREX_USE_HDF5_ASYNC
475 fid = H5Fopen_async(HDF5FileName.c_str(), H5F_ACC_RDWR, fapl, es_par_g);
476#else
477 fid = H5Fopen(HDF5FileName.c_str(), H5F_ACC_RDWR, fapl);
478#endif
479 if (fid < 0) {
480 FileOpenFailed(HDF5FileName.c_str());
481 }
482
483 char level_name[64];
484 for (int lev = 0; lev <= pc.finestLevel(); lev++)
485 {
486 snprintf(level_name, sizeof level_name, "level_%d", lev);
487#ifdef AMREX_USE_HDF5_ASYNC
488 grp = H5Gopen_async(fid, level_name, H5P_DEFAULT, es_par_g);
489#else
490 grp = H5Gopen(fid, level_name, H5P_DEFAULT);
491#endif
492
493 bool gotsome;
494 if(pc.usePrePost) {
495 gotsome = (pc.nParticlesAtLevelPrePost[lev] > 0);
496 } else {
497 gotsome = (pc.NumberOfParticlesAtLevel(lev) > 0);
498 }
499
500 MFInfo info;
501 info.SetAlloc(false);
502 MultiFab state(pc.ParticleBoxArray(lev),
503 pc.ParticleDistributionMap(lev),
504 1,0,info);
505
506 // We eventually want to write out the file name and the offset
507 // into that file into which each grid of particles is written.
508 Vector<int> which(state.size(),0);
509 Vector<int > count(state.size(),0);
510 Vector<Long> where(state.size(),0);
511
512 if(pc.usePrePost) {
513 pc.filePrefixPrePost[lev] = HDF5FileName;
514 }
515
516 if (gotsome)
517 {
518 pc.WriteParticlesHDF5(lev, grp, which, count, where,
519 write_real_comp, write_int_comp,
520 compression,
521 particle_io_flags, is_checkpoint);
522
523 if(pc.usePrePost) {
524 pc.whichPrePost[lev] = which;
525 pc.countPrePost[lev] = count;
526 pc.wherePrePost[lev] = where;
527 } else {
528 ParallelDescriptor::ReduceIntSum (which.dataPtr(), which.size(), IOProcNumber);
529 ParallelDescriptor::ReduceIntSum (count.dataPtr(), count.size(), IOProcNumber);
530 ParallelDescriptor::ReduceLongSum(where.dataPtr(), where.size(), IOProcNumber);
531 }
532 }
533
534#ifdef AMREX_USE_HDF5_ASYNC
535 H5Gclose_async(grp, es_par_g);
536#else
537 H5Gclose(grp);
538#endif
539 } // end for (lev...)
540
541 H5Tclose(comp_dtype);
542 H5Pclose(fapl);
543
544#ifdef AMREX_USE_HDF5_ASYNC
545 H5Fclose_async(fid, es_par_g);
546#else
547 H5Fclose(fid);
548#endif
549
550 return;
551} // End WriteHDF5ParticleDataSync
552
553}
554
555#endif /*AMREX_WRITE_BINARY_PARTICLE_DATA_HDF5_H*/
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define BL_PROFILE_VAR_STOP(vname)
Definition AMReX_BLProfiler.H:563
#define BL_PROFILE_VAR(fname, vname)
Definition AMReX_BLProfiler.H:560
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
amrex::ParmParse pp
Input file parser instance for the given namespace.
Definition AMReX_HypreIJIface.cpp:15
int size() const noexcept
Return the number of FABs in the FabArray.
Definition AMReX_FabArrayBase.H:110
A collection (stored as an array) of FArrayBox objects.
Definition AMReX_MultiFab.H:40
Parse Parameters From Command Line and Input Files.
Definition AMReX_ParmParse.H:351
int query(std::string_view name, bool &ref, int ival=FIRST) const
Same as querykth() but searches for the last occurrence of name.
Definition AMReX_ParmParse.cpp:1948
This class provides the user with a few print options.
Definition AMReX_Print.H:35
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
T * dataPtr() noexcept
get access to the underlying data pointer
Definition AMReX_Vector.H:50
Long size() const noexcept
Definition AMReX_Vector.H:54
amrex_long Long
Definition AMReX_INT.H:30
void Barrier(const std::string &)
Definition AMReX_ParallelDescriptor.cpp:1215
void ReduceIntSum(int &)
Definition AMReX_ParallelDescriptor.cpp:1265
int NProcs() noexcept
Definition AMReX_ParallelDescriptor.H:255
void ReduceLongSum(Long &)
Definition AMReX_ParallelDescriptor.cpp:1236
int IOProcessorNumber() noexcept
The MPI rank number of the I/O Processor (probably rank 0). This rank is usually used to write to std...
Definition AMReX_ParallelDescriptor.H:279
void ReduceLongMax(Long &)
Definition AMReX_ParallelDescriptor.cpp:1237
bool IOProcessor() noexcept
Is this CPU the I/O Processor? To get the rank number, call IOProcessorNumber()
Definition AMReX_ParallelDescriptor.H:289
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:310
MPI_Comm Communicator() noexcept
Definition AMReX_ParallelDescriptor.H:223
int MPI_Comm
Definition AMReX_ccse-mpi.H:51
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:139
void FileOpenFailed(const std::string &file)
Output a message and abort when couldn't open the file.
Definition AMReX_Utility.cpp:137
void WriteHDF5ParticleDataSync(PC const &pc, const std::string &dir, const std::string &name, const Vector< int > &write_real_comp, const Vector< int > &write_int_comp, const Vector< std::string > &real_comp_names, const Vector< std::string > &int_comp_names, const std::string &compression, F &&f, bool is_checkpoint)
Synchronous HDF5 particle writer shared by checkpoint and plotfile routines.
Definition AMReX_WriteBinaryParticleDataHDF5.H:185
void CreateDirectoryFailed(const std::string &dir)
Output a message and abort when couldn't create the directory.
Definition AMReX_Utility.cpp:129
bool UtilCreateDirectory(const std::string &path, mode_t mode, bool verbose=false)
Creates the specified directories. path may be either a full pathname or a relative pathname....
Definition AMReX_Utility.cpp:116
static int CreateWriteHDF5AttrString(hid_t loc, const char *name, const char *str)
Definition AMReX_PlotFileUtilHDF5.cpp:79
static int CreateWriteHDF5Attr(hid_t loc, const char *name, hsize_t n, void *data, hid_t dtype)
Create and write a numeric attribute on the given HDF5 object.
Definition AMReX_WriteBinaryParticleDataHDF5.H:25
static void SetHDF5fapl(hid_t fapl, MPI_Comm comm)
Definition AMReX_PlotFileUtilHDF5.cpp:111
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:241
void ExecOnFinalize(std::function< void()>)
We maintain a stack of functions that need to be called in Finalize(). The functions are called in LI...
Definition AMReX.cpp:331
static int ReadHDF5Attr(hid_t loc, const char *name, void *data, hid_t dtype)
Read an attribute from an HDF5 object into the supplied buffer.
Definition AMReX_WriteBinaryParticleDataHDF5.H:100
FabArray memory allocation information.
Definition AMReX_FabArray.H:68
MFInfo & SetAlloc(bool a) noexcept
Definition AMReX_FabArray.H:75