/* Copyright 2022 Remi Lehe * * This file is part of WarpX. * * License: BSD-3-Clause-LBNL */ #ifndef NamedComponentParticleContainer_H_ #define NamedComponentParticleContainer_H_ #include "Utils/TextMsg.H" #include #include #include #include #include /** Particle Attributes stored in amrex::ParticleContainer's struct of array */ struct PIdx { enum { w = 0, ///< weight ux, uy, uz, #ifdef WARPX_DIM_RZ theta, ///< RZ needs all three position components #endif nattribs ///< number of attributes }; }; /** Particle Container class that allows to add/access particle components * with a name (string) instead of doing so with an integer index. * (The "components" are all the particle quantities - except those * that are stored in an AoS by amrex, i.e. the particle positions and ID) * * This is done by storing maps that give the index of the component * that corresponds to a given string. * * @tparam T_Allocator Mainly controls in which type of memory (e.g. device * arena, pinned memory arena, etc.) the particle data will be stored */ template class T_Allocator=amrex::DefaultAllocator> class NamedComponentParticleContainer : public amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator> { public: /** Construct an empty NamedComponentParticleContainer **/ NamedComponentParticleContainer () : amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>() {} /** Construct a NamedComponentParticleContainer from an AmrParGDB object * * In this case, the only components are the default ones: * weight, momentum and (in RZ geometry) theta. * * @param amr_pgdb A pointer to a ParGDBBase, which contains pointers to * the Geometry, DistributionMapping, and BoxArray objects that define the * AMR hierarchy. Usually, this is generated by an AmrCore or AmrLevel object. */ NamedComponentParticleContainer (amrex::AmrParGDB* amr_pgdb) : amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>(amr_pgdb) { // build up the map of string names to particle component numbers particle_comps["w"] = PIdx::w; particle_comps["ux"] = PIdx::ux; particle_comps["uy"] = PIdx::uy; particle_comps["uz"] = PIdx::uz; #ifdef WARPX_DIM_RZ particle_comps["theta"] = PIdx::theta; #endif } /** Destructor for NamedComponentParticleContainer */ virtual ~NamedComponentParticleContainer() = default; /** Construct a NamedComponentParticleContainer from a regular * amrex::ParticleContainer, and additional name-to-index maps * * @param pc regular particle container, where components are not named (only indexed) * @param p_comps name-to-index map for compile-time and run-time real components * @param p_icomps name-to-index map for compile-time and run-time integer components * @param p_rcomps name-to-index map for run-time real components * @param p_ricomps name-to-index map for run-time integer components */ NamedComponentParticleContainer( amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator> && pc, std::map p_comps, std::map p_icomps, std::map p_rcomps, std::map p_ricomps) : amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>(std::move(pc)), particle_comps(p_comps), particle_icomps(p_icomps), particle_runtime_comps(p_rcomps), particle_runtime_icomps(p_ricomps) {} /** Move constructor for NamedComponentParticleContainer */ NamedComponentParticleContainer ( NamedComponentParticleContainer && ) = default; /** Move operator for NamedComponentParticleContainer */ NamedComponentParticleContainer& operator= ( NamedComponentParticleContainer && ) = default; /** Create an empty particle container * * This creates a new NamedComponentParticleContainer with same compile-time * and run-time attributes. But it can change its allocator. * * This function overloads the corresponding function from the parent * class (amrex::ParticleContainer) */ template class NewAllocator=amrex::DefaultAllocator> NamedComponentParticleContainer make_alike () const { auto tmp = NamedComponentParticleContainer( amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>::template make_alike(), particle_comps, particle_icomps, particle_runtime_comps, particle_runtime_icomps); return tmp; } using amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>::NumRealComps; using amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>::NumIntComps; using amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>::AddRealComp; using amrex::ParticleContainer<0,0,PIdx::nattribs,0,T_Allocator>::AddIntComp; /** Allocate a new run-time real component * * @param name Name of the new component * @param comm Whether to communicate this component, in the particle Redistribute */ void AddRealComp (const std::string& name, bool comm=true) { auto search = particle_comps.find(name); if (search == particle_comps.end()) { particle_comps[name] = NumRealComps(); particle_runtime_comps[name] = NumRealComps() - PIdx::nattribs; AddRealComp(comm); } else { amrex::Print() << Utils::TextMsg::Info( name + " already exists in particle_comps, not adding."); } } /** Allocate a new run-time integer component * * @param name Name of the new component * @param comm Whether to communicate this component, in the particle Redistribute */ void AddIntComp (const std::string& name, bool comm=true) { auto search = particle_icomps.find(name); if (search == particle_icomps.end()) { particle_icomps[name] = NumIntComps(); particle_runtime_icomps[name] = NumIntComps() - 0; AddIntComp(comm); } else { amrex::Print() << Utils::TextMsg::Info( name + " already exists in particle_icomps, not adding."); } } /** Return the name-to-index map for the compile-time and runtime-time real components */ std::map getParticleComps () const noexcept { return particle_comps;} /** Return the name-to-index map for the compile-time and runtime-time integer components */ std::map getParticleiComps () const noexcept { return particle_icomps;} /** Return the name-to-index map for the runtime-time real components */ std::map getParticleRuntimeComps () const noexcept { return particle_runtime_comps;} /** Return the name-to-index map for the runtime-time integer components */ std::map getParticleRuntimeiComps () const noexcept { return particle_runtime_icomps;} protected: std::map particle_comps; std::map particle_icomps; std::map particle_runtime_comps; std::map particle_runtime_icomps; }; #endif