LCOV - code coverage report
Current view: top level - src/Particle - ParticleAttrib.hpp (source / functions) Coverage Total Hit
Test: report.info Lines: 70.6 % 119 84
Test Date: 2025-05-21 12:05:18 Functions: 51.9 % 237 123
Branches: 41.2 % 1096 452

             Branch data     Line data    Source code
       1                 :             : //
       2                 :             : // Class ParticleAttrib
       3                 :             : //   Templated class for all particle attribute classes.
       4                 :             : //
       5                 :             : //   This templated class is used to represent a single particle attribute.
       6                 :             : //   An attribute is one data element within a particle object, and is
       7                 :             : //   stored as a Kokkos::View. This class stores the type information for the
       8                 :             : //   attribute, and provides methods to create and destroy new items, and
       9                 :             : //   to perform operations involving this attribute with others.
      10                 :             : //
      11                 :             : //   ParticleAttrib is the primary element involved in expressions for
      12                 :             : //   particles (just as BareField is the primary element there).  This file
      13                 :             : //   defines the necessary templated classes and functions to make
      14                 :             : //   ParticleAttrib a capable expression-template participant.
      15                 :             : //
      16                 :             : #include "Ippl.h"
      17                 :             : 
      18                 :             : #include "Communicate/DataTypes.h"
      19                 :             : 
      20                 :             : #include "Utility/IpplTimings.h"
      21                 :             : 
      22                 :             : namespace ippl {
      23                 :             : 
      24                 :             :     template <typename T, class... Properties>
      25                 :         252 :     void ParticleAttrib<T, Properties...>::create(size_type n) {
      26                 :         252 :         size_type required = *(this->localNum_mp) + n;
      27         [ +  - ]:         252 :         if (this->size() < required) {
      28                 :         252 :             int overalloc = Comm->getDefaultOverallocation();
      29                 :         252 :             this->realloc(required * overalloc);
      30                 :             :         }
      31                 :         252 :     }
      32                 :             : 
      33                 :             :     template <typename T, class... Properties>
      34                 :          24 :     void ParticleAttrib<T, Properties...>::destroy(const hash_type& deleteIndex,
      35                 :             :                                                    const hash_type& keepIndex,
      36                 :             :                                                    size_type invalidCount) {
      37                 :             :         // Replace all invalid particles in the valid region with valid
      38                 :             :         // particles in the invalid region
      39                 :             :         using policy_type = Kokkos::RangePolicy<execution_space>;
      40   [ +  -  +  - ]:          24 :         Kokkos::parallel_for(
      41                 :          24 :             "ParticleAttrib::destroy()", policy_type(0, invalidCount),
      42   [ +  -  +  -  :       12048 :             KOKKOS_CLASS_LAMBDA(const size_t i) {
          +  -  +  -  -  
                -  -  - ]
      43                 :           0 :                 dview_m(deleteIndex(i)) = dview_m(keepIndex(i));
      44                 :             :             });
      45                 :          24 :     }
      46                 :             : 
      47                 :             :     template <typename T, class... Properties>
      48                 :           0 :     void ParticleAttrib<T, Properties...>::pack(const hash_type& hash) {
      49                 :           0 :         auto size = hash.extent(0);
      50         [ #  # ]:           0 :         if (buf_m.extent(0) < size) {
      51                 :           0 :             int overalloc = Comm->getDefaultOverallocation();
      52                 :           0 :             Kokkos::realloc(buf_m, size * overalloc);
      53                 :             :         }
      54                 :             : 
      55                 :             :         using policy_type = Kokkos::RangePolicy<execution_space>;
      56   [ #  #  #  # ]:           0 :         Kokkos::parallel_for(
      57                 :           0 :             "ParticleAttrib::pack()", policy_type(0, size),
      58   [ #  #  #  #  :           0 :             KOKKOS_CLASS_LAMBDA(const size_t i) { buf_m(i) = dview_m(hash(i)); });
             #  #  #  # ]
      59   [ #  #  #  # ]:           0 :         Kokkos::fence();
      60                 :           0 :     }
      61                 :             : 
      62                 :             :     template <typename T, class... Properties>
      63                 :           0 :     void ParticleAttrib<T, Properties...>::unpack(size_type nrecvs) {
      64                 :           0 :         auto size          = dview_m.extent(0);
      65                 :           0 :         size_type required = *(this->localNum_mp) + nrecvs;
      66         [ #  # ]:           0 :         if (size < required) {
      67                 :           0 :             int overalloc = Comm->getDefaultOverallocation();
      68                 :           0 :             this->resize(required * overalloc);
      69                 :             :         }
      70                 :             : 
      71                 :           0 :         size_type count   = *(this->localNum_mp);
      72                 :             :         using policy_type = Kokkos::RangePolicy<execution_space>;
      73   [ #  #  #  # ]:           0 :         Kokkos::parallel_for(
      74                 :           0 :             "ParticleAttrib::unpack()", policy_type(0, nrecvs),
      75   [ #  #  #  #  :           0 :             KOKKOS_CLASS_LAMBDA(const size_t i) { dview_m(count + i) = buf_m(i); });
                   #  # ]
      76   [ #  #  #  # ]:           0 :         Kokkos::fence();
      77                 :           0 :     }
      78                 :             : 
      79                 :             :     template <typename T, class... Properties>
      80                 :             :     // KOKKOS_INLINE_FUNCTION
      81                 :          48 :     ParticleAttrib<T, Properties...>& ParticleAttrib<T, Properties...>::operator=(T x) {
      82                 :             :         using policy_type = Kokkos::RangePolicy<execution_space>;
      83   [ +  -  +  - ]:          48 :         Kokkos::parallel_for(
      84                 :          48 :             "ParticleAttrib::operator=()", policy_type(0, *(this->localNum_mp)),
      85   [ +  -  +  -  :        3936 :             KOKKOS_CLASS_LAMBDA(const size_t i) { dview_m(i) = x; });
                   -  - ]
      86                 :          48 :         return *this;
      87                 :             :     }
      88                 :             : 
      89                 :             :     template <typename T, class... Properties>
      90                 :             :     template <typename E, size_t N>
      91                 :             :     // KOKKOS_INLINE_FUNCTION
      92                 :           0 :     ParticleAttrib<T, Properties...>& ParticleAttrib<T, Properties...>::operator=(
      93                 :             :         detail::Expression<E, N> const& expr) {
      94                 :             :         using capture_type = detail::CapturedExpression<E, N>;
      95                 :           0 :         capture_type expr_ = reinterpret_cast<const capture_type&>(expr);
      96                 :             : 
      97                 :             :         using policy_type = Kokkos::RangePolicy<execution_space>;
      98   [ #  #  #  # ]:           0 :         Kokkos::parallel_for(
      99                 :           0 :             "ParticleAttrib::operator=()", policy_type(0, *(this->localNum_mp)),
     100   [ #  #  #  #  :           0 :             KOKKOS_CLASS_LAMBDA(const size_t i) { dview_m(i) = expr_(i); });
                   #  # ]
     101                 :           0 :         return *this;
     102                 :             :     }
     103                 :             : 
     104                 :             :     template <typename T, class... Properties>
     105                 :             :     template <typename Field, class PT, typename policy_type>
     106                 :          24 :     void ParticleAttrib<T, Properties...>::scatter(
     107                 :             :         Field& f, const ParticleAttrib<Vector<PT, Field::dim>, Properties...>& pp,
     108                 :             :         policy_type iteration_policy, hash_type hash_array) const {
     109                 :          24 :         constexpr unsigned Dim = Field::dim;
     110                 :             :         using PositionType     = typename Field::Mesh_t::value_type;
     111                 :             : 
     112   [ +  -  +  -  :          24 :         static IpplTimings::TimerRef scatterTimer = IpplTimings::getTimer("scatter");
             +  -  -  - ]
     113         [ +  - ]:          24 :         IpplTimings::startTimer(scatterTimer);
     114                 :             :         using view_type = typename Field::view_type;
     115         [ +  - ]:          24 :         view_type view  = f.getView();
     116                 :             : 
     117                 :             :         using mesh_type       = typename Field::Mesh_t;
     118                 :          24 :         const mesh_type& mesh = f.get_mesh();
     119                 :             : 
     120                 :             :         using vector_type = typename mesh_type::vector_type;
     121                 :             :         using value_type  = typename ParticleAttrib<T, Properties...>::value_type;
     122                 :             : 
     123         [ +  - ]:          24 :         const vector_type& dx     = mesh.getMeshSpacing();
     124                 :          24 :         const vector_type& origin = mesh.getOrigin();
     125         [ #  # ]:          24 :         const vector_type invdx   = 1.0 / dx;
           [ +  -  +  - ]
     126                 :             : 
     127         [ +  - ]:          24 :         const FieldLayout<Dim>& layout = f.getLayout();
     128         [ +  - ]:          24 :         const NDIndex<Dim>& lDom       = layout.getLocalNDIndex();
     129                 :          24 :         const int nghost               = f.getNghost();
     130                 :             : 
     131                 :             :         //using policy_type = Kokkos::RangePolicy<execution_space>;
     132                 :          24 :         const bool useHashView = hash_array.extent(0) > 0;
     133   [ -  +  -  -  :          24 :         if (useHashView && (iteration_policy.end() > hash_array.extent(0))) {
                   -  + ]
     134         [ #  # ]:           0 :             Inform m("scatter");
     135   [ #  #  #  # ]:           0 :             m << "Hash array was passed to scatter, but size does not match iteration policy." << endl;
     136         [ #  # ]:           0 :             ippl::Comm->abort();
     137                 :           0 :         }
     138   [ +  -  +  - ]:          24 :         Kokkos::parallel_for(
     139                 :             :             "ParticleAttrib::scatter", iteration_policy,
     140   [ +  -  +  -  :        1968 :             KOKKOS_CLASS_LAMBDA(const size_t idx) {
          +  -  +  -  -  
          -  -  -  -  -  
             -  -  -  - ]
     141                 :             :                 // map index to possible hash_map
     142 [ #  # ][ -  +  :        1920 :                 size_t mapped_idx = useHashView ? hash_array(idx) : idx;
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                   -  + ]
     143                 :             : 
     144                 :             :                 // find nearest grid point
     145   [ #  #  #  #  :        1920 :                 vector_type l                        = (pp(mapped_idx) - origin) * invdx + 0.5;
             #  #  #  # ]
           [ #  #  #  #  
          #  #  #  #  #  
           # ][ +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     146 [ #  # ][ +  -  :        1920 :                 Vector<int, Field::dim> index        = l;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     147         [ #  # ]:        1920 :                 Vector<PositionType, Field::dim> whi = l - index;
           [ #  #  #  # ]
           [ +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     148         [ #  # ]:        1920 :                 Vector<PositionType, Field::dim> wlo = 1.0 - whi;
           [ #  #  #  # ]
           [ +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     149                 :             : 
     150   [ #  #  #  #  :        1920 :                 Vector<size_t, Field::dim> args = index - lDom.first() + nghost;
           #  # ][ #  #  
          #  #  #  #  #  
           # ][ +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     151                 :             : 
     152                 :             :                 // scatter
     153                 :        1920 :                 const value_type& val = dview_m(mapped_idx);
     154 [ #  # ][ +  -  :        1920 :                 detail::scatterToField(std::make_index_sequence<1 << Field::dim>{}, view, wlo, whi,
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     155                 :             :                                        args, val);
     156                 :        1920 :             });
     157         [ +  - ]:          24 :         IpplTimings::stopTimer(scatterTimer);
     158                 :             : 
     159   [ +  -  +  -  :          24 :         static IpplTimings::TimerRef accumulateHaloTimer = IpplTimings::getTimer("accumulateHalo");
             +  -  -  - ]
     160         [ +  - ]:          24 :         IpplTimings::startTimer(accumulateHaloTimer);
     161         [ +  - ]:          24 :         f.accumulateHalo();
     162         [ +  - ]:          24 :         IpplTimings::stopTimer(accumulateHaloTimer);
     163                 :          24 :     }
     164                 :             : 
     165                 :             :     template <typename T, class... Properties>
     166                 :             :     template <typename Field, typename P2>
     167                 :          12 :     void ParticleAttrib<T, Properties...>::gather(
     168                 :             :         Field& f, const ParticleAttrib<Vector<P2, Field::dim>, Properties...>& pp,
     169                 :             :         const bool addToAttribute) {
     170                 :          12 :         constexpr unsigned Dim = Field::dim;
     171                 :             :         using PositionType     = typename Field::Mesh_t::value_type;
     172                 :             : 
     173   [ +  -  +  -  :          12 :         static IpplTimings::TimerRef fillHaloTimer = IpplTimings::getTimer("fillHalo");
             +  -  -  - ]
     174         [ +  - ]:          12 :         IpplTimings::startTimer(fillHaloTimer);
     175         [ +  - ]:          12 :         f.fillHalo();
     176         [ +  - ]:          12 :         IpplTimings::stopTimer(fillHaloTimer);
     177                 :             : 
     178   [ +  -  +  -  :          12 :         static IpplTimings::TimerRef gatherTimer = IpplTimings::getTimer("gather");
             +  -  -  - ]
     179         [ +  - ]:          12 :         IpplTimings::startTimer(gatherTimer);
     180         [ +  - ]:          12 :         const typename Field::view_type view = f.getView();
     181                 :             : 
     182                 :             :         using mesh_type       = typename Field::Mesh_t;
     183                 :          12 :         const mesh_type& mesh = f.get_mesh();
     184                 :             : 
     185                 :             :         using vector_type = typename mesh_type::vector_type;
     186                 :             : 
     187         [ +  - ]:          12 :         const vector_type& dx     = mesh.getMeshSpacing();
     188                 :          12 :         const vector_type& origin = mesh.getOrigin();
     189         [ #  # ]:          12 :         const vector_type invdx   = 1.0 / dx;
           [ +  -  +  - ]
     190                 :             : 
     191         [ +  - ]:          12 :         const FieldLayout<Dim>& layout = f.getLayout();
     192         [ +  - ]:          12 :         const NDIndex<Dim>& lDom       = layout.getLocalNDIndex();
     193                 :          12 :         const int nghost               = f.getNghost();
     194                 :             : 
     195                 :             :         using policy_type = Kokkos::RangePolicy<execution_space>;
     196   [ +  -  +  - ]:          12 :         Kokkos::parallel_for(
     197                 :          12 :             "ParticleAttrib::gather", policy_type(0, *(this->localNum_mp)),
     198   [ +  -  +  -  :         408 :             KOKKOS_CLASS_LAMBDA(const size_t idx) {
          +  -  +  -  -  
          -  -  -  -  -  
             -  -  -  - ]
     199                 :             :                 // find nearest grid point
     200   [ #  #  #  #  :         384 :                 vector_type l                        = (pp(idx) - origin) * invdx + 0.5;
             #  #  #  # ]
           [ #  #  #  #  
          #  #  #  #  #  
           # ][ +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     201 [ #  # ][ +  -  :         384 :                 Vector<int, Field::dim> index        = l;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     202         [ #  # ]:         384 :                 Vector<PositionType, Field::dim> whi = l - index;
           [ #  #  #  # ]
           [ +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     203         [ #  # ]:         384 :                 Vector<PositionType, Field::dim> wlo = 1.0 - whi;
           [ #  #  #  # ]
           [ +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     204                 :             : 
     205   [ #  #  #  #  :         384 :                 Vector<size_t, Field::dim> args = index - lDom.first() + nghost;
           #  # ][ #  #  
          #  #  #  #  #  
           # ][ +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     206                 :             : 
     207                 :             :                 // gather
     208                 :           0 :                 value_type gathered = detail::gatherFromField(std::make_index_sequence<1 << Field::dim>{},
     209 [ #  # ][ +  -  :         384 :                                                               view, wlo, whi, args);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     210 [ #  # ][ -  +  :         384 :                 if (addToAttribute) {
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                   -  + ]
     211                 :           0 :                     dview_m(idx) += gathered;
     212                 :             :                 } else {
     213                 :         768 :                     dview_m(idx)  = gathered;
     214                 :             :                 }
     215                 :         384 :             });
     216         [ +  - ]:          12 :         IpplTimings::stopTimer(gatherTimer);
     217                 :          12 :     }
     218                 :             : 
     219                 :             :     /*
     220                 :             :      * Non-class function
     221                 :             :      *
     222                 :             :      */
     223                 :             : 
     224                 :             :     /**
     225                 :             :      * @brief Non-class interface for scattering particle attribute data onto a field.
     226                 :             :      *
     227                 :             :      * This overload preserves legacy functionality by providing a default iteration policy.
     228                 :             :      * It calls the member scatter() with a default Kokkos::RangePolicy.
     229                 :             :      * 
     230                 :             :      * @note The default behaviour is to scatter all particles without any custom index mapping.
     231                 :             :      *
     232                 :             :      * @tparam Attrib1 The type of the particle attribute.
     233                 :             :      * @tparam Field The type of the field.
     234                 :             :      * @tparam Attrib2 The type of the particle position attribute.
     235                 :             :      * @tparam policy_type (Default: `Kokkos::RangePolicy<typename Field::execution_space>`)
     236                 :             :      * @param attrib The particle attribute to scatter.
     237                 :             :      * @param f The field onto which the data is scattered.
     238                 :             :      * @param pp The ParticleAttrib representing particle positions.
     239                 :             :      */
     240                 :             :     template <typename Attrib1, typename Field, typename Attrib2, 
     241                 :             :                 typename policy_type = Kokkos::RangePolicy<typename Field::execution_space>>
     242                 :          24 :     inline void scatter(const Attrib1& attrib, Field& f, const Attrib2& pp) {
     243   [ +  -  +  -  :          24 :         attrib.scatter(f, pp, policy_type(0, attrib.getParticleCount())); 
                   +  - ]
     244                 :          24 :     }
     245                 :             : 
     246                 :             :     /**
     247                 :             :      * @brief Non-class interface for scattering with a custom iteration policy and optional index array.
     248                 :             :      *
     249                 :             :      * This overload allows the caller to specify a custom `Kokkos::range_policy` and an optional
     250                 :             :      * `ippl::hash_type` array. It forwards the parameters to the member scatter() function.
     251                 :             :      * 
     252                 :             :      * @note See ParticleAttrib::scatter() for more information on the custom iteration functionality.
     253                 :             :      *
     254                 :             :      * @tparam Attrib1 The type of the particle attribute.
     255                 :             :      * @tparam Field The type of the field.
     256                 :             :      * @tparam Attrib2 The type of the particle position attribute.
     257                 :             :      * @tparam policy_type (Default: `Kokkos::RangePolicy<typename Field::execution_space>`)
     258                 :             :      * @param attrib The particle attribute to scatter.
     259                 :             :      * @param f The field onto which the data is scattered.
     260                 :             :      * @param pp The ParticleAttrib representing particle positions.
     261                 :             :      * @param iteration_policy A custom `Kokkos::range_policy` defining the iteration range.
     262                 :             :      * @param hash_array An optional `ippl::hash_type` array for index mapping.
     263                 :             :      */
     264                 :             :     template <typename Attrib1, typename Field, typename Attrib2, 
     265                 :             :                 typename policy_type = Kokkos::RangePolicy<typename Field::execution_space>>
     266                 :             :     inline void scatter(const Attrib1& attrib, Field& f, const Attrib2& pp, 
     267                 :             :                         policy_type iteration_policy, typename Attrib1::hash_type hash_array = {}) {
     268                 :             :         attrib.scatter(f, pp, iteration_policy, hash_array);
     269                 :             :     }
     270                 :             : 
     271                 :             :     /**
     272                 :             :      * @brief Non-class interface for gathering field data into a particle attribute.
     273                 :             :      * 
     274                 :             :      * This interface calls the member ParticleAttrib::gather() function with the provided
     275                 :             :      * parameters and preserving legacy behavior by assigning `addToAttribute` a default value.
     276                 :             :      * 
     277                 :             :      * @note See ParticleAttrib::gather() for more information on the behavior of `addToAttribute`.
     278                 :             :      * 
     279                 :             :      * @tparam Attrib1 The type of the particle attribute.
     280                 :             :      * @tparam Field The type of the field.
     281                 :             :      * @tparam Attrib2 The type of the particle position attribute.
     282                 :             :      * @param attrib The particle attribute to gather data into.
     283                 :             :      * @param f The field from which data is gathered.
     284                 :             :      * @param pp The ParticleAttrib representing particle positions.
     285                 :             :      * @param addToAttribute If true, the gathered field value is added to the current attribute value;
     286                 :             :      *                       otherwise, the attribute value is overwritten.
     287                 :             :      */
     288                 :             :     template <typename Attrib1, typename Field, typename Attrib2>
     289                 :          12 :     inline void gather(Attrib1& attrib, Field& f, const Attrib2& pp, 
     290                 :             :                         const bool addToAttribute = false) {
     291                 :          12 :         attrib.gather(f, pp, addToAttribute);
     292                 :          12 :     }
     293                 :             : 
     294                 :             : #define DefineParticleReduction(fun, name, op, MPI_Op)            \
     295                 :             :     template <typename T, class... Properties>                    \
     296                 :             :     T ParticleAttrib<T, Properties...>::name() {                  \
     297                 :             :         T temp            = 0.0;                                  \
     298                 :             :         using policy_type = Kokkos::RangePolicy<execution_space>; \
     299                 :             :         Kokkos::parallel_reduce(                                  \
     300                 :             :             "fun", policy_type(0, *(this->localNum_mp)),          \
     301                 :             :             KOKKOS_CLASS_LAMBDA(const size_t i, T& valL) {        \
     302                 :             :                 T myVal = dview_m(i);                             \
     303                 :             :                 op;                                               \
     304                 :             :             },                                                    \
     305                 :             :             Kokkos::fun<T>(temp));                                \
     306                 :             :         T globaltemp = 0.0;                                       \
     307                 :             :         Comm->allreduce(temp, globaltemp, 1, MPI_Op<T>());        \
     308                 :             :         return globaltemp;                                        \
     309                 :             :     }
     310                 :             : 
     311   [ +  -  +  -  :         432 :     DefineParticleReduction(Sum, sum, valL += myVal, std::plus)
          +  -  +  -  +  
                -  +  - ]
     312                 :             :     DefineParticleReduction(Max, max, if (myVal > valL) valL = myVal, std::greater)
     313                 :             :     DefineParticleReduction(Min, min, if (myVal < valL) valL = myVal, std::less)
     314                 :             :     DefineParticleReduction(Prod, prod, valL *= myVal, std::multiplies)
     315                 :             : }  // namespace ippl
        

Generated by: LCOV version 2.0-1