diff options
Diffstat (limited to 'Source/Particles/ParticleCreation/ElementaryProcess.H')
-rw-r--r-- | Source/Particles/ParticleCreation/ElementaryProcess.H | 269 |
1 files changed, 0 insertions, 269 deletions
diff --git a/Source/Particles/ParticleCreation/ElementaryProcess.H b/Source/Particles/ParticleCreation/ElementaryProcess.H deleted file mode 100644 index 3fe2240cc..000000000 --- a/Source/Particles/ParticleCreation/ElementaryProcess.H +++ /dev/null @@ -1,269 +0,0 @@ -/* Copyright 2019 Axel Huebl, Maxence Thevenet, Weiqun Zhang - * - * - * This file is part of WarpX. - * - * License: BSD-3-Clause-LBNL - */ -#ifndef ELEMENTARYPROCESS_H_ -#define ELEMENTARYPROCESS_H_ - -#include "WarpXParticleContainer.H" -#include "CopyParticle.H" -#include "TransformParticle.H" - -/** - * \brief Base class for particle creation processes - * - * Particles in a source particle container are copied to product particle - * containers if they are flagged. Both source and product particles can be - * modified. - * - * - initialize_copy initializes a general copy functor - * - createParticles formats the data to prepare for the copy, then - * calls copyAndTransformParticles - * - copyAndTransformParticles loops over particles, performs the copy and - * transform source and product particles if needed. - * - * The class is templated on the process type. This gives flexibility - * on source and product particle transformations. - */ -template<ElementaryProcessType ProcessT> -class ElementaryProcess -{ -public: - - /** - * \brief initialize and return functor for particle copy - * - * \param cpuid id of MPI rank - * \param do_back_transformed_product whether to copy old attribs - * \param runtime_uold_source momentum of source particles - * \param attribs_source attribs of source particles - * \param attribs_product attribs of product particles - * \param runtime_attribs_product runtime attribs for product, to store old attribs - */ - CopyParticle initialize_copy( - const int cpuid, const int do_back_transformed_product, - const amrex::GpuArray<amrex::ParticleReal*,3> runtime_uold_source, - const amrex::GpuArray<amrex::ParticleReal*,PIdx::nattribs> attribs_source, - const amrex::GpuArray<amrex::ParticleReal*,PIdx::nattribs> attribs_product, - const amrex::GpuArray<amrex::ParticleReal*,6> runtime_attribs_product) const noexcept - { - return CopyParticle( - cpuid, do_back_transformed_product, runtime_uold_source, - attribs_source, attribs_product, runtime_attribs_product - ); - }; - - /** - * \brief create particles in product particle containers - * - * For particle i in mfi, if is_flagged[i]=1, copy particle - * particle i from container pc_source into each container in v_pc_product - * - * \param lev MR level - * \param mfi MFIter where source particles are located - * \param pc_source source particle container - * \param v_pc_product vector of product particle containers - * \param is_flagged particles for which is_flagged is 1 are copied - * \param v_do_back_transformed_product vector: whether to copy old attribs for - * each product container - */ - void createParticles ( - int lev, const amrex::MFIter& mfi, - std::unique_ptr< WarpXParticleContainer>& pc_source, - amrex::Vector<WarpXParticleContainer*> v_pc_product, - amrex::Gpu::ManagedDeviceVector<int>& is_flagged, - amrex::Gpu::ManagedDeviceVector<int> v_do_back_transformed_product) - { - - BL_PROFILE("createParticles"); - const int grid_id = mfi.index(); - const int tile_id = mfi.LocalTileIndex(); - - // Get source particle data - auto& ptile_source = pc_source->GetParticles(lev)[std::make_pair(grid_id,tile_id)]; - const int np_source = ptile_source.GetArrayOfStructs().size(); - if (np_source == 0) return; - // --- source AoS particle data - WarpXParticleContainer::ParticleType* particles_source = ptile_source.GetArrayOfStructs()().data(); - // --- source SoA particle data - auto& soa_source = ptile_source.GetStructOfArrays(); - amrex::GpuArray<amrex::ParticleReal*,PIdx::nattribs> attribs_source; - for (int ia = 0; ia < PIdx::nattribs; ++ia) { - attribs_source[ia] = soa_source.GetRealData(ia).data(); - } - // --- source runtime attribs - amrex::GpuArray<amrex::ParticleReal*,3> runtime_uold_source; - // Prepare arrays for boosted frame diagnostics. - runtime_uold_source[0] = soa_source.GetRealData(PIdx::ux).data(); - runtime_uold_source[1] = soa_source.GetRealData(PIdx::uy).data(); - runtime_uold_source[2] = soa_source.GetRealData(PIdx::uz).data(); - - // --- source runtime integer attribs - amrex::GpuArray<int*,1> runtime_iattribs_source; - std::map<std::string, int> icomps_source = pc_source->getParticleiComps(); - runtime_iattribs_source[0] = soa_source.GetIntData(icomps_source["ionization_level"]).data(); - - int nproducts = v_pc_product.size(); - AMREX_ALWAYS_ASSERT_WITH_MESSAGE( - v_do_back_transformed_product.size() == nproducts, - "v_pc_product and v_do_back_transformed_product must have the same size."); - - // Indices of product particle for each source particle. - // i_product[i]-1 is the location in product tile of product particle - // from source particle i. - amrex::Gpu::ManagedDeviceVector<int> i_product; - i_product.resize(np_source); - // 0<i<np_source - // 0<i_product<np_flagged - // Strictly speaking, i_product should be an exclusive_scan of - // is_flagged. However, for indices where is_flagged is 1, the - // inclusive scan gives the same result with an offset of 1. - // The advantage of inclusive_scan is that the sum of is_flagged - // is in the last element, so no other reduction is required to get - // number of particles. - // Gpu::inclusive_scan runs on the current GPU stream, and synchronizes - // with the CPU, so that the next line (executed by the CPU) has the - // updated values of i_product - amrex::Gpu::inclusive_scan(is_flagged.begin(), is_flagged.end(), i_product.begin()); - int np_flagged = i_product[np_source-1]; - if (np_flagged == 0) return; - - amrex::Gpu::ManagedDeviceVector<CopyParticle> v_copy_functor; - v_copy_functor.reserve(nproducts); - amrex::Gpu::ManagedDeviceVector<int> v_pid_product(nproducts); - amrex::Gpu::ManagedDeviceVector<WarpXParticleContainer::ParticleType*> v_particles_product(nproducts); - for (int iproduct=0; iproduct<nproducts; iproduct++){ - WarpXParticleContainer*& pc_product = v_pc_product[iproduct]; - // Get product particle data - auto& ptile_product = pc_product->GetParticles(lev)[std::make_pair(grid_id,tile_id)]; - // old and new (i.e., including flagged particles) number of particles - // for product species - const int np_product_old = ptile_product.GetArrayOfStructs().size(); - const int np_product_new = np_product_old + np_flagged; - // Allocate extra space in product species for flagged particles. - ptile_product.resize(np_product_new); - // --- product AoS particle data - // WarpXParticleContainer::ParticleType* particles_product = ptile_product.GetArrayOfStructs()().data() + np_product_old; - v_particles_product[iproduct] = ptile_product.GetArrayOfStructs()().data() + np_product_old; - // First element is the first newly-created product particle - // --- product SoA particle data - auto& soa_product = ptile_product.GetStructOfArrays(); - amrex::GpuArray<amrex::ParticleReal*,PIdx::nattribs> attribs_product; - for (int ia = 0; ia < PIdx::nattribs; ++ia) { - // First element is the first newly-created product particle - attribs_product[ia] = soa_product.GetRealData(ia).data() + np_product_old; - } - // --- product runtime attribs - amrex::GpuArray<amrex::ParticleReal*,6> runtime_attribs_product; - const int do_boost = v_do_back_transformed_product[iproduct]; - if (do_boost) { - std::map<std::string, int> comps_product = pc_product->getParticleComps(); - runtime_attribs_product[0] = soa_product.GetRealData(comps_product[ "xold"]).data() + np_product_old; - runtime_attribs_product[1] = soa_product.GetRealData(comps_product[ "yold"]).data() + np_product_old; - runtime_attribs_product[2] = soa_product.GetRealData(comps_product[ "zold"]).data() + np_product_old; - runtime_attribs_product[3] = soa_product.GetRealData(comps_product["uxold"]).data() + np_product_old; - runtime_attribs_product[4] = soa_product.GetRealData(comps_product["uyold"]).data() + np_product_old; - runtime_attribs_product[5] = soa_product.GetRealData(comps_product["uzold"]).data() + np_product_old; - } - - // --- product runtime integer attribs - int pid_product; -#ifdef _OPENMP -#pragma omp critical (doParticleCreation_nextid) -#endif - { - // ID of first newly-created product particle - pid_product = pc_product->NextID(); - // Update NextID to include particles created in this function - pc_product->setNextID(pid_product+np_flagged); - } - const int cpuid = amrex::ParallelDescriptor::MyProc(); - - // Create instance of copy functor, and add it to the vector - v_copy_functor.push_back( initialize_copy( - cpuid, v_do_back_transformed_product[iproduct], - runtime_uold_source, - attribs_source, - attribs_product, - runtime_attribs_product - ) ); - v_pid_product[iproduct] = pid_product; - - } - // Loop over source particles and create product particles - copyAndTransformParticles(is_flagged, i_product, np_source, v_pid_product, - v_particles_product, particles_source, v_copy_functor, - runtime_iattribs_source); - // Synchronize to prevent the destruction of temporary arrays (at the - // end of the function call) before the kernel executes. - amrex::Gpu::streamSynchronize(); - } - - /** - * \brief Loop over source particles and create product particles - * - * \param is_flagged particles for which is_flagged is 1 are copied - * \param i_product relative indices of product particle. This is the same - * for all product particle containers. - * \param np_source number of particles in source container - * \param v_pid_product for each product particle container: ID of the - * first product particle. Others IDs are incremented from this one - * \param v_particles_product for each product particle container: pointer - * to the AoS particle data - * \param particles_source pointter to the AoS source particle data - * \param v_copy_functor vector of copy functors, one for each product particle container - * \param runtime_iattribs_source pointer to source runtime integer attribs - */ - void copyAndTransformParticles( - amrex::Gpu::ManagedDeviceVector<int>& is_flagged, - amrex::Gpu::ManagedDeviceVector<int>& i_product, - int np_source, - amrex::Gpu::ManagedDeviceVector<int> v_pid_product, - amrex::Gpu::ManagedDeviceVector<WarpXParticleContainer::ParticleType*> v_particles_product, - WarpXParticleContainer::ParticleType* particles_source, - const amrex::Gpu::ManagedDeviceVector<CopyParticle>& v_copy_functor, - amrex::GpuArray<int*,1> runtime_iattribs_source) - { - int const * const AMREX_RESTRICT p_is_flagged = is_flagged.dataPtr(); - int const * const AMREX_RESTRICT p_i_product = i_product.dataPtr(); - CopyParticle const * const AMREX_RESTRICT p_copy_functor = v_copy_functor.dataPtr(); - WarpXParticleContainer::ParticleType * * p_particles_product = v_particles_product.data(); - int const * const p_pid_product = v_pid_product.data(); - - // Loop over all source particles. If is_flagged, copy particle data - // to corresponding product particle. - int nproducts = v_particles_product.size(); - amrex::For( - np_source, [=] AMREX_GPU_DEVICE (int is) noexcept - { - if(p_is_flagged[is]){ - // offset of 1 due to inclusive scan - int ip = p_i_product[is]-1; - WarpXParticleContainer::ParticleType& p_source = particles_source[is]; - for (int iproduct=0; iproduct<nproducts; iproduct++){ - // is: index of flagged particle in source species - // ip: index of corresponding new particle in product species - WarpXParticleContainer::ParticleType* particles_product = p_particles_product[iproduct]; - WarpXParticleContainer::ParticleType& p_product = particles_product[ip]; - p_copy_functor[iproduct](is, ip, p_pid_product[iproduct], p_source, p_product); - } - // Transform source particle - transformSourceParticle<ProcessT>(is, p_source, runtime_iattribs_source); - // Transform product particles. The loop over product - // species is done inside the function to allow for - // more flexibility. - transformProductParticle<ProcessT>(ip, p_particles_product); - } - } - ); - } -}; - -// Derived class for ionization process -class IonizationProcess: public ElementaryProcess<ElementaryProcessType::Ionization> -{}; - -#endif // ELEMENTARYPROCESS_H_ |