diff options
Diffstat (limited to 'Source/Diagnostics/WarpXOpenPMD.cpp')
-rw-r--r-- | Source/Diagnostics/WarpXOpenPMD.cpp | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/Source/Diagnostics/WarpXOpenPMD.cpp b/Source/Diagnostics/WarpXOpenPMD.cpp index 6f5c6a36b..daf5fbefc 100644 --- a/Source/Diagnostics/WarpXOpenPMD.cpp +++ b/Source/Diagnostics/WarpXOpenPMD.cpp @@ -489,7 +489,7 @@ WarpXOpenPMDPlot::Init (openPMD::Access access, bool isBTD) void WarpXOpenPMDPlot::WriteOpenPMDParticles (const amrex::Vector<ParticleDiag>& particle_diags, - const bool isBTD) + const bool isBTD, const amrex::Vector<int>& totalParticlesFlushedAlready) { WARPX_PROFILE("WarpXOpenPMDPlot::WriteOpenPMDParticles()"); @@ -552,28 +552,48 @@ WarpXOpenPMDPlot::WriteOpenPMDParticles (const amrex::Vector<ParticleDiag>& part GeometryFilter const geometry_filter(particle_diags[i].m_do_geom_filter, particle_diags[i].m_diag_domain); - using SrcData = WarpXParticleContainer::ParticleTileType::ConstParticleTileDataType; - tmp.copyParticles(*pc, - [=] AMREX_GPU_HOST_DEVICE (const SrcData& src, int ip, const amrex::RandomEngine& engine) - { - const SuperParticleType& p = src.getSuperParticle(ip); - return random_filter(p, engine) * uniform_filter(p, engine) - * parser_filter(p, engine) * geometry_filter(p, engine); - }, true); + if (! isBTD) { + using SrcData = WarpXParticleContainer::ParticleTileType::ConstParticleTileDataType; + tmp.copyParticles(*pc, + [=] AMREX_GPU_HOST_DEVICE (const SrcData& src, int ip, const amrex::RandomEngine& engine) + { + const SuperParticleType& p = src.getSuperParticle(ip); + return random_filter(p, engine) * uniform_filter(p, engine) + * parser_filter(p, engine) * geometry_filter(p, engine); + }, true); + } else if (isBTD) { + PinnedMemoryParticleContainer* pinned_pc = particle_diags[i].getPinnedParticleContainer(); + tmp.SetParticleGeometry(0,pinned_pc->Geom(0)); + tmp.SetParticleBoxArray(0,pinned_pc->ParticleBoxArray(0)); + tmp.SetParticleDistributionMap(0, pinned_pc->ParticleDistributionMap(0)); + tmp.copyParticles(*pinned_pc); + } // real_names contains a list of all real particle attributes. // real_flags is 1 or 0, whether quantity is dumped or not. { - DumpToFile(&tmp, - particle_diags[i].getSpeciesName(), - m_CurrentStep, - real_flags, - int_flags, - real_names, int_names, - pc->getCharge(), pc->getMass(), - isBTD - ); + if (isBTD) { + DumpToFile(&tmp, + particle_diags[i].getSpeciesName(), + m_CurrentStep, + real_flags, + int_flags, + real_names, int_names, + pc->getCharge(), pc->getMass(), + isBTD, totalParticlesFlushedAlready[i] + ); + } else { + DumpToFile(&tmp, + particle_diags[i].getSpeciesName(), + m_CurrentStep, + real_flags, + int_flags, + real_names, int_names, + pc->getCharge(), pc->getMass(), + isBTD, 0 + ); + } } // Convert momentum back to WarpX units @@ -590,12 +610,13 @@ WarpXOpenPMDPlot::DumpToFile (ParticleContainer* pc, const amrex::Vector<std::string>& real_comp_names, const amrex::Vector<std::string>& int_comp_names, amrex::ParticleReal const charge, - amrex::ParticleReal const mass, - const bool isBTD) const + amrex::ParticleReal const mass, const bool isBTD, + int ParticleFlushOffset) { AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_Series != nullptr, "openPMD: series must be initialized"); WarpXParticleCounter counter(pc); + if (counter.GetTotalNumParticles() == 0) return; openPMD::Iteration currIteration = GetIteration(iteration, isBTD); openPMD::ParticleSpecies currSpecies = currIteration.particles[name]; @@ -640,20 +661,29 @@ WarpXOpenPMDPlot::DumpToFile (ParticleContainer* pc, // // define positions & offsets // - SetupPos(currSpecies, counter.GetTotalNumParticles(), charge, mass); - SetupRealProperties(currSpecies, write_real_comp, real_comp_names, write_int_comp, int_comp_names, counter.GetTotalNumParticles()); - + const unsigned long long NewParticleVectorSize = counter.GetTotalNumParticles() + ParticleFlushOffset; + m_doParticleSetUp = false; + if (counter.GetTotalNumParticles() > 0 and ParticleFlushOffset == 0) { + // This will trigger meta-data flush for particles the first-time non-zero number of particles are flushed. + m_doParticleSetUp = true; + } + SetupPos(currSpecies, NewParticleVectorSize, charge, mass, isBTD); + SetupRealProperties(currSpecies, write_real_comp, real_comp_names, write_int_comp, int_comp_names, NewParticleVectorSize, isBTD); // open files from all processors, in case some will not contribute below m_Series->flush(); - for (auto currentLevel = 0; currentLevel <= pc->finestLevel(); currentLevel++) { uint64_t offset = static_cast<uint64_t>( counter.m_ParticleOffsetAtRank[currentLevel] ); - + // For BTD, the offset include the number of particles already flushed + if (isBTD) offset += ParticleFlushOffset; for (ParticleIter pti(*pc, currentLevel); pti.isValid(); ++pti) { auto const numParticleOnTile = pti.numParticles(); uint64_t const numParticleOnTile64 = static_cast<uint64_t>( numParticleOnTile ); + // Do not call storeChunk() with zero-sized particle tiles: + // https://github.com/openPMD/openPMD-api/issues/1147 + if (numParticleOnTile == 0) continue; + // get position and particle ID from aos // note: this implementation iterates the AoS 4x... // if we flush late as we do now, we can also copy out the data in one go @@ -740,11 +770,12 @@ WarpXOpenPMDPlot::SetupRealProperties (openPMD::ParticleSpecies& currSpecies, const amrex::Vector<std::string>& real_comp_names, const amrex::Vector<int>& write_int_comp, const amrex::Vector<std::string>& int_comp_names, - unsigned long long np) const + const unsigned long long np, bool const isBTD) const { - auto dtype_real = openPMD::Dataset(openPMD::determineDatatype<amrex::ParticleReal>(), {np}); - auto dtype_int = openPMD::Dataset(openPMD::determineDatatype<int>(), {np}); - + std::string options = "{}"; + if (isBTD) options = "{ \"resizable\": true }"; + auto dtype_real = openPMD::Dataset(openPMD::determineDatatype<amrex::ParticleReal>(), {np}, options); + auto dtype_int = openPMD::Dataset(openPMD::determineDatatype<int>(), {np}, options); // // the beam/input3d showed write_real_comp.size() = 16 while only 10 real comp names // so using the min to be safe. @@ -767,6 +798,8 @@ WarpXOpenPMDPlot::SetupRealProperties (openPMD::ParticleSpecies& currSpecies, } } + // attributes need to be set only the first time BTD flush is called for a snapshot + if (isBTD and m_doParticleSetUp == false) return; std::set< std::string > addedRecords; // add meta-data per record only once for (auto idx=0; idx<m_NumSoARealAttributes; idx++) { auto ii = m_NumAoSRealAttributes + idx; // jump over AoS names @@ -832,7 +865,6 @@ WarpXOpenPMDPlot::SaveRealProperty (ParticleIter& pti, uint64_t const numParticleOnTile64 = static_cast<uint64_t>( numParticleOnTile ); auto const& aos = pti.GetArrayOfStructs(); // size = numParticlesOnTile auto const& soa = pti.GetStructOfArrays(); - // first we concatinate the AoS into contiguous arrays { for( auto idx=0; idx<m_NumAoSRealAttributes; idx++ ) { @@ -892,23 +924,31 @@ WarpXOpenPMDPlot::SetupPos ( openPMD::ParticleSpecies& currSpecies, const unsigned long long& np, amrex::ParticleReal const charge, - amrex::ParticleReal const mass) const + amrex::ParticleReal const mass, + bool const isBTD) { - auto const realType = openPMD::Dataset(openPMD::determineDatatype<amrex::ParticleReal>(), {np}); - auto const idType = openPMD::Dataset(openPMD::determineDatatype< uint64_t >(), {np}); + std::string options = "{}"; + if (isBTD) options = "{ \"resizable\": true }"; + auto realType= openPMD::Dataset(openPMD::determineDatatype<amrex::ParticleReal>(), {np}, options); + auto idType = openPMD::Dataset(openPMD::determineDatatype< uint64_t >(), {np}, options); auto const positionComponents = detail::getParticlePositionComponentLabels(); for( auto const& comp : positionComponents ) { currSpecies["positionOffset"][comp].resetDataset( realType ); - currSpecies["positionOffset"][comp].makeConstant( 0. ); currSpecies["position"][comp].resetDataset( realType ); } auto const scalar = openPMD::RecordComponent::SCALAR; currSpecies["id"][scalar].resetDataset( idType ); currSpecies["charge"][scalar].resetDataset( realType ); - currSpecies["charge"][scalar].makeConstant( charge ); currSpecies["mass"][scalar].resetDataset( realType ); + + if (isBTD and m_doParticleSetUp == false) return; + // make constant + for( auto const& comp : positionComponents ) { + currSpecies["positionOffset"][comp].makeConstant( 0. ); + } + currSpecies["charge"][scalar].makeConstant( charge ); currSpecies["mass"][scalar].makeConstant( mass ); // meta data |