Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AMReX_WriteBinaryParticleData.H
Go to the documentation of this file.
1#ifndef AMREX_WRITE_BINARY_PARTICLE_DATA_H
2#define AMREX_WRITE_BINARY_PARTICLE_DATA_H
3#include <AMReX_Config.H>
4
5#include <AMReX_TypeTraits.H>
7#include <AMReX_GpuDevice.H>
8
9namespace amrex {
10
12{
13 template <typename SrcData>
15 int operator() (const SrcData& src, int i) const noexcept
16 {
17 return (src.id(i) > 0);
18 }
19};
20
21namespace particle_detail {
22
23template <typename ParticleReal>
24std::size_t PSizeInFile (const Vector<int>& wrc, const Vector<int>& wic)
25{
26 std::size_t rsize = sizeof(ParticleReal)*std::accumulate(wrc.begin(), wrc.end(), 0);
27 std::size_t isize = sizeof(int)*std::accumulate(wic.begin(), wic.end(), 0);
28 return rsize + isize + AMREX_SPACEDIM*sizeof(ParticleReal) + 2*sizeof(int);
29}
30
31template <template <class, class> class Container,
32 class Allocator,
33 class PTile,
34 class F>
35std::enable_if_t<RunOnGpu<typename Container<int, Allocator>::allocator_type>::value>
36fillFlags (Container<int, Allocator>& pflags, const PTile& ptile, F const& f)
37{
38 const auto& ptd = ptile.getConstParticleTileData();
39 const auto np = ptile.numParticles();
40 pflags.resize(np, 0);
41 auto flag_ptr = pflags.data();
43 [=] AMREX_GPU_DEVICE (int k, amrex::RandomEngine const& engine) noexcept
44 {
45 const auto p = ptd.getSuperParticle(k);
46 amrex::ignore_unused(flag_ptr, f, engine);
47 if constexpr (IsCallable<F,decltype(p),RandomEngine>::value) {
48 flag_ptr[k] = f(p,engine);
49 } else {
50 flag_ptr[k] = f(p);
51 }
52 });
53}
54
55template <template <class, class> class Container,
56 class Allocator,
57 class PTile,
58 class F>
59std::enable_if_t<!RunOnGpu<typename Container<int, Allocator>::allocator_type>::value>
60fillFlags (Container<int, Allocator>& pflags, const PTile& ptile, F const& f)
61{
62 const auto& ptd = ptile.getConstParticleTileData();
63 const auto np = ptile.numParticles();
64 pflags.resize(np, 0);
65 auto flag_ptr = pflags.data();
66 for (int k = 0; k < np; ++k) {
67 const auto p = ptd.getSuperParticle(k);
68 if constexpr (IsCallable<F,decltype(p),RandomEngine>::value) {
69 flag_ptr[k] = f(p,RandomEngine{});
70 } else {
71 flag_ptr[k] = f(p);
72 }
73 }
74}
75
76template <template <class, class> class Container, class Allocator, class PC>
77std::enable_if_t<RunOnGpu<typename Container<int, Allocator>::allocator_type>::value, amrex::Long>
78countFlags (const Vector<std::map<std::pair<int,int>,Container<int,Allocator>>>& particle_io_flags, const PC& pc)
79{
80 ReduceOps<ReduceOpSum> reduce_op;
81 ReduceData<Long> reduce_data(reduce_op);
82 using ReduceTuple = typename decltype(reduce_data)::Type;
83
84 for (int lev = 0; lev < pc.GetParticles().size(); lev++)
85 {
86 const auto& pmap = pc.GetParticles(lev);
87 for (const auto& kv : pmap)
88 {
89 const auto& pflags = particle_io_flags[lev].at(kv.first);
90 const auto flag_ptr = pflags.data();
91 reduce_op.eval(pflags.size(), reduce_data,
92 [=] AMREX_GPU_DEVICE (const int i) -> ReduceTuple
93 {
94 return flag_ptr[i] ? 1 : 0;
95 });
96 }
97 }
98 ReduceTuple hv = reduce_data.value(reduce_op);
99 return amrex::get<0>(hv);
100}
101
102template <template <class, class> class Container, class Allocator>
103std::enable_if_t<RunOnGpu<typename Container<int, Allocator>::allocator_type>::value, int>
104countFlags (const Container<int,Allocator>& pflags)
105{
106 ReduceOps<ReduceOpSum> reduce_op;
107 ReduceData<Long> reduce_data(reduce_op);
108 using ReduceTuple = typename decltype(reduce_data)::Type;
109
110 const auto flag_ptr = pflags.data();
111 reduce_op.eval(pflags.size(), reduce_data,
112 [=] AMREX_GPU_DEVICE (const int i) -> ReduceTuple
113 {
114 return flag_ptr[i] ? 1 : 0;
115 });
116 ReduceTuple hv = reduce_data.value(reduce_op);
117 return amrex::get<0>(hv);
118}
119
120template <template <class, class> class Container, class Allocator, class PC>
121std::enable_if_t<!RunOnGpu<typename Container<int, Allocator>::allocator_type>::value, amrex::Long>
122countFlags (const Vector<std::map<std::pair<int,int>,Container<int,Allocator>>>& particle_io_flags, const PC& pc)
123{
124 amrex::Long nparticles = 0;
125 for (int lev = 0; lev < pc.GetParticles().size(); lev++)
126 {
127 const auto& pmap = pc.GetParticles(lev);
128 for (const auto& kv : pmap)
129 {
130 const auto& pflags = particle_io_flags[lev].at(kv.first);
131 for (int k = 0; k < kv.second.numParticles(); ++k)
132 {
133 if (pflags[k]) { nparticles++; }
134 }
135 }
136 }
137 return nparticles;
138}
139
140template <template <class, class> class Container, class Allocator>
141std::enable_if_t<!RunOnGpu<typename Container<int, Allocator>::allocator_type>::value, int>
142countFlags (const Container<int,Allocator>& pflags)
143{
144 int nparticles = 0;
145 for (std::size_t k = 0; k < pflags.size(); ++k)
146 {
147 if (pflags[k]) { nparticles++; }
148 }
149 return nparticles;
150}
151
152template <typename P, typename I>
154void packParticleIDs (I* idata, const P& p, bool is_checkpoint) noexcept
155{
156 if (is_checkpoint) {
157 std::int32_t xi, yi;
158 std::uint32_t xu, yu;
159 xu = (std::uint32_t)((p.m_idcpu & 0xFFFFFFFF00000000LL) >> 32);
160 yu = (std::uint32_t)( p.m_idcpu & 0xFFFFFFFFLL);
161 amrex::Gpu::memcpy(&xi, &xu, sizeof(xu));
162 amrex::Gpu::memcpy(&yi, &yu, sizeof(yu));
163 idata[0] = xi;
164 idata[1] = yi;
165 } else {
166 idata[0] = p.id();
167 idata[1] = p.cpu();
168 }
169}
170
171template <class PC>
172std::enable_if_t<RunOnGpu<typename PC::template AllocatorType<int>>::value, void>
173packIOData (Vector<int>& idata, Vector<ParticleReal>& rdata, const PC& pc, int lev, int grid,
174 const Vector<int>& write_real_comp, const Vector<int>& write_int_comp,
175 const Vector<std::map<std::pair<int, int>, typename PC::IntVector>>& particle_io_flags,
176 const Vector<int>& tiles, int np, bool is_checkpoint)
177{
178 int num_output_int = 0;
179 for (int i = 0; i < pc.NumIntComps() + PC::NStructInt; ++i) {
180 if (write_int_comp[i]) { ++num_output_int; }
181 }
182
183 const Long iChunkSize = 2 + num_output_int;
184 idata.resize(np*iChunkSize);
185
186 int num_output_real = 0;
187 for (int i : write_real_comp) {
188 if (i) { ++num_output_real; }
189 }
190
191 const Long rChunkSize = AMREX_SPACEDIM + num_output_real;
192 rdata.resize(np*rChunkSize);
193
194 typename PC::IntVector write_int_comp_d(write_int_comp.size());
195 typename PC::IntVector write_real_comp_d(write_real_comp.size());
196 Gpu::copyAsync(Gpu::hostToDevice, write_int_comp.begin(), write_int_comp.end(),
197 write_int_comp_d.begin());
198 Gpu::copyAsync(Gpu::hostToDevice, write_real_comp.begin(), write_real_comp.end(),
199 write_real_comp_d.begin());
200
201 const auto write_int_comp_d_ptr = write_int_comp_d.data();
202 const auto write_real_comp_d_ptr = write_real_comp_d.data();
203
204 std::size_t poffset = 0;
205 for (int tile : tiles) {
206 const auto& ptile = pc.ParticlesAt(lev, grid, tile);
207 const auto& pflags = particle_io_flags[lev].at(std::make_pair(grid, tile));
208 int np_tile = ptile.numParticles();
209 typename PC::IntVector offsets(np_tile);
210 int num_copies = Scan::ExclusiveSum(np_tile, pflags.begin(), offsets.begin(), Scan::retSum);
211
212 typename PC::IntVector idata_d(num_copies*iChunkSize);
213 typename PC::RealVector rdata_d(num_copies*rChunkSize);
214
215 const auto flag_ptr = pflags.data();
216
217 auto idata_d_ptr = idata_d.data();
218 auto rdata_d_ptr = rdata_d.data();
219
220 const auto& ptd = ptile.getConstParticleTileData();
221 amrex::ParallelFor(num_copies,
222 [=] AMREX_GPU_DEVICE (int pindex) noexcept
223 {
224 // might be worth using shared memory here
225 const auto p = ptd.getSuperParticle(pindex);
226
227 if (flag_ptr[pindex]) {
228 std::size_t iout_index = pindex*iChunkSize;
229 packParticleIDs(&idata_d_ptr[iout_index], p, is_checkpoint);
230 iout_index += 2;
231
232 std::size_t rout_index = pindex*rChunkSize;
233 for (int j = 0; j < AMREX_SPACEDIM; j++) {
234 rdata_d_ptr[rout_index] = p.pos(j);
235 rout_index++;
236 }
237
238 for (int j = 0; j < PC::SuperParticleType::NInt; j++) {
239 if (write_int_comp_d_ptr[j]) {
240 idata_d_ptr[iout_index] = p.idata(j);
241 iout_index++;
242 }
243 }
244
245 for (int j = 0; j < ptd.m_num_runtime_int; j++) {
246 if (write_int_comp_d_ptr[PC::SuperParticleType::NInt + j]) {
247 idata_d_ptr[iout_index] = ptd.m_runtime_idata[j][pindex];
248 iout_index++;
249 }
250 }
251
252 // extra SoA Real components
253 const int real_start_offset = PC::ParticleType::is_soa_particle ? AMREX_SPACEDIM : 0; // pure SoA: skip positions
254 for (int j = real_start_offset; j < PC::SuperParticleType::NReal; j++) {
255 const int write_comp_index = j-real_start_offset;
256 if (write_real_comp_d_ptr[write_comp_index]) {
257 rdata_d_ptr[rout_index] = p.rdata(j);
258 rout_index++;
259 }
260 }
261
262 for (int j = 0; j < ptd.m_num_runtime_real; j++) {
263 if (write_real_comp_d_ptr[PC::SuperParticleType::NReal+j-real_start_offset]) {
264 rdata_d_ptr[rout_index] = ptd.m_runtime_rdata[j][pindex];
265 rout_index++;
266 }
267 }
268 }
269 });
270
271 Gpu::copyAsync(Gpu::deviceToHost, idata_d.begin(), idata_d.end(),
272 idata.begin() + typename PC::IntVector::difference_type(poffset));
273 Gpu::copyAsync(Gpu::deviceToHost, rdata_d.begin(), rdata_d.end(),
274 rdata.begin() + typename PC::RealVector::difference_type(poffset));
276
277 poffset += num_copies;
278 }
279}
280
281template <class PC>
282std::enable_if_t<!RunOnGpu<typename PC::template AllocatorType<int>>::value, void>
283packIOData (Vector<int>& idata, Vector<ParticleReal>& rdata, const PC& pc, int lev, int grid,
284 const Vector<int>& write_real_comp, const Vector<int>& write_int_comp,
285 const Vector<std::map<std::pair<int, int>, typename PC::IntVector>>& particle_io_flags,
286 const Vector<int>& tiles, int np, bool is_checkpoint)
287{
288 int num_output_int = 0;
289 for (int i = 0; i < pc.NumIntComps() + PC::NStructInt; ++i) {
290 if (write_int_comp[i]) { ++num_output_int; }
291 }
292
293 const Long iChunkSize = 2 + num_output_int;
294 idata.resize(np*iChunkSize);
295
296 int num_output_real = 0;
297 for (int i : write_real_comp) {
298 if (i) { ++num_output_real; }
299 }
300
301 const Long rChunkSize = AMREX_SPACEDIM + num_output_real;
302 rdata.resize(np*rChunkSize);
303
304 int* iptr = idata.dataPtr();
305 ParticleReal* rptr = rdata.dataPtr();
306 for (int tile : tiles) {
307 const auto& ptile = pc.ParticlesAt(lev, grid, tile);
308 const auto& pflags = particle_io_flags[lev].at(std::make_pair(grid, tile));
309 for (int pindex = 0; pindex < ptile.numParticles(); ++pindex) {
310 if (pflags[pindex]) {
311 const auto& soa = ptile.GetStructOfArrays();
312
313 // note: for pure SoA particle layouts, we do write the id, cpu and positions as a struct
314 // for backwards compatibility with readers
315 if constexpr(!PC::ParticleType::is_soa_particle)
316 {
317 const auto& aos = ptile.GetArrayOfStructs();
318 const auto& p = aos[pindex];
319
320 // Int: id, cpu
321 packParticleIDs(iptr, p, is_checkpoint);
322 iptr += 2;
323
324 // Real: positions
325 for (int j = 0; j < AMREX_SPACEDIM; j++) { rptr[j] = p.pos(j); }
326 rptr += AMREX_SPACEDIM;
327
328 // extra AoS Int components
329 for (int j = 0; j < PC::NStructInt; j++) {
330 if (write_int_comp[j]) {
331 *iptr = p.idata(j);
332 ++iptr;
333 }
334 }
335 // extra AoS Real components
336 for (int j = 0; j < PC::NStructReal; j++) {
337 if (write_real_comp[j]) {
338 *rptr = p.rdata(j);
339 ++rptr;
340 }
341 }
342 }
343 else {
344 uint64_t idcpu = soa.GetIdCPUData()[pindex];
345 if (is_checkpoint) {
346 std::int32_t xi, yi;
347 std::uint32_t xu, yu;
348 xu = (std::uint32_t)((idcpu & 0xFFFFFFFF00000000LL) >> 32);
349 yu = (std::uint32_t)( idcpu & 0xFFFFFFFFLL);
350 std::memcpy(&xi, &xu, sizeof(xu));
351 std::memcpy(&yi, &yu, sizeof(yu));
352 *iptr = xi;
353 iptr += 1;
354 *iptr = yi;
355 iptr += 1;
356 } else {
357 // Int: id, cpu
358 *iptr = (int) ParticleIDWrapper(idcpu);
359 iptr += 1;
360 *iptr = (int) ParticleCPUWrapper(idcpu);
361 iptr += 1;
362 }
363
364 // Real: position
365 for (int j = 0; j < AMREX_SPACEDIM; j++) { rptr[j] = soa.GetRealData(j)[pindex]; }
366 rptr += AMREX_SPACEDIM;
367 }
368
369 // SoA int data
370 const int int_start_offset = 0;
371 for (int j = int_start_offset; j < pc.NumIntComps(); j++) {
372 if (write_int_comp[PC::NStructInt+j]) {
373 *iptr = soa.GetIntData(j)[pindex];
374 ++iptr;
375 }
376 }
377
378 // extra SoA Real components
379 const int real_start_offset = PC::ParticleType::is_soa_particle ? AMREX_SPACEDIM : 0; // pure SoA: skip positions
380 for (int j = real_start_offset; j < pc.NumRealComps(); j++) {
381 const int write_comp_index = PC::NStructReal+j-real_start_offset;
382 if (write_real_comp[write_comp_index]) {
383 *rptr = (ParticleReal) soa.GetRealData(j)[pindex];
384 ++rptr;
385 }
386 }
387 }
388 }
389 }
390}
391}
392
393template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value, int> foo = 0>
395 const std::string& dir, const std::string& name,
396 const Vector<int>& write_real_comp,
397 const Vector<int>& write_int_comp,
398 const Vector<std::string>& real_comp_names,
399 const Vector<std::string>& int_comp_names,
400 F const& f, bool is_checkpoint)
401{
402 BL_PROFILE("WriteBinaryParticleData()");
403 AMREX_ASSERT(pc.OK());
404
405 AMREX_ASSERT(sizeof(typename PC::ParticleType::RealType) == 4 ||
406 sizeof(typename PC::ParticleType::RealType) == 8);
407
408 constexpr int NStructReal = PC::NStructReal;
409 constexpr int NStructInt = PC::NStructInt;
410
411 const int NProcs = ParallelDescriptor::NProcs();
412 const int IOProcNumber = ParallelDescriptor::IOProcessorNumber();
413
414 if constexpr(PC::ParticleType::is_soa_particle) {
415 AMREX_ALWAYS_ASSERT(real_comp_names.size() == pc.NumRealComps() + NStructReal - AMREX_SPACEDIM); // pure SoA: skip positions
416 } else {
417 AMREX_ALWAYS_ASSERT(real_comp_names.size() == pc.NumRealComps() + NStructReal);
418 }
419 AMREX_ALWAYS_ASSERT( int_comp_names.size() == pc.NumIntComps() + NStructInt);
420
421 std::string pdir = dir;
422 if ( ! pdir.empty() && pdir[pdir.size()-1] != '/') { pdir += '/'; }
423 pdir += name;
424
425 if ( ! pc.GetLevelDirectoriesCreated()) {
427 {
428 if ( ! amrex::UtilCreateDirectory(pdir, 0755))
429 {
431 }
432 }
434 }
435
436 std::ofstream HdrFile;
437
438 Long nparticles = 0;
439 Long maxnextid;
440
441 // evaluate f for every particle to determine which ones to output
442 Vector<std::map<std::pair<int, int>, typename PC::IntVector > >
443 particle_io_flags(pc.GetParticles().size());
444 for (int lev = 0; lev < pc.GetParticles().size(); lev++)
445 {
446 const auto& pmap = pc.GetParticles(lev);
447 for (const auto& kv : pmap)
448 {
449 auto& flags = particle_io_flags[lev][kv.first];
450 particle_detail::fillFlags(flags, kv.second, f);
451 }
452 }
453
455
456 if(pc.GetUsePrePost())
457 {
458 nparticles = pc.GetNParticlesPrePost();
459 maxnextid = pc.GetMaxNextIDPrePost();
460 }
461 else
462 {
463 nparticles = particle_detail::countFlags(particle_io_flags, pc);
464 maxnextid = PC::ParticleType::NextID();
465 ParallelDescriptor::ReduceLongSum(nparticles, IOProcNumber);
466 PC::ParticleType::NextID(maxnextid);
467 ParallelDescriptor::ReduceLongMax(maxnextid, IOProcNumber);
468 }
469
471 {
472 std::string HdrFileName = pdir;
473
474 if ( ! HdrFileName.empty() && HdrFileName[HdrFileName.size()-1] != '/') {
475 HdrFileName += '/';
476 }
477
478 HdrFileName += "Header";
479 pc.HdrFileNamePrePost = HdrFileName;
480
481 HdrFile.open(HdrFileName.c_str(), std::ios::out|std::ios::trunc);
482
483 if ( ! HdrFile.good()) { amrex::FileOpenFailed(HdrFileName); }
484
485 //
486 // First thing written is our version string.
487 // We append "_single" or "_double" to the version string indicating
488 // whether we're using "float" or "double" floating point data.
489 //
490 std::string version_string = is_checkpoint ? PC::CheckpointVersion() : PC::PlotfileVersion();
491 if (sizeof(typename PC::ParticleType::RealType) == 4)
492 {
493 HdrFile << version_string << "_single" << '\n';
494 }
495 else
496 {
497 HdrFile << version_string << "_double" << '\n';
498 }
499
500 int num_output_real = 0;
501 for (int i : write_real_comp) {
502 if (i) { ++num_output_real; }
503 }
504
505 int num_output_int = 0;
506 for (int i = 0; i < pc.NumIntComps() + NStructInt; ++i) {
507 if (write_int_comp[i]) { ++num_output_int; }
508 }
509
510 // AMREX_SPACEDIM and N for sanity checking.
511 HdrFile << AMREX_SPACEDIM << '\n';
512
513 // The number of extra real parameters
514 HdrFile << num_output_real << '\n';
515
516 // Real component names
517 for (int i = 0; i < (int) real_comp_names.size(); ++i ) {
518 if (write_real_comp[i]) { HdrFile << real_comp_names[i] << '\n'; }
519 }
520
521 // The number of extra int parameters
522 HdrFile << num_output_int << '\n';
523
524 // int component names
525 for (int i = 0; i < NStructInt + pc.NumIntComps(); ++i ) {
526 if (write_int_comp[i]) { HdrFile << int_comp_names[i] << '\n'; }
527 }
528
529 bool is_checkpoint_legacy = true; // legacy
530 HdrFile << is_checkpoint_legacy << '\n';
531
532 // The total number of particles.
533 HdrFile << nparticles << '\n';
534
535 // The value of nextid that we need to restore on restart.
536 HdrFile << maxnextid << '\n';
537
538 // Then the finest level of the AMR hierarchy.
539 HdrFile << pc.finestLevel() << '\n';
540
541 // Then the number of grids at each level.
542 for (int lev = 0; lev <= pc.finestLevel(); lev++) {
543 HdrFile << pc.ParticleBoxArray(lev).size() << '\n';
544 }
545 }
546
547 // We want to write the data out in parallel.
548 // We'll allow up to nOutFiles active writers at a time.
549 int nOutFiles(256);
550
551 ParmParse pp("particles");
552 pp.queryAdd("particles_nfiles",nOutFiles);
553 if(nOutFiles == -1) { nOutFiles = NProcs; }
554 nOutFiles = std::max(1, std::min(nOutFiles,NProcs));
555 pc.nOutFilesPrePost = nOutFiles;
556
557 for (int lev = 0; lev <= pc.finestLevel(); lev++)
558 {
559 bool gotsome;
560 if(pc.usePrePost)
561 {
562 gotsome = (pc.nParticlesAtLevelPrePost[lev] > 0);
563 }
564 else
565 {
566 gotsome = (pc.NumberOfParticlesAtLevel(lev) > 0);
567 }
568
569 // We store the particles at each level in their own subdirectory.
570 std::string LevelDir = pdir;
571
572 if (gotsome)
573 {
574 if ( ! LevelDir.empty() && LevelDir[LevelDir.size()-1] != '/') { LevelDir += '/'; }
575
576 LevelDir = amrex::Concatenate(LevelDir.append("Level_"), lev, 1);
577
578 if ( ! pc.GetLevelDirectoriesCreated())
579 {
581 if ( ! amrex::UtilCreateDirectory(LevelDir, 0755)) {
583 }
584 }
586 }
587 }
588
589 // Write out the header for each particle
590 if (gotsome && ParallelDescriptor::IOProcessor()) {
591 std::string HeaderFileName = LevelDir;
592 HeaderFileName += "/Particle_H";
593 std::ofstream ParticleHeader(HeaderFileName);
594
595 pc.ParticleBoxArray(lev).writeOn(ParticleHeader);
596 ParticleHeader << '\n';
597
598 ParticleHeader.flush();
599 ParticleHeader.close();
600 }
601
602 MFInfo info;
603 info.SetAlloc(false);
604 MultiFab state(pc.ParticleBoxArray(lev),
605 pc.ParticleDistributionMap(lev),
606 1,0,info);
607
608 // We eventually want to write out the file name and the offset
609 // into that file into which each grid of particles is written.
610 Vector<int> which(state.size(),0);
611 Vector<int > count(state.size(),0);
612 Vector<Long> where(state.size(),0);
613
614 std::string filePrefix(LevelDir);
615 filePrefix += '/';
616 filePrefix += PC::DataPrefix();
617 if(pc.usePrePost) {
618 pc.filePrefixPrePost[lev] = filePrefix;
619 }
620 bool groupSets(false), setBuf(true);
621
622 if (gotsome)
623 {
624 for(NFilesIter nfi(nOutFiles, filePrefix, groupSets, setBuf); nfi.ReadyToWrite(); ++nfi)
625 {
626 auto& myStream = (std::ofstream&) nfi.Stream();
627 pc.WriteParticles(lev, myStream, nfi.FileNumber(), which, count, where,
628 write_real_comp, write_int_comp, particle_io_flags, is_checkpoint);
629 }
630
631 if(pc.usePrePost) {
632 pc.whichPrePost[lev] = which;
633 pc.countPrePost[lev] = count;
634 pc.wherePrePost[lev] = where;
635 } else {
636 ParallelDescriptor::ReduceIntSum (which.dataPtr(), static_cast<int>(which.size()), IOProcNumber);
637 ParallelDescriptor::ReduceIntSum (count.dataPtr(), static_cast<int>(count.size()), IOProcNumber);
638 ParallelDescriptor::ReduceLongSum(where.dataPtr(), static_cast<int>(where.size()), IOProcNumber);
639 }
640 }
641
643 {
644 if(pc.GetUsePrePost()) {
645 // ---- write to the header and unlink in CheckpointPost
646 } else {
647 for (int j = 0; j < state.size(); j++)
648 {
649 HdrFile << which[j] << ' ' << count[j] << ' ' << where[j] << '\n';
650 }
651
652 if (gotsome && pc.doUnlink)
653 {
654 // Unlink any zero-length data files.
655 Vector<Long> cnt(nOutFiles,0);
656
657 for (int i = 0, N=static_cast<int>(count.size()); i < N; i++) {
658 cnt[which[i]] += count[i];
659 }
660
661 for (int i = 0, N=static_cast<int>(cnt.size()); i < N; i++)
662 {
663 if (cnt[i] == 0)
664 {
665 std::string FullFileName = NFilesIter::FileName(i, filePrefix);
666 FileSystem::Remove(FullFileName);
667 }
668 }
669 }
670 }
671 }
672 }
673
675 {
676 HdrFile.flush();
677 HdrFile.close();
678 if ( ! HdrFile.good())
679 {
680 amrex::Abort("amrex::WriteBinaryParticleDataSync(): problem writing HdrFile");
681 }
682 }
683}
684
685template <class PC, std::enable_if_t<IsParticleContainer<PC>::value, int> foo = 0>
687 const std::string& dir, const std::string& name,
688 const Vector<int>& write_real_comp,
689 const Vector<int>& write_int_comp,
690 const Vector<std::string>& real_comp_names,
691 const Vector<std::string>& int_comp_names, bool is_checkpoint)
692{
693 BL_PROFILE("WriteBinaryParticleDataAsync");
694 AMREX_ASSERT(pc.OK());
695
696 AMREX_ASSERT(sizeof(typename PC::ParticleType::RealType) == 4 ||
697 sizeof(typename PC::ParticleType::RealType) == 8);
698
699 constexpr int NStructReal = PC::NStructReal;
700 constexpr int NStructInt = PC::NStructInt;
701 constexpr int NArrayReal = PC::NArrayReal;
702 constexpr int NArrayInt = PC::NArrayInt;
703
704 const int MyProc = ParallelDescriptor::MyProc();
705 const int NProcs = ParallelDescriptor::NProcs();
706 const int IOProcNumber = NProcs - 1;
707
708 if constexpr(PC::ParticleType::is_soa_particle) {
709 AMREX_ALWAYS_ASSERT(real_comp_names.size() == pc.NumRealComps() + NStructReal - AMREX_SPACEDIM); // pure SoA: skip positions
710 } else {
711 AMREX_ALWAYS_ASSERT(real_comp_names.size() == pc.NumRealComps() + NStructReal);
712 }
713 AMREX_ALWAYS_ASSERT( int_comp_names.size() == pc.NumIntComps() + NStructInt);
714
715 Vector<LayoutData<Long> > np_per_grid_local(pc.finestLevel()+1);
716 for (int lev = 0; lev <= pc.finestLevel(); lev++)
717 {
718 np_per_grid_local[lev].define(pc.ParticleBoxArray(lev), pc.ParticleDistributionMap(lev));
719 using ParIter = typename PC::ParConstIterType;
720 for (ParIter pti(pc, lev); pti.isValid(); ++pti)
721 {
722 int gid = pti.index();
723 const auto& ptile = pc.ParticlesAt(lev, pti);
724 const auto& ptd = ptile.getConstParticleTileData();
725 const int np = ptile.numParticles();
726
727 ReduceOps<ReduceOpSum> reduce_op;
728 ReduceData<int> reduce_data(reduce_op);
729 using ReduceTuple = typename decltype(reduce_data)::Type;
730
731 reduce_op.eval(np, reduce_data,
732 [=] AMREX_GPU_DEVICE (int i) -> ReduceTuple
733 {
734 return (ptd.id(i) > 0) ? 1 : 0;
735 });
736
737 int np_valid = amrex::get<0>(reduce_data.value(reduce_op));
738 np_per_grid_local[lev][gid] += np_valid;
739 }
740 }
741
742 Vector<Vector<Long> > np_per_grid_global(pc.finestLevel()+1);
743 Long total_np = 0;
744 Vector<Long> np_per_level(pc.finestLevel()+1);
745 for (int lev = 0; lev <= pc.finestLevel(); lev++)
746 {
747 np_per_grid_global[lev].resize(np_per_grid_local[lev].size());
749 np_per_grid_global[lev],
750 IOProcNumber);
751 np_per_level[lev] = std::accumulate(np_per_grid_global[lev].begin(),
752 np_per_grid_global[lev].end(), 0L);
753 total_np += np_per_level[lev];
754 }
755
756 std::string pdir = dir;
757 if ( ! pdir.empty() && pdir[pdir.size()-1] != '/') { pdir += '/'; }
758 pdir += name;
759
760 if (MyProc == IOProcNumber)
761 {
762 if ( ! pc.GetLevelDirectoriesCreated())
763 {
764 if ( ! amrex::UtilCreateDirectory(pdir, 0755))
765 {
767 }
768 }
769
770 for (int lev = 0; lev <= pc.finestLevel(); lev++)
771 {
772 std::string LevelDir = pdir;
773 bool gotsome = np_per_level[lev];
774
775 if (gotsome)
776 {
777 if ( ! LevelDir.empty() && LevelDir[LevelDir.size()-1] != '/') { LevelDir += '/'; }
778
779 LevelDir = amrex::Concatenate(LevelDir.append("Level_"), lev, 1);
780
781 if ( ! pc.GetLevelDirectoriesCreated())
782 {
783 if ( ! amrex::UtilCreateDirectory(LevelDir, 0755))
784 {
786 }
787 }
788
789 std::string HeaderFileName = LevelDir;
790 HeaderFileName += "/Particle_H";
791 std::ofstream ParticleHeader(HeaderFileName);
792
793 pc.ParticleBoxArray(lev).writeOn(ParticleHeader);
794 ParticleHeader << '\n';
795
796 ParticleHeader.flush();
797 ParticleHeader.close();
798 }
799 }
800 }
802
803 Long maxnextid = PC::ParticleType::NextID();
804 ParallelDescriptor::ReduceLongMax(maxnextid, IOProcNumber);
805
806 Vector<Long> np_on_rank(NProcs, 0L);
807 std::size_t psize = particle_detail::PSizeInFile<ParticleReal>(write_real_comp, write_int_comp);
808 Vector<int64_t> rank_start_offset(NProcs);
809 if (MyProc == IOProcNumber)
810 {
811 for (int lev = 0; lev <= pc.finestLevel(); lev++)
812 {
813 for (int k = 0; k < pc.ParticleBoxArray(lev).size(); ++k)
814 {
815 int rank = pc.ParticleDistributionMap(lev)[k];
816 np_on_rank[rank] += np_per_grid_global[lev][k];
817 }
818 }
819
820 for (int ip = 0; ip < NProcs; ++ip)
821 {
822 auto info = AsyncOut::GetWriteInfo(ip);
823 rank_start_offset[ip] = (info.ispot == 0) ? 0 : static_cast<int64_t>(rank_start_offset[ip-1] + np_on_rank[ip-1]*psize);
824 }
825 }
826
827 // make tmp particle tiles in pinned memory to write
828 using PinnedPTile = ParticleTile<typename PC::ParticleType, NArrayReal, NArrayInt,
830 auto myptiles = std::make_shared<Vector<std::map<std::pair<int, int>,PinnedPTile> > >();
831 myptiles->resize(pc.finestLevel()+1);
832 for (int lev = 0; lev <= pc.finestLevel(); lev++)
833 {
834 for (MFIter mfi = pc.MakeMFIter(lev); mfi.isValid(); ++mfi)
835 {
836 auto& new_ptile = (*myptiles)[lev][std::make_pair(mfi.index(),
837 mfi.LocalTileIndex())];
838
839 if (np_per_grid_local[lev][mfi.index()] > 0)
840 {
841 const auto& ptile = pc.ParticlesAt(lev, mfi);
842
843 const auto np = np_per_grid_local[lev][mfi.index()];
844
845 new_ptile.resize(np);
846
847 const auto runtime_real_comps = ptile.NumRuntimeRealComps();
848 const auto runtime_int_comps = ptile.NumRuntimeIntComps();
849
850 new_ptile.define(runtime_real_comps, runtime_int_comps);
851
852 for (auto comp(0); comp < runtime_real_comps; ++comp) {
853 new_ptile.push_back_real(NArrayReal+comp, np, 0.);
854 }
855
856 for (auto comp(0); comp < runtime_int_comps; ++comp) {
857 new_ptile.push_back_int(NArrayInt+comp, np, 0);
858 }
859
860 amrex::filterParticles(new_ptile, ptile, KeepValidFilter());
861 }
862 }
863 }
864
865 int finest_level = pc.finestLevel();
868 for (int lev = 0; lev <= pc.finestLevel(); lev++)
869 {
870 bas.push_back(pc.ParticleBoxArray(lev));
871 dms.push_back(pc.ParticleDistributionMap(lev));
872 }
873
874 int nrc = pc.NumRealComps();
875 int nic = pc.NumIntComps();
876 int rnames_size = (int) real_comp_names.size();
877
878 auto RD = pc.ParticleRealDescriptor;
879
880 AsyncOut::Submit([=] ()
881#if defined(__GNUC__) && (__GNUC__ == 8) && (__GNUC_MINOR__ == 1)
882 mutable // workaround for bug in gcc 8.1
883#endif
884 {
885 if (MyProc == IOProcNumber)
886 {
887 std::string HdrFileName = pdir;
888 std::ofstream HdrFile;
889
890 if ( ! HdrFileName.empty() && HdrFileName[HdrFileName.size()-1] != '/') {
891 HdrFileName += '/';
892 }
893
894 HdrFileName += "Header";
895
896 HdrFile.open(HdrFileName.c_str(), std::ios::out|std::ios::trunc);
897
898 if ( ! HdrFile.good()) { amrex::FileOpenFailed(HdrFileName); }
899
900 std::string version_string = is_checkpoint ? PC::CheckpointVersion() : PC::PlotfileVersion();
901 if (sizeof(typename PC::ParticleType::RealType) == 4)
902 {
903 HdrFile << version_string << "_single" << '\n';
904 }
905 else
906 {
907 HdrFile << version_string << "_double" << '\n';
908 }
909
910 int num_output_real = 0;
911 for (int i = 0; i < rnames_size; ++i) {
912 if (write_real_comp[i]) { ++num_output_real; }
913 }
914
915 int num_output_int = 0;
916 for (int i = 0; i < nic + NStructInt; ++i) {
917 if (write_int_comp[i]) { ++num_output_int; }
918 }
919
920 // AMREX_SPACEDIM and N for sanity checking.
921 HdrFile << AMREX_SPACEDIM << '\n';
922
923 // The number of extra real parameters
924 HdrFile << num_output_real << '\n';
925
926 // Real component names
927 for (int i = 0; i < rnames_size; ++i ) {
928 if (write_real_comp[i]) { HdrFile << real_comp_names[i] << '\n'; }
929 }
930
931 // The number of extra int parameters
932 HdrFile << num_output_int << '\n';
933
934 // int component names
935 for (int i = 0; i < NStructInt + nic; ++i ) {
936 if (write_int_comp[i]) { HdrFile << int_comp_names[i] << '\n'; }
937 }
938
939 bool is_checkpoint_legacy = true; // legacy
940 HdrFile << is_checkpoint_legacy << '\n';
941
942 // The total number of particles.
943 HdrFile << total_np << '\n';
944
945 // The value of nextid that we need to restore on restart.
946 HdrFile << maxnextid << '\n';
947
948 // Then the finest level of the AMR hierarchy.
949 HdrFile << finest_level << '\n';
950
951 // Then the number of grids at each level.
952 for (int lev = 0; lev <= finest_level; lev++) {
953 HdrFile << dms[lev].size() << '\n';
954 }
955
956 for (int lev = 0; lev <= finest_level; lev++)
957 {
958 Vector<int64_t> grid_offset(NProcs, 0);
959 for (int k = 0; k < bas[lev].size(); ++k)
960 {
961 int rank = dms[lev][k];
962 auto info = AsyncOut::GetWriteInfo(rank);
963 HdrFile << info.ifile << ' '
964 << np_per_grid_global[lev][k] << ' '
965 << grid_offset[rank] + rank_start_offset[rank] << '\n';
966 grid_offset[rank] += static_cast<int64_t>(np_per_grid_global[lev][k]*psize);
967 }
968 }
969
970 HdrFile.flush();
971 HdrFile.close();
972 if ( ! HdrFile.good())
973 {
974 amrex::Abort("amrex::WriteBinaryParticleDataAsync(): problem writing HdrFile");
975 }
976 }
977
978 AsyncOut::Wait(); // Wait for my turn
979
980 for (int lev = 0; lev <= finest_level; lev++)
981 {
982 // For a each grid, the tiles it contains
983 std::map<int, Vector<int> > tile_map;
984
985 for (const auto& kv : (*myptiles)[lev])
986 {
987 const int grid = kv.first.first;
988 const int tile = kv.first.second;
989 tile_map[grid].push_back(tile);
990 }
991
992 std::string LevelDir = pdir;
993 if ( ! LevelDir.empty() && LevelDir[LevelDir.size()-1] != '/') { LevelDir += '/'; }
994 LevelDir = amrex::Concatenate(LevelDir.append("Level_"), lev, 1);
995 std::string filePrefix(LevelDir);
996 filePrefix += '/';
997 filePrefix += PC::DataPrefix();
998 auto info = AsyncOut::GetWriteInfo(MyProc);
999 std::string file_name = amrex::Concatenate(filePrefix, info.ifile, 5);
1000 std::ofstream ofs;
1001 ofs.open(file_name.c_str(), (info.ispot == 0) ? (std::ios::binary | std::ios::trunc)
1002 : (std::ios::binary | std::ios::app));
1003
1004 for (int k = 0; k < bas[lev].size(); ++k)
1005 {
1006 int rank = dms[lev][k];
1007 if (rank != MyProc) { continue; }
1008 const int grid = k;
1009 if (np_per_grid_local[lev][grid] == 0) { continue; }
1010
1011 // First write out the integer data in binary.
1012 int num_output_int = 0;
1013 for (int i = 0; i < nic + NStructInt; ++i) {
1014 if (write_int_comp[i]) { ++num_output_int; }
1015 }
1016
1017 const Long iChunkSize = 2 + num_output_int;
1018 Vector<int> istuff(np_per_grid_local[lev][grid]*iChunkSize);
1019 int* iptr = istuff.dataPtr();
1020
1021 for (unsigned i = 0; i < tile_map[grid].size(); i++) {
1022 auto ptile_index = std::make_pair(grid, tile_map[grid][i]);
1023 const auto& pbox = (*myptiles)[lev][ptile_index];
1024 const auto& ptd = pbox.getConstParticleTileData();
1025 for (int pindex = 0; pindex < pbox.numParticles(); ++pindex)
1026 {
1027 const auto& soa = pbox.GetStructOfArrays();
1028
1030 const auto& p = mp(ptd, pindex);
1031 if (p.id() <= 0) { continue; }
1032
1033 // note: for pure SoA particle layouts, we do write the id, cpu and positions as a struct
1034 // for backwards compatibility with readers
1035 if constexpr(!PC::ParticleType::is_soa_particle)
1036 {
1037 // Ints: id, cpu
1038 particle_detail::packParticleIDs(iptr, p, is_checkpoint);
1039 iptr += 2;
1040
1041 // extra AoS Int components
1042 for (int j = 0; j < NStructInt; j++)
1043 {
1044 if (write_int_comp[j])
1045 {
1046 *iptr = p.idata(j);
1047 ++iptr;
1048 }
1049 }
1050 }
1051 else {
1052 uint64_t idcpu = soa.GetIdCPUData()[pindex];
1053 if (is_checkpoint) {
1054 std::int32_t xi, yi;
1055 std::uint32_t xu, yu;
1056 xu = (std::uint32_t)((idcpu & 0xFFFFFFFF00000000LL) >> 32);
1057 yu = (std::uint32_t)( idcpu & 0xFFFFFFFFLL);
1058 std::memcpy(&xi, &xu, sizeof(xu));
1059 std::memcpy(&yi, &yu, sizeof(yu));
1060 *iptr = xi;
1061 iptr += 1;
1062 *iptr = yi;
1063 iptr += 1;
1064 } else {
1065 // Int: id, cpu
1066 *iptr = (int) ParticleIDWrapper(idcpu);
1067 iptr += 1;
1068 *iptr = (int) ParticleCPUWrapper(idcpu);
1069 iptr += 1;
1070 }
1071 }
1072
1073 // extra SoA Ints
1074 const int int_start_offset = 0;
1075 for (int j = int_start_offset; j < nic; j++)
1076 {
1077 if (write_int_comp[NStructInt+j])
1078 {
1079 *iptr = soa.GetIntData(j)[pindex];
1080 ++iptr;
1081 }
1082 }
1083 }
1084 }
1085
1086 writeIntData(istuff.dataPtr(), istuff.size(), ofs);
1087 ofs.flush(); // Some systems require this flush() (probably due to a bug)
1088
1089 // Write the Real data in binary.
1090 int num_output_real = 0;
1091 for (int i = 0; i < rnames_size; ++i) {
1092 if (write_real_comp[i]) { ++num_output_real; }
1093 }
1094
1095 const Long rChunkSize = AMREX_SPACEDIM + num_output_real;
1096 Vector<typename PC::ParticleType::RealType> rstuff(np_per_grid_local[lev][grid]*rChunkSize);
1097 typename PC::ParticleType::RealType* rptr = rstuff.dataPtr();
1098
1099 for (unsigned i = 0; i < tile_map[grid].size(); i++) {
1100 auto ptile_index = std::make_pair(grid, tile_map[grid][i]);
1101 const auto& pbox = (*myptiles)[lev][ptile_index];
1102 const auto& ptd = pbox.getConstParticleTileData();
1103 for (int pindex = 0;
1104 pindex < pbox.numParticles(); ++pindex)
1105 {
1106 const auto& soa = pbox.GetStructOfArrays();
1108 const auto& p = mp(ptd, pindex);
1109
1110 if (p.id() <= 0) { continue; }
1111
1112 if constexpr(!PC::ParticleType::is_soa_particle)
1113 {
1114 // Real: position
1115 for (int j = 0; j < AMREX_SPACEDIM; j++) { rptr[j] = p.pos(j); }
1116 rptr += AMREX_SPACEDIM;
1117
1118 // extra AoS real
1119 for (int j = 0; j < NStructReal; j++)
1120 {
1121 if (write_real_comp[j])
1122 {
1123 *rptr = p.rdata(j);
1124 ++rptr;
1125 }
1126 }
1127 }
1128 else {
1129 // Real: position
1130 for (int j = 0; j < AMREX_SPACEDIM; j++) { rptr[j] = soa.GetRealData(j)[pindex]; }
1131 rptr += AMREX_SPACEDIM;
1132 }
1133
1134 // extra SoA real
1135 const int real_start_offset = PC::ParticleType::is_soa_particle ? AMREX_SPACEDIM : 0; // pure SoA: positions
1136 for (int j = real_start_offset; j < nrc; j++)
1137 {
1138 const int write_comp_offset = PC::ParticleType::is_soa_particle ? AMREX_SPACEDIM : 0; // pure SoA: skip positions
1139 const int write_comp_index = PC::NStructReal+j-write_comp_offset;
1140 if (write_real_comp[write_comp_index])
1141 {
1142 *rptr = (typename PC::ParticleType::RealType) soa.GetRealData(j)[pindex];
1143 ++rptr;
1144 }
1145 }
1146 }
1147 }
1148
1149 if (sizeof(typename PC::ParticleType::RealType) == 4) {
1150 writeFloatData((float*) rstuff.dataPtr(), rstuff.size(), ofs, RD);
1151 }
1152 else if (sizeof(typename PC::ParticleType::RealType) == 8) {
1153 writeDoubleData((double*) rstuff.dataPtr(), rstuff.size(), ofs, RD);
1154 }
1155
1156 ofs.flush(); // Some systems require this flush() (probably due to a bug)
1157 }
1158 }
1159 AsyncOut::Notify(); // Notify others I am done
1160 });
1161}
1162
1163}
1164
1165#ifdef AMREX_USE_HDF5
1167#endif
1168
1169#endif /*AMREX_WRITE_BINARY_PARTICLE_DATA_H*/
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
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:109
static void streamSynchronize() noexcept
Definition AMReX_GpuDevice.cpp:681
Definition AMReX_MFIter.H:57
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:141
int index() const noexcept
The index into the underlying BoxArray of the current FAB.
Definition AMReX_MFIter.H:144
A collection (stored as an array) of FArrayBox objects.
Definition AMReX_MultiFab.H:38
This class encapsulates writing to nfiles.
Definition AMReX_NFiles.H:27
bool ReadyToWrite(bool appendFirst=false)
if appendFirst is true, the first set for this iterator will open the files in append mode
Definition AMReX_NFiles.cpp:204
const std::string & FileName() const
Definition AMReX_NFiles.H:160
Definition AMReX_ParIter.H:113
Parse Parameters From Command Line and Input Files.
Definition AMReX_ParmParse.H:320
int queryAdd(const char *name, T &ref)
If name is found, the value in the ParmParse database will be stored in the ref argument....
Definition AMReX_ParmParse.H:1014
Definition AMReX_GpuAllocators.H:126
Definition AMReX_Reduce.H:249
Type value()
Definition AMReX_Reduce.H:281
Definition AMReX_Reduce.H:364
std::enable_if_t< IsFabArray< MF >::value > eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:441
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:27
T * dataPtr() noexcept
get access to the underlying data pointer
Definition AMReX_Vector.H:46
Long size() const noexcept
Definition AMReX_Vector.H:50
WriteInfo GetWriteInfo(int rank)
Definition AMReX_AsyncOut.cpp:72
void Wait()
Definition AMReX_AsyncOut.cpp:112
void Notify()
Definition AMReX_AsyncOut.cpp:127
void Submit(std::function< void()> &&a_f)
Definition AMReX_AsyncOut.cpp:95
bool Remove(std::string const &filename)
Definition AMReX_FileSystem.cpp:190
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void * memcpy(void *dest, const void *src, std::size_t count)
Definition AMReX_GpuUtility.H:220
void copyAsync(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
A host-to-device copy routine. Note this is just a wrapper around memcpy, so it assumes contiguous st...
Definition AMReX_GpuContainers.H:233
static constexpr DeviceToHost deviceToHost
Definition AMReX_GpuContainers.H:99
static constexpr HostToDevice hostToDevice
Definition AMReX_GpuContainers.H:98
void ReduceIntSum(int &)
Integer sum reduction.
Definition AMReX_ParallelDescriptor.cpp:1255
int MyProc() noexcept
return the rank number local to the current Parallel Context
Definition AMReX_ParallelDescriptor.H:125
void ReduceLongMax(Long &)
Long max reduction.
Definition AMReX_ParallelDescriptor.cpp:1227
void ReduceLongSum(Long &)
Long sum reduction.
Definition AMReX_ParallelDescriptor.cpp:1226
int NProcs() noexcept
return the number of MPI ranks local to the current Parallel Context
Definition AMReX_ParallelDescriptor.H:243
void GatherLayoutDataToVector(const LayoutData< T > &sendbuf, Vector< T > &recvbuf, int root)
Gather LayoutData values to a vector on root.
Definition AMReX_ParallelDescriptor.H:1211
int IOProcessorNumber() noexcept
Definition AMReX_ParallelDescriptor.H:266
void Barrier(const std::string &)
Definition AMReX_ParallelDescriptor.cpp:1205
bool IOProcessor() noexcept
Is this CPU the I/O Processor? To get the rank number, call IOProcessorNumber()
Definition AMReX_ParallelDescriptor.H:275
T ExclusiveSum(N n, T const *in, T *out, RetSum a_ret_sum=retSum)
Definition AMReX_Scan.H:1229
static constexpr RetSum retSum
Definition AMReX_Scan.H:29
std::size_t PSizeInFile(const Vector< int > &wrc, const Vector< int > &wic)
Definition AMReX_WriteBinaryParticleData.H:24
std::enable_if_t< RunOnGpu< typename Container< int, Allocator >::allocator_type >::value > fillFlags(Container< int, Allocator > &pflags, const PTile &ptile, F const &f)
Definition AMReX_WriteBinaryParticleData.H:36
std::enable_if_t< RunOnGpu< typename PC::template AllocatorType< int > >::value, void > packIOData(Vector< int > &idata, Vector< ParticleReal > &rdata, const PC &pc, int lev, int grid, const Vector< int > &write_real_comp, const Vector< int > &write_int_comp, const Vector< std::map< std::pair< int, int >, typename PC::IntVector > > &particle_io_flags, const Vector< int > &tiles, int np, bool is_checkpoint)
Definition AMReX_WriteBinaryParticleData.H:173
std::enable_if_t< RunOnGpu< typename Container< int, Allocator >::allocator_type >::value, amrex::Long > countFlags(const Vector< std::map< std::pair< int, int >, Container< int, Allocator > > > &particle_io_flags, const PC &pc)
Definition AMReX_WriteBinaryParticleData.H:78
AMREX_GPU_HOST_DEVICE void packParticleIDs(I *idata, const P &p, bool is_checkpoint) noexcept
Definition AMReX_WriteBinaryParticleData.H:154
Definition AMReX_Amr.cpp:49
void writeIntData(const From *data, std::size_t size, std::ostream &os, const amrex::IntDescriptor &id)
Definition AMReX_IntConv.H:23
void WriteBinaryParticleDataSync(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, F const &f, bool is_checkpoint)
Definition AMReX_WriteBinaryParticleData.H:394
void FileOpenFailed(const std::string &file)
Output a message and abort when couldn't open the file.
Definition AMReX_Utility.cpp:131
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:191
void writeFloatData(const float *data, std::size_t size, std::ostream &os, const RealDescriptor &rd=FPC::Native32RealDescriptor())
Definition AMReX_VectorIO.cpp:114
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 end(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1890
std::string Concatenate(const std::string &root, int num, int mindigits)
Returns rootNNNN where NNNN == num.
Definition AMReX_String.cpp:34
Index filterParticles(DstTile &dst, const SrcTile &src, const Index *mask) noexcept
Conditionally copy particles from src to dst based on the value of mask.
Definition AMReX_ParticleTransformation.H:325
void CreateDirectoryFailed(const std::string &dir)
Output a message and abort when couldn't create the directory.
Definition AMReX_Utility.cpp:123
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
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:127
void writeDoubleData(const double *data, std::size_t size, std::ostream &os, const RealDescriptor &rd=FPC::Native64RealDescriptor())
Definition AMReX_VectorIO.cpp:126
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 begin(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1881
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:230
const int[]
Definition AMReX_BLProfiler.cpp:1664
void WriteBinaryParticleDataAsync(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, bool is_checkpoint)
Definition AMReX_WriteBinaryParticleData.H:686
AMREX_ATTRIBUTE_FLATTEN_FOR void ParallelForRNG(T n, L const &f) noexcept
Definition AMReX_GpuLaunchFunctsC.H:1221
Test if a given type T is callable with arguments of type Args...
Definition AMReX_TypeTraits.H:201
Definition AMReX_WriteBinaryParticleData.H:12
AMREX_GPU_HOST_DEVICE int operator()(const SrcData &src, int i) const noexcept
Definition AMReX_WriteBinaryParticleData.H:15
FabArray memory allocation information.
Definition AMReX_FabArray.H:66
MFInfo & SetAlloc(bool a) noexcept
Definition AMReX_FabArray.H:73
Definition AMReX_Particle.H:140
Definition AMReX_Particle.H:37
Definition AMReX_ParticleTile.H:702
Definition AMReX_RandomEngine.H:57
Definition AMReX_MakeParticle.H:18