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 LField 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 : #ifndef IPPL_PARTICLE_ATTRIB_H
17 : #define IPPL_PARTICLE_ATTRIB_H
18 :
19 : #include "Expression/IpplExpressions.h"
20 :
21 : #include "Interpolation/CIC.h"
22 : #include "Particle/ParticleAttribBase.h"
23 :
24 : namespace ippl {
25 :
26 : // ParticleAttrib class definition
27 : template <typename T, class... Properties>
28 : class ParticleAttrib : public detail::ParticleAttribBase<>::with_properties<Properties...>,
29 : public detail::Expression<
30 : ParticleAttrib<T, Properties...>,
31 : sizeof(typename detail::ViewType<T, 1, Properties...>::view_type)> {
32 : public:
33 : typedef T value_type;
34 : constexpr static unsigned dim = 1;
35 :
36 : using Base = typename detail::ParticleAttribBase<>::with_properties<Properties...>;
37 :
38 : using hash_type = typename Base::hash_type;
39 :
40 : using view_type = typename detail::ViewType<T, 1, Properties...>::view_type;
41 :
42 : using HostMirror = typename view_type::host_mirror_type;
43 :
44 : using memory_space = typename view_type::memory_space;
45 : using execution_space = typename view_type::execution_space;
46 :
47 : using size_type = detail::size_type;
48 :
49 : // Create storage for M particle attributes. The storage is uninitialized.
50 : // New items are appended to the end of the array.
51 : void create(size_type) override;
52 :
53 : /*!
54 : * Particle deletion function. Partition the particles into a valid region
55 : * and an invalid region.
56 : * @param deleteIndex List of indices of invalid particles in the valid region
57 : * @param keepIndex List of indices of valid particles in the invalid region
58 : * @param invalidCount Number of invalid particles in the valid region
59 : */
60 : void destroy(const hash_type& deleteIndex, const hash_type& keepIndex,
61 : size_type invalidCount) override;
62 :
63 : void pack(const hash_type&) override;
64 :
65 : void unpack(size_type) override;
66 :
67 0 : void serialize(detail::Archive<memory_space>& ar, size_type nsends) override {
68 0 : ar.serialize(buf_m, nsends);
69 0 : }
70 :
71 0 : void deserialize(detail::Archive<memory_space>& ar, size_type nrecvs) override {
72 0 : ar.deserialize(buf_m, nrecvs);
73 0 : }
74 :
75 864 : virtual ~ParticleAttrib() = default;
76 :
77 264 : size_type size() const override { return dview_m.extent(0); }
78 :
79 0 : size_type packedSize(const size_type count) const override {
80 0 : return count * sizeof(value_type);
81 : }
82 :
83 0 : void resize(size_type n) { Kokkos::resize(dview_m, n); }
84 :
85 252 : void realloc(size_type n) { Kokkos::realloc(dview_m, n); }
86 :
87 0 : void print() {
88 0 : HostMirror hview = Kokkos::create_mirror_view(dview_m);
89 0 : Kokkos::deep_copy(hview, dview_m);
90 0 : for (size_type i = 0; i < *(this->localNum_mp); ++i) {
91 0 : std::cout << hview(i) << std::endl;
92 : }
93 0 : }
94 :
95 10752 : KOKKOS_INLINE_FUNCTION T& operator()(const size_t i) const { return dview_m(i); }
96 :
97 324 : view_type& getView() { return dview_m; }
98 :
99 462 : const view_type& getView() const { return dview_m; }
100 :
101 180 : HostMirror getHostMirror() { return Kokkos::create_mirror(dview_m); }
102 :
103 : /*!
104 : * Assign the same value to the whole attribute.
105 : */
106 : // KOKKOS_INLINE_FUNCTION
107 : ParticleAttrib<T, Properties...>& operator=(T x);
108 :
109 : /*!
110 : * Assign an arbitrary particle attribute expression
111 : * @tparam E expression type
112 : * @tparam N size of the expression, this is necessary for running on the
113 : * device since otherwise it does not allocate enough memory
114 : * @param expr is the expression
115 : */
116 : template <typename E, size_t N>
117 : // KOKKOS_INLINE_FUNCTION
118 : ParticleAttrib<T, Properties...>& operator=(detail::Expression<E, N> const& expr);
119 :
120 : /**
121 : * @brief Scatter particle attribute data onto a field.
122 : *
123 : * This function scatters data from this attribute onto the given field,
124 : * using the given position attribute.
125 : * The function can be used together with a custom iteration policy to iterate
126 : * over a specified range and, optionally, an `ippl::hash_type` array to remap
127 : * iteration indices.
128 : *
129 : * When a non-empty `hash_array` is provided, the function:
130 : * - Checks that the iteration policy's range does not exceed the size of `hash_array`.
131 : * - Maps the current index to the appropriate index using the `hash_array`.
132 : * - Careful: access pattern optimization might be lost when using `hash_array`.
133 : *
134 : * @note This custom iteration functionality is needed to support energy binning
135 : * in the field solver of OPAL-X, allowing only particles within a specific bin
136 : * to be scattered.
137 : *
138 : * @tparam Field The type of the field.
139 : * @tparam P2 The type for the position attribute.
140 : * @tparam policy_type The type of the Kokkos iteration policy when using `hash_array`.
141 : * @param f The field onto which the particle data is scattered.
142 : * @param pp The ParticleAttrib representing particle positions.
143 : * @param iteration_policy A custom `Kokkos::range_policy` defining the iteration range.
144 : * @param hash_array An optional `ippl::hash_type` array for index mapping. If empty, no map is used.
145 : */
146 : template <typename Field, typename P2, typename policy_type>
147 : void scatter(Field& f,
148 : const ParticleAttrib<Vector<P2, Field::dim>, Properties...>& pp,
149 : policy_type iteration_policy, hash_type hash_array = {}) const;
150 :
151 : /**
152 : * @brief Gather field data into the particle attribute.
153 : *
154 : * This function gathers data from the given field into the particle attribute
155 : * by iterating over all particles. Depending on the parameter @p addToAttribute,
156 : * the gathered field value is either added to the existing attribute value (using "+=")
157 : * or used to overwrite the attribute value.
158 : *
159 : * @note This behavior exists to give the OPAL-X field solver the ablity to gather field data
160 : * per "energy bin".
161 : *
162 : * @tparam Field The type of the field.
163 : * @tparam P2 The particle type for the position attribute.
164 : * @param f The field from which data is gathered.
165 : * @param pp The ParticleAttrib representing particle positions.
166 : * @param addToAttribute If `true`, the gathered value is added to the current attribute value;
167 : * otherwise, the attribute value is overwritten.
168 : */
169 : template <typename Field, typename P2>
170 : void gather(Field& f, const ParticleAttrib<Vector<P2, Field::dim>, Properties...>& pp,
171 : const bool addToAttribute = false);
172 :
173 : T sum();
174 : T max();
175 : T min();
176 : T prod();
177 :
178 : private:
179 : view_type dview_m;
180 : view_type buf_m;
181 : };
182 : } // namespace ippl
183 :
184 : #include "Particle/ParticleAttrib.hpp"
185 :
186 : #endif
|