1#ifndef AMREX_WRITE_BINARY_PARTICLE_DATA_H
2#define AMREX_WRITE_BINARY_PARTICLE_DATA_H
3#include <AMReX_Config.H>
14 template <
typename SrcData>
16 int operator() (
const SrcData& src,
int i)
const noexcept
18 return (src.id(i).is_valid());
23namespace particle_detail {
25template <
typename ParticleReal>
26std::size_t PSizeInFile (
const Vector<int>& wrc,
const Vector<int>& wic)
28 std::size_t rsize =
sizeof(ParticleReal)*std::accumulate(wrc.begin(), wrc.end(), 0);
29 std::size_t isize =
sizeof(int)*std::accumulate(wic.begin(), wic.end(), 0);
30 return rsize + isize + AMREX_SPACEDIM*
sizeof(ParticleReal) + 2*
sizeof(
int);
33template <
class Container,
37fillFlagsGpu (Container& pflags,
const PTile& ptile, F
const& f)
39 const auto& ptd = ptile.getConstParticleTileData();
40 const auto np = ptile.numParticles();
42 auto flag_ptr = pflags.data();
46 const auto p = ptd.getSuperParticle(k);
48 if constexpr (IsCallable<
F,
decltype(p),RandomEngine>::value) {
49 flag_ptr[k] = f(p,engine);
50 }
else if constexpr (IsCallable<
F,
decltype(p)>::value) {
52 }
else if constexpr (IsCallable<
F,
decltype(ptd),
int,RandomEngine>::value) {
53 flag_ptr[k] = f(ptd,k,engine);
55 flag_ptr[k] = f(ptd,k);
60template <
class Container,
64fillFlagsCpu (Container& pflags,
const PTile& ptile, F
const& f)
66 const auto& ptd = ptile.getConstParticleTileData();
67 const auto np = ptile.numParticles();
69 auto flag_ptr = pflags.data();
70 for (
int k = 0; k < np; ++k) {
71 const auto p = ptd.getSuperParticle(k);
72 if constexpr (IsCallable<
F,
decltype(p),RandomEngine>::value) {
74 }
else if constexpr (IsCallable<
F,
decltype(p)>::value) {
76 }
else if constexpr (IsCallable<
F,
decltype(ptd),
int,RandomEngine>::value) {
79 flag_ptr[k] = f(ptd,k);
84template <
template <
class,
class>
class Container,
89fillFlags (Container<int, Allocator>& pflags,
const PTile& ptile, F
const& f)
91 if constexpr (IsPolymorphicArenaAllocator<Allocator>::value) {
92 if (pflags.arena()->isManaged() || pflags.arena()->isDevice()) {
93 fillFlagsGpu(pflags, ptile, f);
95 fillFlagsCpu(pflags, ptile, f);
98 if constexpr (RunOnGpu<Allocator>::value) {
99 fillFlagsGpu(pflags, ptile, f);
101 fillFlagsCpu(pflags, ptile, f);
106template <
class Container,
class PC>
108countFlagsGpu (
const Vector<std::map<std::pair<int,int>,Container>>& particle_io_flags,
const PC& pc)
110 ReduceOps<ReduceOpSum> reduce_op;
111 ReduceData<Long> reduce_data(reduce_op);
112 using ReduceTuple =
typename decltype(reduce_data)::Type;
114 for (
int lev = 0; lev < pc.GetParticles().size(); lev++)
116 const auto& pmap = pc.GetParticles(lev);
117 for (
const auto& kv : pmap)
119 const auto& pflags = particle_io_flags[lev].at(kv.first);
120 const auto flag_ptr = pflags.data();
121 reduce_op.eval(pflags.size(), reduce_data,
124 return flag_ptr[i] ? 1 : 0;
128 ReduceTuple hv = reduce_data.value(reduce_op);
129 return amrex::get<0>(hv);
132template <
class Container>
134countFlagsGpu (
const Container& pflags)
136 ReduceOps<ReduceOpSum> reduce_op;
137 ReduceData<Long> reduce_data(reduce_op);
138 using ReduceTuple =
typename decltype(reduce_data)::Type;
140 const auto flag_ptr = pflags.data();
141 reduce_op.eval(pflags.size(), reduce_data,
144 return flag_ptr[i] ? 1 : 0;
146 ReduceTuple hv = reduce_data.value(reduce_op);
147 return amrex::get<0>(hv);
150template <
class Container,
class PC>
152countFlagsCpu (
const Vector<std::map<std::pair<int,int>,Container>>& particle_io_flags,
const PC& pc)
155 for (
int lev = 0; lev < pc.GetParticles().size(); lev++)
157 const auto& pmap = pc.GetParticles(lev);
158 for (
const auto& kv : pmap)
160 const auto& pflags = particle_io_flags[lev].at(kv.first);
161 for (
int k = 0; k < kv.second.numParticles(); ++k)
163 if (pflags[k]) { nparticles++; }
170template <
class Container>
172countFlagsCpu (
const Container& pflags)
175 for (std::size_t k = 0; k < pflags.size(); ++k)
177 if (pflags[k]) { nparticles++; }
182template <
template <
class,
class>
class Container,
class Allocator,
class PC>
184countFlags (
const Vector<std::map<std::pair<int,int>,Container<int,Allocator>>>& particle_io_flags,
const PC& pc)
186 if constexpr (IsPolymorphicArenaAllocator<Allocator>::value) {
187 if (pc.arena()->isManaged() || pc.arena()->isDevice()) {
188 return countFlagsGpu(particle_io_flags, pc);
190 return countFlagsCpu(particle_io_flags, pc);
193 if constexpr (RunOnGpu<Allocator>::value) {
194 return countFlagsGpu(particle_io_flags, pc);
196 return countFlagsCpu(particle_io_flags, pc);
201template <
template <
class,
class>
class Container,
class Allocator>
203countFlags (
const Container<int,Allocator>& pflags)
205 if constexpr (IsPolymorphicArenaAllocator<Allocator>::value) {
206 if (pflags.arena()->isManaged() || pflags.arena()->isDevice()) {
207 return countFlagsGpu(pflags);
209 return countFlagsCpu(pflags);
212 if constexpr (RunOnGpu<Allocator>::value) {
213 return countFlagsGpu(pflags);
215 return countFlagsCpu(pflags);
222void packParticleIDs (I* idata,
const std::uint64_t idcpu,
bool is_checkpoint)
noexcept
226 std::uint32_t xu, yu;
227 xu = (std::uint32_t)((idcpu & 0xFFFFFFFF00000000LL) >> 32);
228 yu = (std::uint32_t)( idcpu & 0xFFFFFFFFLL);
234 idata[0] = ConstParticleIDWrapper{idcpu};
235 idata[1] = ConstParticleCPUWrapper{idcpu};
241rPackParticleData (
const PTD& ptd,
int idx, std::remove_const_t<typename PTD::RealType> * rdata_ptr,
242 const int * write_real_comp)
244 std::size_t rout_index = 0;
246 if constexpr (!PTD::ParticleType::is_rtsoa_particle) {
247 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
248 rdata_ptr[rout_index] = ptd.pos(j, idx);
252 if constexpr (!PTD::ParticleType::is_soa_particle) {
253 const auto& p = ptd[idx];
255 for (
int j = 0; j < PTD::ParticleType::NReal; ++j) {
256 if (write_real_comp[j]) {
257 rdata_ptr[rout_index] = p.rdata(j);
263 constexpr int real_start_offset = PTD::ParticleType::is_soa_particle ? AMREX_SPACEDIM : 0;
265 if constexpr (PTD::NAR > 0) {
266 for (
int j = real_start_offset; j < PTD::NAR; ++j) {
267 if (write_real_comp[PTD::ParticleType::NReal + j - real_start_offset]) {
268 rdata_ptr[rout_index] = ptd.rdata(j)[idx];
274 for (
int j = 0; j < ptd.m_num_runtime_real; ++j) {
275 if (write_real_comp[PTD::ParticleType::NReal + PTD::NAR + j - real_start_offset]) {
276 rdata_ptr[rout_index] = ptd.m_runtime_rdata[j][idx];
281 for (
int j = 0; j < ptd.m_n_real; ++j) {
282 if ((j < AMREX_SPACEDIM) || write_real_comp[j - AMREX_SPACEDIM]) {
283 rdata_ptr[rout_index] = ptd.rdata(j)[idx];
292iPackParticleData (
const PTD& ptd,
int idx, std::remove_const_t<typename PTD::IntType> * idata_ptr,
293 const int * write_int_comp,
bool is_checkpoint)
295 std::size_t iout_index = 0;
297 packParticleIDs(&idata_ptr[iout_index], ptd.idcpu(idx), is_checkpoint);
300 if constexpr (!PTD::ParticleType::is_rtsoa_particle) {
301 if constexpr (!PTD::ParticleType::is_soa_particle) {
302 const auto& p = ptd[idx];
304 for (
int j = 0; j < PTD::ParticleType::NInt; ++j) {
305 if (write_int_comp[j]) {
306 idata_ptr[iout_index] = p.idata(j);
312 if constexpr (PTD::NAI > 0) {
313 for (
int j = 0; j < PTD::NAI; ++j) {
314 if (write_int_comp[PTD::ParticleType::NInt + j]) {
315 idata_ptr[iout_index] = ptd.idata(j)[idx];
321 for (
int j = 0; j < ptd.m_num_runtime_int; ++j) {
322 if (write_int_comp[PTD::ParticleType::NInt + PTD::NAI + j]) {
323 idata_ptr[iout_index] = ptd.m_runtime_idata[j][idx];
328 for (
int j = 0; j < ptd.m_n_int; ++j) {
329 if (write_int_comp[j]) {
330 idata_ptr[iout_index] = ptd.idata(j)[idx];
339packIODataGpu (Vector<int>& idata, Vector<ParticleReal>& rdata,
const PC& pc,
int lev,
int grid,
340 const Vector<int>& write_real_comp,
const Vector<int>& write_int_comp,
341 const Vector<std::map<std::pair<int, int>,
typename PC::FlagsVector>>& particle_io_flags,
342 const Vector<int>& tiles,
int np,
bool is_checkpoint)
344 int num_output_int = 0;
345 for (
int i = 0; i < pc.NumIntComps() + PC::NStructInt; ++i) {
346 if (write_int_comp[i]) { ++num_output_int; }
349 const Long iChunkSize = 2 + num_output_int;
350 idata.resize(np*iChunkSize);
352 int num_output_real = 0;
353 for (
int i : write_real_comp) {
354 if (i) { ++num_output_real; }
357 const Long rChunkSize = AMREX_SPACEDIM + num_output_real;
358 rdata.resize(np*rChunkSize);
360 Gpu::DeviceVector<int> write_int_comp_d(write_int_comp.size());
361 Gpu::DeviceVector<int> write_real_comp_d(write_real_comp.size());
362 Gpu::copyAsync(Gpu::hostToDevice, write_int_comp.begin(), write_int_comp.end(),
363 write_int_comp_d.begin());
364 Gpu::copyAsync(Gpu::hostToDevice, write_real_comp.begin(), write_real_comp.end(),
365 write_real_comp_d.begin());
367 const auto* write_int_comp_d_ptr = write_int_comp_d.data();
368 const auto* write_real_comp_d_ptr = write_real_comp_d.data();
370 std::size_t poffset = 0;
371 for (
int tile : tiles) {
372 const auto& ptile = pc.ParticlesAt(lev, grid, tile);
373 const auto& pflags = particle_io_flags[lev].at(std::make_pair(grid, tile));
374 int np_tile = ptile.numParticles();
375 Gpu::DeviceVector<int> offsets(np_tile);
376 int num_copies = Scan::ExclusiveSum(np_tile, pflags.begin(), offsets.begin(), Scan::retSum);
378 Gpu::DeviceVector<int> idata_d(num_copies*iChunkSize);
379 Gpu::DeviceVector<ParticleReal> rdata_d(num_copies*rChunkSize);
381 const auto* flag_ptr = pflags.data();
382 const auto* offset_ptr = offsets.data();
384 auto* idata_d_ptr = idata_d.data();
385 auto* rdata_d_ptr = rdata_d.data();
387 const auto& ptd = ptile.getConstParticleTileData();
391 if (flag_ptr[pindex]) {
392 const int out_indx = offset_ptr[pindex];
393 iPackParticleData(ptd, pindex, idata_d_ptr + out_indx * iChunkSize,
394 write_int_comp_d_ptr, is_checkpoint);
396 rPackParticleData(ptd, pindex, rdata_d_ptr + out_indx * rChunkSize,
397 write_real_comp_d_ptr);
401 Gpu::copyAsync(Gpu::deviceToHost, idata_d.begin(), idata_d.end(),
402 idata.begin() +
static_cast<Long>(poffset * iChunkSize));
403 Gpu::copyAsync(Gpu::deviceToHost, rdata_d.begin(), rdata_d.end(),
404 rdata.begin() +
static_cast<Long>(poffset * rChunkSize));
405 Gpu::Device::streamSynchronize();
407 poffset += num_copies;
413packIODataCpu (Vector<int>& idata, Vector<ParticleReal>& rdata,
const PC& pc,
int lev,
int grid,
414 const Vector<int>& write_real_comp,
const Vector<int>& write_int_comp,
415 const Vector<std::map<std::pair<int, int>,
typename PC::FlagsVector>>& particle_io_flags,
416 const Vector<int>& tiles,
int np,
bool is_checkpoint)
418 int num_output_int = 0;
419 for (
int i = 0; i < pc.NumIntComps() + PC::NStructInt; ++i) {
420 if (write_int_comp[i]) { ++num_output_int; }
423 const Long iChunkSize = 2 + num_output_int;
424 idata.resize(np*iChunkSize);
426 int num_output_real = 0;
427 for (
int i : write_real_comp) {
428 if (i) { ++num_output_real; }
431 const Long rChunkSize = AMREX_SPACEDIM + num_output_real;
432 rdata.resize(np*rChunkSize);
434 int* iptr = idata.dataPtr();
436 for (
int tile : tiles) {
437 const auto& ptile = pc.ParticlesAt(lev, grid, tile);
438 const auto& pflags = particle_io_flags[lev].at(std::make_pair(grid, tile));
439 const auto& ptd = ptile.getConstParticleTileData();
441 for (
int pindex = 0; pindex < ptile.numParticles(); ++pindex) {
442 if (pflags[pindex]) {
443 iPackParticleData(ptd, pindex, iptr,
444 write_int_comp.dataPtr(), is_checkpoint);
447 rPackParticleData(ptd, pindex, rptr,
448 write_real_comp.dataPtr());
457packIOData (Vector<int>& idata, Vector<ParticleReal>& rdata,
const PC& pc,
int lev,
int grid,
458 const Vector<int>& write_real_comp,
const Vector<int>& write_int_comp,
459 const Vector<std::map<std::pair<int, int>,
typename PC::FlagsVector>>& particle_io_flags,
460 const Vector<int>& tiles,
int np,
bool is_checkpoint)
462 if constexpr (IsPolymorphicArenaAllocator<typename PC::FlagsVector::allocator_type>::value) {
463 if (pc.arena()->isManaged() || pc.arena()->isDevice()) {
464 packIODataGpu(idata, rdata, pc, lev, grid, write_real_comp, write_int_comp,
465 particle_io_flags, tiles, np, is_checkpoint);
467 packIODataCpu(idata, rdata, pc, lev, grid, write_real_comp, write_int_comp,
468 particle_io_flags, tiles, np, is_checkpoint);
471 if constexpr (RunOnGpu<typename PC::FlagsVector::allocator_type>::value) {
472 packIODataGpu(idata, rdata, pc, lev, grid, write_real_comp, write_int_comp,
473 particle_io_flags, tiles, np, is_checkpoint);
475 packIODataCpu(idata, rdata, pc, lev, grid, write_real_comp, write_int_comp,
476 particle_io_flags, tiles, np, is_checkpoint);
484template <class PC, class F, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
486 const std::string& dir,
const std::string& name,
491 F const& f,
bool is_checkpoint)
496 AMREX_ASSERT(
sizeof(
typename PC::ParticleType::RealType) == 4 ||
497 sizeof(
typename PC::ParticleType::RealType) == 8);
499 constexpr int NStructReal = PC::NStructReal;
500 constexpr int NStructInt = PC::NStructInt;
505 if constexpr(PC::ParticleType::is_soa_particle) {
512 std::string pdir = dir;
513 if ( ! pdir.empty() && pdir[pdir.size()-1] !=
'/') { pdir +=
'/'; }
516 if ( ! pc.GetLevelDirectoriesCreated()) {
527 std::ofstream HdrFile;
534 particle_io_flags(pc.GetParticles().size());
536 for (
int lev = 0; lev < pc.GetParticles().size(); lev++)
538 const auto& pmap = pc.GetParticles(lev);
539 for (
const auto& kv : pmap)
541 auto& flags = particle_io_flags[lev][kv.first];
542 if constexpr (PC::has_polymorphic_allocator) {
543 flags.setArena(pc.arena());
545 particle_detail::fillFlags(flags, kv.second, f);
551 if(pc.GetUsePrePost())
553 nparticles = pc.GetNParticlesPrePost();
554 maxnextid = pc.GetMaxNextIDPrePost();
558 nparticles = particle_detail::countFlags(particle_io_flags, pc);
559 maxnextid = PC::ParticleType::NextID();
561 PC::ParticleType::NextID(maxnextid);
567 std::string HdrFileName = pdir;
569 if ( ! HdrFileName.empty() && HdrFileName[HdrFileName.size()-1] !=
'/') {
573 HdrFileName +=
"Header";
574 pc.HdrFileNamePrePost = HdrFileName;
576 HdrFile.open(HdrFileName.c_str(), std::ios::out|std::ios::trunc);
585 std::string version_string = is_checkpoint ? PC::CheckpointVersion() : PC::PlotfileVersion();
586 if (
sizeof(
typename PC::ParticleType::RealType) == 4)
588 HdrFile << version_string <<
"_single" <<
'\n';
592 HdrFile << version_string <<
"_double" <<
'\n';
595 int num_output_real = 0;
596 for (
int i : write_real_comp) {
597 if (i) { ++num_output_real; }
600 int num_output_int = 0;
601 for (
int i = 0; i < pc.NumIntComps() + NStructInt; ++i) {
602 if (write_int_comp[i]) { ++num_output_int; }
606 HdrFile << AMREX_SPACEDIM <<
'\n';
609 HdrFile << num_output_real <<
'\n';
612 for (
int i = 0; i < (
int) real_comp_names.
size(); ++i ) {
613 if (write_real_comp[i]) { HdrFile << real_comp_names[i] <<
'\n'; }
617 HdrFile << num_output_int <<
'\n';
620 for (
int i = 0; i < NStructInt + pc.NumIntComps(); ++i ) {
621 if (write_int_comp[i]) { HdrFile << int_comp_names[i] <<
'\n'; }
624 bool is_checkpoint_legacy =
true;
625 HdrFile << is_checkpoint_legacy <<
'\n';
628 HdrFile << nparticles <<
'\n';
631 HdrFile << maxnextid <<
'\n';
634 HdrFile << pc.finestLevel() <<
'\n';
637 for (
int lev = 0; lev <= pc.finestLevel(); lev++) {
638 HdrFile << pc.ParticleBoxArray(lev).
size() <<
'\n';
648 if(nOutFiles == -1) { nOutFiles = NProcs; }
649 nOutFiles = std::max(1, std::min(nOutFiles,NProcs));
650 pc.nOutFilesPrePost = nOutFiles;
652 for (
int lev = 0; lev <= pc.finestLevel(); lev++)
657 gotsome = (pc.nParticlesAtLevelPrePost[lev] > 0);
661 gotsome = (pc.NumberOfParticlesAtLevel(lev) > 0);
665 std::string LevelDir = pdir;
669 if ( ! LevelDir.empty() && LevelDir[LevelDir.size()-1] !=
'/') { LevelDir +=
'/'; }
673 if ( ! pc.GetLevelDirectoriesCreated())
686 std::string HeaderFileName = LevelDir;
687 HeaderFileName +=
"/Particle_H";
688 std::ofstream ParticleHeader(HeaderFileName);
690 pc.ParticleBoxArray(lev).writeOn(ParticleHeader);
691 ParticleHeader <<
'\n';
693 ParticleHeader.flush();
694 ParticleHeader.close();
699 MultiFab state(pc.ParticleBoxArray(lev),
700 pc.ParticleDistributionMap(lev),
709 std::string filePrefix(LevelDir);
711 filePrefix += PC::DataPrefix();
713 pc.filePrefixPrePost[lev] = filePrefix;
715 bool groupSets(
false), setBuf(
true);
721 auto& myStream = (std::ofstream&) nfi.Stream();
722 pc.WriteParticles(lev, myStream, nfi.FileNumber(), which, count, where,
723 write_real_comp, write_int_comp, particle_io_flags, is_checkpoint);
727 pc.whichPrePost[lev] = which;
728 pc.countPrePost[lev] = count;
729 pc.wherePrePost[lev] = where;
739 if(pc.GetUsePrePost()) {
742 for (
int j = 0; j < state.
size(); j++)
744 HdrFile << which[j] <<
' ' << count[j] <<
' ' << where[j] <<
'\n';
747 if (gotsome && pc.doUnlink)
752 for (
int i = 0, N=
static_cast<int>(count.
size()); i < N; i++) {
753 cnt[which[i]] += count[i];
756 for (
int i = 0, N=
static_cast<int>(cnt.
size()); i < N; i++)
776 if ( ! HdrFile.good())
778 amrex::Abort(
"amrex::WriteBinaryParticleDataSync(): problem writing HdrFile");
783template <class PC, std::enable_if_t<IsParticleContainer<PC>::value,
int> foo = 0>
785 const std::string& dir,
const std::string& name,
794 AMREX_ASSERT(
sizeof(
typename PC::ParticleType::RealType) == 4 ||
795 sizeof(
typename PC::ParticleType::RealType) == 8);
797 constexpr int NStructReal = PC::NStructReal;
798 constexpr int NStructInt = PC::NStructInt;
799 constexpr int NArrayReal = PC::NArrayReal;
800 constexpr int NArrayInt = PC::NArrayInt;
804 const int IOProcNumber = NProcs - 1;
806 if constexpr(PC::ParticleType::is_soa_particle) {
814 for (
int lev = 0; lev <= pc.finestLevel(); lev++)
816 np_per_grid_local[lev].define(pc.ParticleBoxArray(lev), pc.ParticleDistributionMap(lev));
817 using ParIter =
typename PC::ParConstIterType;
820 int gid = pti.
index();
821 const auto& ptile = pc.ParticlesAt(lev, pti);
822 const auto& ptd = ptile.getConstParticleTileData();
823 const int np = ptile.numParticles();
827 using ReduceTuple =
typename decltype(reduce_data)::Type;
829 reduce_op.
eval(np, reduce_data,
832 return (ptd.id(i).is_valid()) ? 1 : 0;
835 int np_valid = amrex::get<0>(reduce_data.
value(reduce_op));
836 np_per_grid_local[lev][gid] += np_valid;
843 for (
int lev = 0; lev <= pc.finestLevel(); lev++)
845 np_per_grid_global[lev].resize(np_per_grid_local[lev].size());
847 np_per_grid_global[lev],
849 np_per_level[lev] = std::accumulate(np_per_grid_global[lev].
begin(),
850 np_per_grid_global[lev].
end(), 0L);
851 total_np += np_per_level[lev];
854 std::string pdir = dir;
855 if ( ! pdir.empty() && pdir[pdir.size()-1] !=
'/') { pdir +=
'/'; }
858 if (MyProc == IOProcNumber)
860 if ( ! pc.GetLevelDirectoriesCreated())
868 for (
int lev = 0; lev <= pc.finestLevel(); lev++)
870 std::string LevelDir = pdir;
871 bool gotsome = np_per_level[lev];
875 if ( ! LevelDir.empty() && LevelDir[LevelDir.size()-1] !=
'/') { LevelDir +=
'/'; }
879 if ( ! pc.GetLevelDirectoriesCreated())
887 std::string HeaderFileName = LevelDir;
888 HeaderFileName +=
"/Particle_H";
889 std::ofstream ParticleHeader(HeaderFileName);
891 pc.ParticleBoxArray(lev).writeOn(ParticleHeader);
892 ParticleHeader <<
'\n';
894 ParticleHeader.flush();
895 ParticleHeader.close();
901 Long maxnextid = PC::ParticleType::NextID();
905 std::size_t psize = particle_detail::PSizeInFile<ParticleReal>(write_real_comp, write_int_comp);
907 if (MyProc == IOProcNumber)
909 for (
int lev = 0; lev <= pc.finestLevel(); lev++)
911 for (
int k = 0; k < pc.ParticleBoxArray(lev).size(); ++k)
913 int rank = pc.ParticleDistributionMap(lev)[k];
914 np_on_rank[rank] += np_per_grid_global[lev][k];
918 for (
int ip = 0; ip < NProcs; ++ip)
921 rank_start_offset[ip] = (info.ispot == 0) ? 0 :
static_cast<int64_t
>(rank_start_offset[ip-1] + np_on_rank[ip-1]*psize);
926 using PinnedPTile = std::conditional_t<
928 typename PC::ParticleTileType,
931 auto myptiles = std::make_shared<Vector<std::map<std::pair<int, int>,PinnedPTile> > >();
932 myptiles->
resize(pc.finestLevel()+1);
933 for (
int lev = 0; lev <= pc.finestLevel(); lev++)
937 auto& new_ptile = (*myptiles)[lev][std::make_pair(mfi.index(),
938 mfi.LocalTileIndex())];
940 if (np_per_grid_local[lev][mfi.index()] > 0)
942 const auto& ptile = pc.ParticlesAt(lev, mfi);
944 const auto np = np_per_grid_local[lev][mfi.index()];
946 const auto runtime_real_comps = ptile.NumRuntimeRealComps();
947 const auto runtime_int_comps = ptile.NumRuntimeIntComps();
949 new_ptile.define(runtime_real_comps, runtime_int_comps,
952 new_ptile.resize(np);
959 int finest_level = pc.finestLevel();
962 for (
int lev = 0; lev <= pc.finestLevel(); lev++)
964 bas.push_back(pc.ParticleBoxArray(lev));
965 dms.push_back(pc.ParticleDistributionMap(lev));
968 int nic = pc.NumIntComps();
969 int rnames_size = (
int) real_comp_names.
size();
971 auto RD = pc.ParticleRealDescriptor;
974#
if defined(__GNUC__) && (__GNUC__ == 8) && (__GNUC_MINOR__ == 1)
978 if (MyProc == IOProcNumber)
980 std::string HdrFileName = pdir;
981 std::ofstream HdrFile;
983 if ( ! HdrFileName.empty() && HdrFileName[HdrFileName.size()-1] !=
'/') {
987 HdrFileName +=
"Header";
989 HdrFile.open(HdrFileName.c_str(), std::ios::out|std::ios::trunc);
993 std::string version_string = is_checkpoint ? PC::CheckpointVersion() : PC::PlotfileVersion();
994 if (
sizeof(
typename PC::ParticleType::RealType) == 4)
996 HdrFile << version_string <<
"_single" <<
'\n';
1000 HdrFile << version_string <<
"_double" <<
'\n';
1003 int num_output_real = 0;
1004 for (
int i = 0; i < rnames_size; ++i) {
1005 if (write_real_comp[i]) { ++num_output_real; }
1008 int num_output_int = 0;
1009 for (
int i = 0; i < nic + NStructInt; ++i) {
1010 if (write_int_comp[i]) { ++num_output_int; }
1014 HdrFile << AMREX_SPACEDIM <<
'\n';
1017 HdrFile << num_output_real <<
'\n';
1020 for (
int i = 0; i < rnames_size; ++i ) {
1021 if (write_real_comp[i]) { HdrFile << real_comp_names[i] <<
'\n'; }
1025 HdrFile << num_output_int <<
'\n';
1028 for (
int i = 0; i < NStructInt + nic; ++i ) {
1029 if (write_int_comp[i]) { HdrFile << int_comp_names[i] <<
'\n'; }
1032 bool is_checkpoint_legacy =
true;
1033 HdrFile << is_checkpoint_legacy <<
'\n';
1036 HdrFile << total_np <<
'\n';
1039 HdrFile << maxnextid <<
'\n';
1042 HdrFile << finest_level <<
'\n';
1045 for (
int lev = 0; lev <= finest_level; lev++) {
1046 HdrFile << dms[lev].
size() <<
'\n';
1049 for (
int lev = 0; lev <= finest_level; lev++)
1052 for (
int k = 0; k < bas[lev].
size(); ++k)
1054 int rank = dms[lev][k];
1056 HdrFile << info.ifile <<
' '
1057 << np_per_grid_global[lev][k] <<
' '
1058 << grid_offset[rank] + rank_start_offset[rank] <<
'\n';
1059 grid_offset[rank] +=
static_cast<int64_t
>(np_per_grid_global[lev][k]*psize);
1065 if ( ! HdrFile.good())
1067 amrex::Abort(
"amrex::WriteBinaryParticleDataAsync(): problem writing HdrFile");
1073 for (
int lev = 0; lev <= finest_level; lev++)
1076 std::map<int, Vector<int> > tile_map;
1078 for (
const auto& kv : (*myptiles)[lev])
1080 const int grid = kv.first.first;
1081 const int tile = kv.first.second;
1082 tile_map[grid].push_back(tile);
1085 std::string LevelDir = pdir;
1086 if ( ! LevelDir.empty() && LevelDir[LevelDir.size()-1] !=
'/') { LevelDir +=
'/'; }
1088 std::string filePrefix(LevelDir);
1090 filePrefix += PC::DataPrefix();
1094 ofs.open(file_name.c_str(), (info.ispot == 0) ? (std::ios::binary | std::ios::trunc)
1095 : (std::ios::binary | std::ios::app));
1097 for (
int k = 0; k < bas[lev].
size(); ++k)
1099 int rank = dms[lev][k];
1100 if (rank != MyProc) {
continue; }
1102 if (np_per_grid_local[lev][grid] == 0) {
continue; }
1105 int num_output_int = 0;
1106 for (
int i = 0; i < nic + NStructInt; ++i) {
1107 if (write_int_comp[i]) { ++num_output_int; }
1110 const Long iChunkSize = 2 + num_output_int;
1111 Vector<int> istuff(np_per_grid_local[lev][grid]*iChunkSize);
1114 for (
unsigned i = 0; i < tile_map[grid].size(); i++) {
1115 auto ptile_index = std::make_pair(grid, tile_map[grid][i]);
1116 const auto& pbox = (*myptiles)[lev][ptile_index];
1117 const auto& ptd = pbox.getConstParticleTileData();
1118 for (
int pindex = 0; pindex < pbox.numParticles(); ++pindex)
1120 if (!ptd.id(pindex).is_valid()) {
continue; }
1122 particle_detail::iPackParticleData(ptd, pindex, iptr,
1123 write_int_comp.
dataPtr(), is_checkpoint);
1132 int num_output_real = 0;
1133 for (
int i = 0; i < rnames_size; ++i) {
1134 if (write_real_comp[i]) { ++num_output_real; }
1137 const Long rChunkSize = AMREX_SPACEDIM + num_output_real;
1139 typename PC::ParticleType::RealType* rptr = rstuff.
dataPtr();
1141 for (
unsigned i = 0; i < tile_map[grid].size(); i++) {
1142 auto ptile_index = std::make_pair(grid, tile_map[grid][i]);
1143 const auto& pbox = (*myptiles)[lev][ptile_index];
1144 const auto& ptd = pbox.getConstParticleTileData();
1145 for (
int pindex = 0; pindex < pbox.numParticles(); ++pindex)
1147 if (!ptd.id(pindex).is_valid()) {
continue; }
1149 particle_detail::rPackParticleData(ptd, pindex, rptr,
1155 if (
sizeof(
typename PC::ParticleType::RealType) == 4) {
1158 else if (
sizeof(
typename PC::ParticleType::RealType) == 8) {
1171#ifdef AMREX_USE_HDF5
#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:110
static void streamSynchronize() noexcept
Definition AMReX_GpuDevice.cpp:855
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:85
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:169
int index() const noexcept
The index into the underlying BoxArray of the current FAB.
Definition AMReX_MFIter.H:172
A collection (stored as an array) of FArrayBox objects.
Definition AMReX_MultiFab.H:40
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:118
Parse Parameters From Command Line and Input Files.
Definition AMReX_ParmParse.H:348
int queryAdd(std::string_view name, T &ref)
If name is found, the value in the ParmParse database will be stored in the ref argument....
Definition AMReX_ParmParse.H:1044
Definition AMReX_Reduce.H:453
Type value()
Definition AMReX_Reduce.H:488
Definition AMReX_Reduce.H:612
std::enable_if_t< IsFabArray< MF >::value > eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:746
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:28
T * dataPtr() noexcept
get access to the underlying data pointer
Definition AMReX_Vector.H:49
Long size() const noexcept
Definition AMReX_Vector.H:53
static bool GetBarrierAfterLevel()
Definition AMReX_VisMF.H:286
amrex_particle_real ParticleReal
Floating Point Type for Particles.
Definition AMReX_REAL.H:90
amrex_long Long
Definition AMReX_INT.H:30
Arena * The_Pinned_Arena()
Definition AMReX_Arena.cpp:845
int MyProc() noexcept
Definition AMReX_ParallelDescriptor.H:128
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
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
__host__ __device__ void * memcpy(void *dest, const void *src, std::size_t count)
Definition AMReX_GpuUtility.H:220
void GatherLayoutDataToVector(const LayoutData< T > &sendbuf, Vector< T > &recvbuf, int root)
Gather LayoutData values to a vector on root.
Definition AMReX_ParallelDescriptor.H:1295
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
__host__ __device__ void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:139
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:485
void FileOpenFailed(const std::string &file)
Output a message and abort when couldn't open the file.
Definition AMReX_Utility.cpp:137
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:193
void writeFloatData(const float *data, std::size_t size, std::ostream &os, const RealDescriptor &rd=FPC::Native32RealDescriptor())
Definition AMReX_VectorIO.cpp:114
__host__ __device__ Dim3 begin(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:2006
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:393
void CreateDirectoryFailed(const std::string &dir)
Output a message and abort when couldn't create the directory.
Definition AMReX_Utility.cpp:129
RandomEngine getInvalidRandomEngine()
Definition AMReX_RandomEngine.H:86
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
void writeDoubleData(const double *data, std::size_t size, std::ostream &os, const RealDescriptor &rd=FPC::Native64RealDescriptor())
Definition AMReX_VectorIO.cpp:126
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:240
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:784
__host__ __device__ Dim3 end(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:2015
AMREX_ATTRIBUTE_FLATTEN_FOR void ParallelForRNG(T n, L const &f) noexcept
Definition AMReX_GpuLaunchFunctsC.H:1231
Definition AMReX_WriteBinaryParticleData.H:13
__host__ __device__ int operator()(const SrcData &src, int i) const noexcept
Definition AMReX_WriteBinaryParticleData.H:16
FabArray memory allocation information.
Definition AMReX_FabArray.H:66
MFInfo & SetAlloc(bool a) noexcept
Definition AMReX_FabArray.H:73
Definition AMReX_ParticleTile.H:723
void resize(std::size_t count, GrowthStrategy strategy=GrowthStrategy::Poisson)
Definition AMReX_ParticleTile.H:971
Definition AMReX_RandomEngine.H:72