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
100 const index_type& n_total_pairs,
101 ParticleTileType& ptile1, ParticleTileType& ptile2,
103 ParticleTileType** AMREX_RESTRICT tile_products,
104 const amrex::ParticleReal& m1, const amrex::ParticleReal& m2,
105 const amrex::Vector<amrex::ParticleReal>& products_mass,
106 const index_type* AMREX_RESTRICT p_mask,
107 const amrex::Vector<index_type>& products_np,
108 const SmartCopy* AMREX_RESTRICT copy_species1,
109 const SmartCopy* AMREX_RESTRICT copy_species2,
110 const index_type* AMREX_RESTRICT p_pair_indices_1,
111 const index_type* AMREX_RESTRICT p_pair_indices_2,
112 const amrex::ParticleReal* AMREX_RESTRICT p_pair_reaction_weight,
113 const amrex::ParticleReal* /*p_product_data*/
114 ) const
115 {
116 using namespace amrex::literals;
117
118 if (n_total_pairs == 0) { return amrex::Vector<int>(m_num_product_species, 0); }
119
120 // Compute offset array and allocate memory for the produced species
121 amrex::Gpu::DeviceVector<index_type> offsets(n_total_pairs);
122 const auto total = amrex::Scan::ExclusiveSum(n_total_pairs, p_mask, offsets.data());
123 const index_type* AMREX_RESTRICT p_offsets = offsets.dataPtr();
124 // How many particles of each product species are created.
125 // Linear Compton: one macroparticle per product species
126 // (one product photon at reactant photon position, same for electron)
127 // All other binary processes: create one product particle at
128 // the position of each reacting particles (factor 2).
129 // E.g., if a binary collision produces one electron, we create two electrons,
130 // one at the position of each particle that collided.
131 // This allows for exact charge conservation.
132 const int products_per_reactant_factor =
135 for (int i = 0; i < m_num_product_species; i++)
136 {
137 const index_type num_added = total * m_num_products_host[i] * products_per_reactant_factor;
138 num_added_vec[i] = static_cast<int>(num_added);
139 tile_products[i]->resize(products_np[i] + num_added);
140 }
141
142 const auto soa_1 = ptile1.getParticleTileData();
143 const auto soa_2 = ptile2.getParticleTileData();
144
145 // Create necessary GPU vectors, that will be used in the kernel below
146 amrex::Vector<SoaData_type> soa_products;
147 for (int i = 0; i < m_num_product_species; i++)
148 {
149 soa_products.push_back(tile_products[i]->getParticleTileData());
150 }
151#ifdef AMREX_USE_GPU
156 soa_products.end(),
157 device_soa_products.begin());
159 products_np.end(),
160 device_products_np.begin());
161 amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, products_mass.begin(),
162 products_mass.end(),
163 device_products_mass.begin());
165 SoaData_type* AMREX_RESTRICT soa_products_data = device_soa_products.data();
166 const index_type* AMREX_RESTRICT products_np_data = device_products_np.data();
167 const amrex::ParticleReal* AMREX_RESTRICT products_mass_data = device_products_mass.data();
168#else
169 SoaData_type* AMREX_RESTRICT soa_products_data = soa_products.data();
170 const index_type* AMREX_RESTRICT products_np_data = products_np.data();
171 const amrex::ParticleReal* AMREX_RESTRICT products_mass_data = products_mass.data();
172#endif
173
174 const int t_num_product_species = m_num_product_species;
175 const int* AMREX_RESTRICT p_num_products_device = m_num_products_device.data();
176 const CollisionType t_collision_type = m_collision_type;
177 const ScatteringAngleModel t_scattering_angle_model = m_scattering_angle_model;
178
179 amrex::ParallelForRNG(n_total_pairs,
180 [=] AMREX_GPU_DEVICE (int i, amrex::RandomEngine const& engine) noexcept
181 {
182 if (p_mask[i])
183 {
184 for (int j = 0; j < t_num_product_species; j++)
185 {
186 for (int k = 0; k < p_num_products_device[j]; k++)
187 {
188 if (t_collision_type == CollisionType::LinearCompton)
189 {
190 // Linear Compton only: one macroparticle per product species,
191 // first at first reactant position, second at second.
192 const auto product_index = products_np_data[j] +
193 (p_offsets[i]*p_num_products_device[j] + k);
194 if (j == 0) // first product: photon
195 {
196 copy_species1[j](soa_products_data[j], soa_1,
197 static_cast<int>(p_pair_indices_1[i]),
198 static_cast<int>(product_index), engine);
199 }
200 else if (j == 1) // second product: electron
201 {
202 copy_species2[j](soa_products_data[j], soa_2,
203 static_cast<int>(p_pair_indices_2[i]),
204 static_cast<int>(product_index), engine);
205 }
206 soa_products_data[j].m_rdata[PIdx::w][product_index] =
207 p_pair_reaction_weight[i];
208 }
209 else
210 {
211 // Create one product at the position of each source particle
212 const auto product_index = products_np_data[j] +
213 2*(p_offsets[i]*p_num_products_device[j] + k);
214 copy_species1[j](soa_products_data[j], soa_1,
215 static_cast<int>(p_pair_indices_1[i]),
216 static_cast<int>(product_index), engine);
217 copy_species2[j](soa_products_data[j], soa_2,
218 static_cast<int>(p_pair_indices_2[i]),
219 static_cast<int>(product_index + 1), engine);
220 soa_products_data[j].m_rdata[PIdx::w][product_index] =
221 p_pair_reaction_weight[i]/amrex::ParticleReal(2.);
222 soa_products_data[j].m_rdata[PIdx::w][product_index + 1] =
223 p_pair_reaction_weight[i]/amrex::ParticleReal(2.);
224 }
225 }
226 }
227
228 // Initialize the product particles' momentum, using a function depending on the
229 // specific collision type
230 if (t_collision_type == CollisionType::ProtonBoronToAlphasFusion)
231 {
232 const index_type product_start_index = products_np_data[0] + 2*p_offsets[i]*
233 p_num_products_device[0];
234 ProtonBoronFusionInitializeMomentum(soa_1, soa_2, soa_products_data[0],
235 p_pair_indices_1[i], p_pair_indices_2[i],
236 product_start_index, m1, m2,
237 t_scattering_angle_model, engine);
238 }
239 else if (BinaryCollisionUtils::is_two_product_fusion_type(t_collision_type))
240 {
241 const amrex::ParticleReal mass_before = m1 + m2;
242 const amrex::ParticleReal mass_after = products_mass_data[0] + products_mass_data[1];
243 const amrex::ParticleReal fusion_energy = (mass_before - mass_after)*PhysConst::c2;
244 TwoProductFusionInitializeMomentum(soa_1, soa_2,
245 soa_products_data[0], soa_products_data[1],
246 p_pair_indices_1[i], p_pair_indices_2[i],
247 products_np_data[0] + 2*p_offsets[i]*p_num_products_device[0],
248 products_np_data[1] + 2*p_offsets[i]*p_num_products_device[1],
249 m1, m2, products_mass_data[0], products_mass_data[1], fusion_energy,
250 t_scattering_angle_model, engine);
251 }
252 else if(t_collision_type == CollisionType::LinearBreitWheeler){
253 LinearBreitWheelerInitializeMomentum(soa_1, soa_2,
254 soa_products_data[0], soa_products_data[1],
255 p_pair_indices_1[i], p_pair_indices_2[i],
256 products_np_data[0] + 2*p_offsets[i]*p_num_products_device[0],
257 products_np_data[1] + 2*p_offsets[i]*p_num_products_device[1],
258 engine);
259 }
260 else if(t_collision_type == CollisionType::LinearCompton){
261 LinearComptonInitializeMomentum(soa_1, soa_2,
262 soa_products_data[0], soa_products_data[1],
263 p_pair_indices_1[i], p_pair_indices_2[i],
264 products_np_data[0] + p_offsets[i]*p_num_products_device[0],
265 products_np_data[1] + p_offsets[i]*p_num_products_device[1],
266 engine);
267 }
268 }
269 });
270
271 // Initialize the user runtime components
272 for (int i = 0; i < m_num_product_species; i++)
273 {
274 const auto start_index = int(products_np[i]);
275 const auto stop_index = int(products_np[i] + num_added_vec[i]);
277 *pc_products[i], start_index, stop_index);
278 }
279
281
282 return num_added_vec;
283 }
284
285private:
286 // How many different type of species the collision produces
288 // Vectors of size m_num_product_species storing how many particles of a given species are
289 // produced by a collision event. These vectors are duplicated (one version for host and one
290 // for device) which is necessary with GPUs but redundant on CPU.
295};
296
297
303{
306 using ParticleTileDataType = typename ParticleTileType::ParticleTileDataType;
309 using SoaData_type = typename WarpXParticleContainer::ParticleTileType::ParticleTileDataType;
310
311public:
313
314 NoParticleCreationFunc (const std::string& /*collision_name*/,
315 MultiParticleContainer const * const /*mypc*/) {}
316
319 const index_type& /*n_total_pairs*/,
320 ParticleTileType& /*ptile1*/, ParticleTileType& /*ptile2*/,
322 ParticleTileType** /*tile_products*/,
323 const amrex::ParticleReal& /*m1*/, const amrex::ParticleReal& /*m2*/,
324 const amrex::Vector<amrex::ParticleReal>& /*products_mass*/,
325 const index_type* /*p_mask*/, const amrex::Vector<index_type>& /*products_np*/,
326 const SmartCopy* /*copy_species1*/, const SmartCopy* /*copy_species2*/,
327 const index_type* /*p_pair_indices_1*/, const index_type* /*p_pair_indices_2*/,
328 const amrex::ParticleReal* /*p_pair_reaction_weight*/,
329 const amrex::ParticleReal* AMREX_RESTRICT /*p_product_data*/
330 ) const
331 {
332 return {};
333 }
334};
335
336#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
@ LinearCompton
Definition BinaryCollisionUtils.H:26
ScatteringAngleModel
For binary collision algorithms, the strategy to determine the scattering angle in the center of mass...
Definition WarpXAlgorithmSelection.H:198
@ Default
Definition WarpXAlgorithmSelection.H:198
Definition MultiParticleContainer.H:69
typename WarpXParticleContainer::ParticleType ParticleType
Definition ParticleCreationFunc.H:304
NoParticleCreationFunc(const std::string &, MultiParticleContainer const *const)
Definition ParticleCreationFunc.H:314
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:318
typename ParticleBins::index_type index_type
Definition ParticleCreationFunc.H:308
NoParticleCreationFunc()=default
amrex::DenseBins< ParticleTileDataType > ParticleBins
Definition ParticleCreationFunc.H:307
typename WarpXParticleContainer::ParticleTileType ParticleTileType
Definition ParticleCreationFunc.H:305
typename ParticleTileType::ParticleTileDataType ParticleTileDataType
Definition ParticleCreationFunc.H:306
typename WarpXParticleContainer::ParticleTileType::ParticleTileDataType SoaData_type
Definition ParticleCreationFunc.H:309
CollisionType m_collision_type
Definition ParticleCreationFunc.H:293
amrex::DenseBins< ParticleTileDataType > ParticleBins
Definition ParticleCreationFunc.H:40
int m_num_product_species
Definition ParticleCreationFunc.H:287
amrex::Gpu::DeviceVector< int > m_num_products_device
Definition ParticleCreationFunc.H:291
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:99
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:292
ScatteringAngleModel m_scattering_angle_model
Definition ParticleCreationFunc.H:294
iterator begin() noexcept
T * dataPtr() noexcept
T * data() noexcept
std::conditional_t< is_rtsoa_pc, ParticleTileRT< typename ParticleType::RealType, typename ParticleType::IntType >, ParticleTile< ParticleType, NArrayReal, NArrayInt, Allocator > > ParticleTileType
amrex_particle_real ParticleReal
T ExclusiveSum(N n, T const *in, T *out, RetSum a_ret_sum=retSum)
PinnedVector< T > HostVector
PODVector< T, ArenaAllocator< T > > DeviceVector
AMREX_GPU_HOST_DEVICE AMREX_INLINE bool is_two_product_fusion_type(const CollisionType collision_type)
Definition BinaryCollisionUtils.H:77
void DefaultInitializeRuntimeAttributes(PTile &ptile, const DstPC &pc, int start, int stop, const int n_external_attr_real=0, const int n_external_attr_int=0, const bool do_qed_comps=false)
Default initialize runtime attributes in a tile. This routine does not initialize the first n_externa...
Definition DefaultInitialization.H:111
constexpr auto c2
square of the vacuum speed of light [m^2/s^2]
Definition constant.H:214
void synchronize() noexcept
void copyAsync(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
static constexpr HostToDevice hostToDevice
void streamSynchronize() noexcept
const int[]
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