WarpX
Loading...
Searching...
No Matches
ParticleCreationFunc.H
Go to the documentation of this file.
1/* Copyright 2021 Neil Zaim
2 *
3 * This file is part of WarpX.
4 *
5 * License: BSD-3-Clause-LBNL
6 */
7
8#ifndef WARPX_PARTICLE_CREATION_FUNC_H_
9#define WARPX_PARTICLE_CREATION_FUNC_H_
10
12
20
21#include <AMReX_DenseBins.H>
22#include <AMReX_GpuAtomic.H>
23#include <AMReX_GpuDevice.H>
24#include <AMReX_GpuContainers.H>
25#include <AMReX_INT.H>
26#include <AMReX_Random.H>
27#include <AMReX_REAL.H>
28#include <AMReX_Vector.H>
29
35{
36 // Define shortcuts for frequently-used type names
39 using ParticleTileDataType = typename ParticleTileType::ParticleTileDataType;
42 using SoaData_type = typename WarpXParticleContainer::ParticleTileType::ParticleTileDataType;
43
44public:
49
56 ParticleCreationFunc (const std::string& collision_name, MultiParticleContainer const * mypc);
57
98 const index_type& n_total_pairs,
99 ParticleTileType& ptile1, ParticleTileType& ptile2,
101 ParticleTileType** AMREX_RESTRICT tile_products,
102 const amrex::ParticleReal& m1, const amrex::ParticleReal& m2,
103 const amrex::Vector<amrex::ParticleReal>& products_mass,
104 const index_type* AMREX_RESTRICT p_mask,
105 const amrex::Vector<index_type>& products_np,
106 const SmartCopy* AMREX_RESTRICT copy_species1,
107 const SmartCopy* AMREX_RESTRICT copy_species2,
108 const index_type* AMREX_RESTRICT p_pair_indices_1,
109 const index_type* AMREX_RESTRICT p_pair_indices_2,
110 const amrex::ParticleReal* AMREX_RESTRICT p_pair_reaction_weight,
111 const amrex::ParticleReal* /*p_product_data*/
112 ) const
113 {
114 using namespace amrex::literals;
115
116 if (n_total_pairs == 0) { return amrex::Vector<int>(m_num_product_species, 0); }
117
118 // Compute offset array and allocate memory for the produced species
119 amrex::Gpu::DeviceVector<index_type> offsets(n_total_pairs);
120 const auto total = amrex::Scan::ExclusiveSum(n_total_pairs, p_mask, offsets.data());
121 const index_type* AMREX_RESTRICT p_offsets = offsets.dataPtr();
123 for (int i = 0; i < m_num_product_species; i++)
124 {
125 // How many particles of product species i are created.
126 // Factor 2 is here because we currently create one product species at the position of
127 // each source particle of the binary collision. E.g., if a binary collision produces
128 // one electron, we create two electrons, one at the position of each particle that
129 // collided. This allows for exact charge conservation.
130 const index_type num_added = total * m_num_products_host[i] * 2;
131 num_added_vec[i] = static_cast<int>(num_added);
132 tile_products[i]->resize(products_np[i] + num_added);
133 }
134
135 const auto soa_1 = ptile1.getParticleTileData();
136 const auto soa_2 = ptile2.getParticleTileData();
137
138 // Create necessary GPU vectors, that will be used in the kernel below
139 amrex::Vector<SoaData_type> soa_products;
140 for (int i = 0; i < m_num_product_species; i++)
141 {
142 soa_products.push_back(tile_products[i]->getParticleTileData());
143 }
144#ifdef AMREX_USE_GPU
149 soa_products.end(),
150 device_soa_products.begin());
152 products_np.end(),
153 device_products_np.begin());
154 amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, products_mass.begin(),
155 products_mass.end(),
156 device_products_mass.begin());
158 SoaData_type* AMREX_RESTRICT soa_products_data = device_soa_products.data();
159 const index_type* AMREX_RESTRICT products_np_data = device_products_np.data();
160 const amrex::ParticleReal* AMREX_RESTRICT products_mass_data = device_products_mass.data();
161#else
162 SoaData_type* AMREX_RESTRICT soa_products_data = soa_products.data();
163 const index_type* AMREX_RESTRICT products_np_data = products_np.data();
164 const amrex::ParticleReal* AMREX_RESTRICT products_mass_data = products_mass.data();
165#endif
166
167 const int t_num_product_species = m_num_product_species;
168 const int* AMREX_RESTRICT p_num_products_device = m_num_products_device.data();
169 const CollisionType t_collision_type = m_collision_type;
170
171 amrex::ParallelForRNG(n_total_pairs,
172 [=] AMREX_GPU_DEVICE (int i, amrex::RandomEngine const& engine) noexcept
173 {
174 if (p_mask[i])
175 {
176 for (int j = 0; j < t_num_product_species; j++)
177 {
178 for (int k = 0; k < p_num_products_device[j]; k++)
179 {
180 // Factor 2 is here because we create one product species at the position
181 // of each source particle
182 const auto product_index = products_np_data[j] +
183 2*(p_offsets[i]*p_num_products_device[j] + k);
184 // Create product particle at position of particle 1
185 copy_species1[j](soa_products_data[j], soa_1, static_cast<int>(p_pair_indices_1[i]),
186 static_cast<int>(product_index), engine);
187 // Create another product particle at position of particle 2
188 copy_species2[j](soa_products_data[j], soa_2, static_cast<int>(p_pair_indices_2[i]),
189 static_cast<int>(product_index + 1), engine);
190
191 // Set the weight of the new particles to p_pair_reaction_weight[i]/2
192 soa_products_data[j].m_rdata[PIdx::w][product_index] =
193 p_pair_reaction_weight[i]/amrex::ParticleReal(2.);
194 soa_products_data[j].m_rdata[PIdx::w][product_index + 1] =
195 p_pair_reaction_weight[i]/amrex::ParticleReal(2.);
196 }
197 }
198
199 // Initialize the product particles' momentum, using a function depending on the
200 // specific collision type
201 if (t_collision_type == CollisionType::ProtonBoronToAlphasFusion)
202 {
203 const index_type product_start_index = products_np_data[0] + 2*p_offsets[i]*
204 p_num_products_device[0];
205 ProtonBoronFusionInitializeMomentum(soa_1, soa_2, soa_products_data[0],
206 p_pair_indices_1[i], p_pair_indices_2[i],
207 product_start_index, m1, m2, engine);
208 }
209 else if ((t_collision_type == CollisionType::DeuteriumTritiumToNeutronHeliumFusion)
212 {
213 amrex::ParticleReal fusion_energy = 0.0_prt;
215 fusion_energy = 17.5893e6_prt * PhysConst::q_e;
216 }
217 else if (t_collision_type == CollisionType::DeuteriumDeuteriumToProtonTritiumFusion) {
218 fusion_energy = 4.032667e6_prt * PhysConst::q_e;
219 }
220 else if (t_collision_type == CollisionType::DeuteriumDeuteriumToNeutronHeliumFusion) {
221 fusion_energy = 3.268911e6_prt * PhysConst::q_e;
222 }
223 TwoProductFusionInitializeMomentum(soa_1, soa_2,
224 soa_products_data[0], soa_products_data[1],
225 p_pair_indices_1[i], p_pair_indices_2[i],
226 products_np_data[0] + 2*p_offsets[i]*p_num_products_device[0],
227 products_np_data[1] + 2*p_offsets[i]*p_num_products_device[1],
228 m1, m2, products_mass_data[0], products_mass_data[1], fusion_energy, engine);
229 }
230 else if(t_collision_type == CollisionType::LinearBreitWheeler){
231 LinearBreitWheelerInitializeMomentum(soa_1, soa_2,
232 soa_products_data[0], soa_products_data[1],
233 p_pair_indices_1[i], p_pair_indices_2[i],
234 products_np_data[0] + 2*p_offsets[i]*p_num_products_device[0],
235 products_np_data[1] + 2*p_offsets[i]*p_num_products_device[1],
236 engine);
237 }
238 else if(t_collision_type == CollisionType::LinearCompton){
239 LinearComptonInitializeMomentum(soa_1, soa_2,
240 soa_products_data[0], soa_products_data[1],
241 p_pair_indices_1[i], p_pair_indices_2[i],
242 products_np_data[0] + 2*p_offsets[i]*p_num_products_device[0],
243 products_np_data[1] + 2*p_offsets[i]*p_num_products_device[1],
244 engine);
245 }
246 }
247 });
248
249 // Initialize the user runtime components
250 for (int i = 0; i < m_num_product_species; i++)
251 {
252 const auto start_index = int(products_np[i]);
253 const auto stop_index = int(products_np[i] + num_added_vec[i]);
255 0, 0,
256 pc_products[i]->getUserRealAttribs(), pc_products[i]->getUserIntAttribs(),
257 pc_products[i]->GetRealSoANames(), pc_products[i]->GetIntSoANames(),
258 pc_products[i]->getUserRealAttribParser(),
259 pc_products[i]->getUserIntAttribParser(),
260#ifdef WARPX_QED
261 false, // do not initialize QED quantities, since they were initialized
262 // when calling the SmartCopy functors
263 pc_products[i]->get_breit_wheeler_engine_ptr(),
264 pc_products[i]->get_quantum_sync_engine_ptr(),
265#endif
266 pc_products[i]->getIonizationInitialLevel(),
267 start_index, stop_index);
268 }
269
271
272 return num_added_vec;
273 }
274
275private:
276 // How many different type of species the collision produces
278 // Vectors of size m_num_product_species storing how many particles of a given species are
279 // produced by a collision event. These vectors are duplicated (one version for host and one
280 // for device) which is necessary with GPUs but redundant on CPU.
284};
285
286
292{
295 using ParticleTileDataType = typename ParticleTileType::ParticleTileDataType;
298 using SoaData_type = typename WarpXParticleContainer::ParticleTileType::ParticleTileDataType;
299
300public:
302
303 NoParticleCreationFunc (const std::string& /*collision_name*/,
304 MultiParticleContainer const * const /*mypc*/) {}
305
308 const index_type& /*n_total_pairs*/,
309 ParticleTileType& /*ptile1*/, ParticleTileType& /*ptile2*/,
311 ParticleTileType** /*tile_products*/,
312 const amrex::ParticleReal& /*m1*/, const amrex::ParticleReal& /*m2*/,
313 const amrex::Vector<amrex::ParticleReal>& /*products_mass*/,
314 const index_type* /*p_mask*/, const amrex::Vector<index_type>& /*products_np*/,
315 const SmartCopy* /*copy_species1*/, const SmartCopy* /*copy_species2*/,
316 const index_type* /*p_pair_indices_1*/, const index_type* /*p_pair_indices_2*/,
317 const amrex::ParticleReal* /*p_pair_reaction_weight*/,
318 const amrex::ParticleReal* AMREX_RESTRICT /*p_product_data*/
319 ) const
320 {
321 return {};
322 }
323};
324
325#endif // WARPX_PARTICLE_CREATION_FUNC_H_
#define AMREX_RESTRICT
#define AMREX_INLINE
#define AMREX_GPU_DEVICE
CollisionType
Definition BinaryCollisionUtils.H:17
@ LinearBreitWheeler
Definition BinaryCollisionUtils.H:25
@ ProtonBoronToAlphasFusion
Definition BinaryCollisionUtils.H:21
@ DeuteriumDeuteriumToProtonTritiumFusion
Definition BinaryCollisionUtils.H:18
@ DeuteriumDeuteriumToNeutronHeliumFusion
Definition BinaryCollisionUtils.H:19
@ DeuteriumTritiumToNeutronHeliumFusion
Definition BinaryCollisionUtils.H:17
@ LinearCompton
Definition BinaryCollisionUtils.H:26
Definition MultiParticleContainer.H:68
typename WarpXParticleContainer::ParticleType ParticleType
Definition ParticleCreationFunc.H:293
NoParticleCreationFunc(const std::string &, MultiParticleContainer const *const)
Definition ParticleCreationFunc.H:303
AMREX_INLINE amrex::Vector< int > operator()(const index_type &, ParticleTileType &, ParticleTileType &, amrex::Vector< WarpXParticleContainer * > &, ParticleTileType **, const amrex::ParticleReal &, const amrex::ParticleReal &, const amrex::Vector< amrex::ParticleReal > &, const index_type *, const amrex::Vector< index_type > &, const SmartCopy *, const SmartCopy *, const index_type *, const index_type *, const amrex::ParticleReal *, const amrex::ParticleReal *AMREX_RESTRICT) const
Definition ParticleCreationFunc.H:307
typename ParticleBins::index_type index_type
Definition ParticleCreationFunc.H:297
NoParticleCreationFunc()=default
amrex::DenseBins< ParticleTileDataType > ParticleBins
Definition ParticleCreationFunc.H:296
typename WarpXParticleContainer::ParticleTileType ParticleTileType
Definition ParticleCreationFunc.H:294
typename ParticleTileType::ParticleTileDataType ParticleTileDataType
Definition ParticleCreationFunc.H:295
typename WarpXParticleContainer::ParticleTileType::ParticleTileDataType SoaData_type
Definition ParticleCreationFunc.H:298
CollisionType m_collision_type
Definition ParticleCreationFunc.H:283
amrex::DenseBins< ParticleTileDataType > ParticleBins
Definition ParticleCreationFunc.H:40
int m_num_product_species
Definition ParticleCreationFunc.H:277
amrex::Gpu::DeviceVector< int > m_num_products_device
Definition ParticleCreationFunc.H:281
typename ParticleTileType::ParticleTileDataType ParticleTileDataType
Definition ParticleCreationFunc.H:39
typename WarpXParticleContainer::ParticleType ParticleType
Definition ParticleCreationFunc.H:37
typename ParticleBins::index_type index_type
Definition ParticleCreationFunc.H:41
AMREX_INLINE amrex::Vector< int > operator()(const index_type &n_total_pairs, ParticleTileType &ptile1, ParticleTileType &ptile2, const amrex::Vector< WarpXParticleContainer * > &pc_products, ParticleTileType **AMREX_RESTRICT tile_products, const amrex::ParticleReal &m1, const amrex::ParticleReal &m2, const amrex::Vector< amrex::ParticleReal > &products_mass, const index_type *AMREX_RESTRICT p_mask, const amrex::Vector< index_type > &products_np, const SmartCopy *AMREX_RESTRICT copy_species1, const SmartCopy *AMREX_RESTRICT copy_species2, const index_type *AMREX_RESTRICT p_pair_indices_1, const index_type *AMREX_RESTRICT p_pair_indices_2, const amrex::ParticleReal *AMREX_RESTRICT p_pair_reaction_weight, const amrex::ParticleReal *) const
operator() of the ParticleCreationFunc class. It creates new particles from binary collisions....
Definition ParticleCreationFunc.H:97
typename WarpXParticleContainer::ParticleTileType ParticleTileType
Definition ParticleCreationFunc.H:38
ParticleCreationFunc()=default
Default constructor of the ParticleCreationFunc class.
typename WarpXParticleContainer::ParticleTileType::ParticleTileDataType SoaData_type
Definition ParticleCreationFunc.H:42
amrex::Gpu::HostVector< int > m_num_products_host
Definition ParticleCreationFunc.H:282
iterator begin() noexcept
T * dataPtr() noexcept
T * data() noexcept
void DefaultInitializeRuntimeAttributes(PTile &ptile, const int n_external_attr_real, const int n_external_attr_int, const std::vector< std::string > &user_real_attribs, const std::vector< std::string > &user_int_attribs, const std::vector< std::string > &particle_comps, const std::vector< std::string > &particle_icomps, const std::vector< amrex::Parser * > &user_real_attrib_parser, const std::vector< amrex::Parser * > &user_int_attrib_parser, const bool do_qed_comps, BreitWheelerEngine *p_bw_engine, QuantumSynchrotronEngine *p_qs_engine, const int ionization_initial_level, int start, int stop)
Default initialize runtime attributes in a tile. This routine does not initialize the first n_externa...
Definition DefaultInitialization.H:118
constexpr auto q_e
elementary charge [C]
Definition constant.H:158
void synchronize() noexcept
PinnedVector< T > HostVector
void copyAsync(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
static constexpr HostToDevice hostToDevice
void streamSynchronize() noexcept
PODVector< T, ArenaAllocator< T > > DeviceVector
T ExclusiveSum(N n, T const *in, T *out, RetSum a_ret_sum=retSum)
AMREX_ATTRIBUTE_FLATTEN_FOR void ParallelForRNG(T n, L const &f) noexcept
@ w
Definition WarpXParticleContainer.H:70
This is a functor for performing a "smart copy" that works in both host and device code.
Definition SmartCopy.H:34