LCOV - code coverage report
Current view: top level - src/Particle - ParticleBase.h (source / functions) Coverage Total Hit
Test: final_report.info Lines: 72.7 % 22 16
Test Date: 2025-07-17 08:40:11 Functions: 71.0 % 372 264

            Line data    Source code
       1              : //
       2              : // Class ParticleBase
       3              : //   Base class for all user-defined particle classes.
       4              : //
       5              : //   ParticleBase is a container and manager for a set of particles.
       6              : //   The user must define a class derived from ParticleBase which describes
       7              : //   what specific data attributes the particle has (e.g., mass or charge).
       8              : //   Each attribute is an instance of a ParticleAttribute<T> class; ParticleBase
       9              : //   keeps a list of pointers to these attributes, and performs particle creation
      10              : //   and destruction.
      11              : //
      12              : //   ParticleBase is templated on the ParticleLayout mechanism for the particles.
      13              : //   This template parameter should be a class derived from ParticleLayout.
      14              : //   ParticleLayout-derived classes maintain the info on which particles are
      15              : //   located on which processor, and performs the specific communication
      16              : //   required between processors for the particles.  The ParticleLayout is
      17              : //   templated on the type and dimension of the atom position attribute, and
      18              : //   ParticleBase uses the same types for these items as the given
      19              : //   ParticleLayout.
      20              : //
      21              : //   ParticleBase and all derived classes have the following common
      22              : //   characteristics:
      23              : //       - The spatial positions of the N particles are stored in the
      24              : //         particle_position_type variable R
      25              : //       - The global index of the N particles are stored in the
      26              : //         particle_index_type variable ID
      27              : //       - A pointer to an allocated layout class.  When you construct a
      28              : //         ParticleBase, you must provide a layout instance, and ParticleBase
      29              : //         will delete this instance when it (the ParticleBase) is deleted.
      30              : //
      31              : //   To use this class, the user defines a derived class with the same
      32              : //   structure as in this example:
      33              : //
      34              : //     class UserParticles :
      35              : //              public ParticleBase< ParticleSpatialLayout<double,3> > {
      36              : //     public:
      37              : //       // attributes for this class
      38              : //       ParticleAttribute<double> rad;  // radius
      39              : //       particle_position_type    vel;  // velocity, same storage type as R
      40              : //
      41              : //       // constructor: add attributes to base class
      42              : //       UserParticles(ParticleSpatialLayout<double,2>* L) : ParticleBase(L) {
      43              : //         addAttribute(rad);
      44              : //         addAttribute(vel);
      45              : //       }
      46              : //     };
      47              : //
      48              : //   This example defines a user class with 3D position and two extra
      49              : //   attributes: a radius rad (double), and a velocity vel (a 3D Vector).
      50              : //
      51              : #ifndef IPPL_PARTICLE_BASE_H
      52              : #define IPPL_PARTICLE_BASE_H
      53              : 
      54              : #include <tuple>
      55              : #include <type_traits>
      56              : #include <vector>
      57              : 
      58              : #include "Types/IpplTypes.h"
      59              : 
      60              : #include "Utility/TypeUtils.h"
      61              : 
      62              : #include "Particle/ParticleLayout.h"
      63              : 
      64              : namespace ippl {
      65              : 
      66              :     /*!
      67              :      * @class ParticleBase
      68              :      * @tparam PLayout the particle layout implementing an algorithm to
      69              :      * distribute the particles among MPI ranks
      70              :      * @tparam IDProperties the view properties for particle IDs (if any
      71              :      * of the provided types is ippl::DisableParticleIDs, then particle
      72              :      * IDs will be disabled for the bunch)
      73              :      */
      74              :     template <class PLayout, typename... IDProperties>
      75              :     class ParticleBase {
      76              :         constexpr static bool EnableIDs = sizeof...(IDProperties) > 0;
      77              : 
      78              :     public:
      79              :         using vector_type            = typename PLayout::vector_type;
      80              :         using index_type             = typename PLayout::index_type;
      81              :         using particle_position_type = typename PLayout::particle_position_type;
      82              :         using particle_index_type    = ParticleAttrib<index_type, IDProperties...>;
      83              : 
      84              :         using Layout_t = PLayout;
      85              : 
      86              :         template <typename... Properties>
      87              :         using attribute_type = typename detail::ParticleAttribBase<Properties...>;
      88              : 
      89              :         template <typename MemorySpace>
      90              :         using container_type = std::vector<attribute_type<MemorySpace>*>;
      91              : 
      92              :         using attribute_container_type =
      93              :             typename detail::ContainerForAllSpaces<container_type>::type;
      94              : 
      95              :         using bc_container_type = typename PLayout::bc_container_type;
      96              : 
      97              :         using hash_container_type = typename detail::ContainerForAllSpaces<detail::hash_type>::type;
      98              : 
      99              :         using size_type = detail::size_type;
     100              : 
     101              :     public:
     102              :         //! view of particle positions
     103              :         particle_position_type R;
     104              : 
     105              :         //! view of particle IDs
     106              :         particle_index_type ID;
     107              : 
     108              :         /*!
     109              :          * If this constructor is used, the user must call 'initialize' with
     110              :          * a layout object in order to use this.
     111              :          */
     112              :         ParticleBase();
     113              : 
     114              :         /*!
     115              :          * Ctor called when layout is provided with std::shared_ptr. It
     116              :          * calls the default ctor which then calls the private ctor. The
     117              :          * layout instance is moved to this class, hence, the argument
     118              :          * is null afterwards, i.e., layout == nullptr.
     119              :          * @param layout to be moved.
     120              :          */
     121              :         ParticleBase(Layout_t& layout);
     122              : 
     123              :         /* cannot use '= default' since we get a
     124              :          * compiler warning otherwise:
     125              :          * warning: calling a __host__ function("std::vector< ::ippl::detail::ParticleAttribBase *,
     126              :          * ::std::allocator<
     127              :          * ::ippl::detail::ParticleAttribBase *> > ::~vector") from a __host__ __device__
     128              :          * function("ippl::ParticleBase<
     129              :          * ::ippl::ParticleLayout<double, (unsigned int)3u> > ::~ParticleBase") is not allowed
     130              :          */
     131          204 :         ~ParticleBase() {}  // = default; //{ }
     132              : 
     133              :         /*!
     134              :          * Initialize the particle layout. Needs to be called
     135              :          * when the ParticleBase instance is constructed with the
     136              :          * default ctor.
     137              :          */
     138              :         void initialize(Layout_t& layout);
     139              : 
     140              :         /*!
     141              :          * @returns processor local number of particles
     142              :          */
     143         3144 :         size_type getLocalNum() const { return localNum_m; }
     144              : 
     145              :         void setLocalNum(size_type size) { localNum_m = size; }
     146              : 
     147              :         /*!
     148              :          * @returns total number of particles (across all processes)
     149              :          */
     150              :         size_type getTotalNum() const { return totalNum_m; }
     151              : 
     152              :         /*!
     153              :          * @returns particle layout
     154              :          */
     155          120 :         Layout_t& getLayout() { return *layout_m; }
     156              : 
     157              :         /*!
     158              :          * @returns particle layout
     159              :          */
     160              :         const Layout_t& getLayout() const { return *layout_m; }
     161              : 
     162              :         /*!
     163              :          * Set all boundary conditions
     164              :          * @param bc the boundary conditions
     165              :          */
     166           12 :         void setParticleBC(const bc_container_type& bcs) { layout_m->setParticleBC(bcs); }
     167              : 
     168              :         /*!
     169              :          * Set all boundary conditions to this BC
     170              :          * @param bc the boundary conditions
     171              :          */
     172           96 :         void setParticleBC(BC bc) { layout_m->setParticleBC(bc); }
     173              : 
     174              :         /*!
     175              :          * Add particle attribute
     176              :          * @param pa attribute to be added to ParticleBase
     177              :          */
     178              :         template <typename MemorySpace>
     179              :         void addAttribute(detail::ParticleAttribBase<MemorySpace>& pa);
     180              : 
     181              :         /*!
     182              :          * Get particle attribute
     183              :          * @param i attribute number in container
     184              :          * @returns a pointer to the attribute
     185              :          */
     186              :         template <typename MemorySpace = Kokkos::DefaultExecutionSpace::memory_space>
     187              :         attribute_type<MemorySpace>* getAttribute(size_t i) {
     188              :             return attributes_m.template get<MemorySpace>()[i];
     189              :         }
     190              : 
     191              :         /*!
     192              :          * Calls a given function for all attributes in the bunch
     193              :          * @tparam MemorySpace the memory space of the attributes to visit (void to visit all of
     194              :          * them)
     195              :          * @tparam Functor the functor type
     196              :          * @param f a functor taking a single ParticleAttrib<MemorySpace>
     197              :          */
     198              :         template <typename MemorySpace = void, typename Functor>
     199            0 :         void forAllAttributes(Functor&& f) const {
     200              :             if constexpr (std::is_void_v<MemorySpace>) {
     201              :                 attributes_m.forAll(f);
     202              :             } else {
     203            0 :                 for (auto& attribute : attributes_m.template get<MemorySpace>()) {
     204            0 :                     f(attribute);
     205              :                 }
     206              :             }
     207            0 :         }
     208              : 
     209              :         // Non-const variant of same function
     210              :         template <typename MemorySpace = void, typename Functor>
     211          180 :         void forAllAttributes(Functor&& f) {
     212              :             if constexpr (std::is_void_v<MemorySpace>) {
     213          360 :                 attributes_m.forAll([&]<typename Attributes>(Attributes& atts) {
     214          456 :                     for (auto& attribute : atts) {
     215          276 :                         f(attribute);
     216              :                     }
     217              :                 });
     218              :             } else {
     219            0 :                 for (auto& attribute : attributes_m.template get<MemorySpace>()) {
     220            0 :                     f(attribute);
     221              :                 }
     222              :             }
     223          180 :         }
     224              : 
     225              :         /*!
     226              :          * @returns the number of attributes
     227              :          */
     228           12 :         unsigned getAttributeNum() const {
     229           12 :             unsigned total = 0;
     230           36 :             detail::runForAllSpaces([&]<typename MemorySpace>() {
     231           12 :                 total += attributes_m.template get<MemorySpace>().size();
     232              :             });
     233           12 :             return total;
     234              :         }
     235              : 
     236              :         /*!
     237              :          * Create nLocal processor local particles. This is a collective call,
     238              :          * i.e. all MPI ranks must call this.
     239              :          * @param nLocal number of local particles to be created
     240              :          */
     241              :         void create(size_type nLocal);
     242              : 
     243              :         /*!
     244              :          * Create a new particle with a given ID. This is a collective call. If a process
     245              :          * passes a negative number, it does not create a particle.
     246              :          * @param id particle identity number
     247              :          */
     248              :         void createWithID(index_type id);
     249              : 
     250              :         /*!
     251              :          * Create nTotal particles globally, equally distributed among all processors.
     252              :          * This is a collective call.
     253              :          * @param nTotal number of total particles to be created
     254              :          */
     255              :         void globalCreate(size_type nTotal);
     256              : 
     257              :         /*!
     258              :          * Particle deletion Function. Partition the particles into a valid region
     259              :          * and an invalid region,
     260              :          * effectively deleting the invalid particles. This is a collective call.
     261              :          * @param invalid View marking which indices are invalid
     262              :          * @param destroyNum Total number of invalid particles
     263              :          */
     264              :         template <typename... Properties>
     265              :         void destroy(const Kokkos::View<bool*, Properties...>& invalid, const size_type destroyNum);
     266              : 
     267              :         // This is a collective call.
     268           84 :         void update() { layout_m->update(*this); }
     269              : 
     270              :         /*
     271              :          * The following functions should not be called in an application.
     272              :          */
     273              : 
     274              :         /* This function does not alter the totalNum_m member function. It should only be called
     275              :          * during the update function where we know the number of particles remains the same.
     276              :          */
     277              :         template <typename... Properties>
     278              :         void internalDestroy(const Kokkos::View<bool*, Properties...>& invalid,
     279              :                              const size_type destroyNum);
     280              : 
     281              :         /*!
     282              :          * Sends particles to another rank
     283              :          * @tparam HashType the hash view type
     284              :          * @param rank the destination rank
     285              :          * @param tag the MPI tag
     286              :          * @param sendNum the number of messages already sent (to distinguish the buffers)
     287              :          * @param requests destination vector in which to store the MPI requests for polling
     288              :          * purposes
     289              :          * @param hash a hash view indicating which particles need to be sent to which rank
     290              :          */
     291              :         template <typename HashType>
     292              :         void sendToRank(int rank, int tag, std::vector<MPI_Request>& requests,
     293              :                         const HashType& hash);
     294              : 
     295              :         /*!
     296              :          * Receives particles from another rank
     297              :          * @param rank the source rank
     298              :          * @param tag the MPI tag
     299              :          * @param recvNum the number of messages already received (to distinguish the buffers)
     300              :          * @param nRecvs the number of particles to receive
     301              :          */
     302              :         void recvFromRank(int rank, int tag, size_type nRecvs);
     303              : 
     304              :         /*!
     305              :          * Serialize to do MPI calls.
     306              :          * @param ar archive
     307              :          */
     308              :         template <typename Archive>
     309              :         void serialize(Archive& ar, size_type nsends);
     310              : 
     311              :         /*!
     312              :          * Deserialize to do MPI calls.
     313              :          * @param ar archive
     314              :          */
     315              :         template <typename Archive>
     316              :         void deserialize(Archive& ar, size_type nrecvs);
     317              : 
     318              :         /*!
     319              :          * Determine the total space necessary to store a certain number of particles
     320              :          * @tparam MemorySpace only consider attributes stored in this memory space
     321              :          * @param count particle number
     322              :          * @return Total size of a buffer packed with the given number of particles
     323              :          */
     324              :         template <typename MemorySpace>
     325              :         size_type packedSize(const size_type count) const;
     326              : 
     327              :     protected:
     328              :         /*!
     329              :          * Fill attributes of buffer.
     330              :          * @param buffer to send
     331              :          * @param hash function to access index.
     332              :          */
     333              :         void pack(const hash_container_type& hash);
     334              : 
     335              :         /*!
     336              :          * Fill my attributes.
     337              :          * @param buffer received
     338              :          */
     339              :         void unpack(size_type nrecvs);
     340              : 
     341              :     private:
     342              :         //! particle layout
     343              :         // cannot use std::unique_ptr due to Kokkos
     344              :         Layout_t* layout_m;
     345              : 
     346              :         //! processor local number of particles
     347              :         size_type localNum_m;
     348              : 
     349              :         //! total number of particles (across all processes)
     350              :         size_type totalNum_m;
     351              : 
     352              :         //! all attributes
     353              :         attribute_container_type attributes_m;
     354              : 
     355              :         //! next unique particle ID
     356              :         index_type nextID_m;
     357              : 
     358              :         //! number of MPI ranks
     359              :         index_type numNodes_m;
     360              : 
     361              :         //! buffers for particle partitioning
     362              :         hash_container_type deleteIndex_m;
     363              :         hash_container_type keepIndex_m;
     364              :     };
     365              : }  // namespace ippl
     366              : 
     367              : #include "Particle/ParticleBase.hpp"
     368              : 
     369              : #endif
        

Generated by: LCOV version 2.0-1