7 #ifndef WARPX_PARTICLES_COLLISION_BINARYCOLLISION_H_ 8 #define WARPX_PARTICLES_COLLISION_BINARYCOLLISION_H_ 27 #include <AMReX_Algorithm.H> 28 #include <AMReX_BLassert.H> 29 #include <AMReX_Config.H> 30 #include <AMReX_DenseBins.H> 31 #include <AMReX_Extension.H> 32 #include <AMReX_Geometry.H> 33 #include <AMReX_GpuAtomic.H> 34 #include <AMReX_GpuControl.H> 35 #include <AMReX_GpuDevice.H> 36 #include <AMReX_GpuLaunch.H> 37 #include <AMReX_GpuQualifiers.H> 38 #include <AMReX_LayoutData.H> 39 #include <AMReX_MFIter.H> 40 #include <AMReX_PODVector.H> 41 #include <AMReX_ParmParse.H> 42 #include <AMReX_Particles.H> 43 #include <AMReX_ParticleTile.H> 44 #include <AMReX_Random.H> 45 #include <AMReX_REAL.H> 46 #include <AMReX_Scan.H> 47 #include <AMReX_Utility.H> 48 #include <AMReX_Vector.H> 50 #include <AMReX_BaseFwd.H> 64 template <
typename CollisionFunctorType,
73 using SoaData_type = WarpXParticleContainer::ParticleTileType::ParticleTileDataType;
87 amrex::Abort(
"Binary collision " + collision_name +
" must have exactly two species.");
96 amrex::ParmParse pp_collision_name(collision_name);
114 if (
int(std::floor(cur_time/dt)) %
m_ndt != 0 )
return;
121 amrex::Vector<WarpXParticleContainer*> product_species_vector;
122 amrex::Vector<SmartCopy> copy_species1;
123 amrex::Vector<SmartCopy> copy_species2;
124 for (
int i = 0;
i < n_product_species;
i++)
128 product_species_vector.push_back(&product);
131 copy_species1.push_back(copy_factory_species1.
getSmartCopy());
132 copy_species2.push_back(copy_factory_species2.
getSmartCopy());
135 amrex::Gpu::DeviceVector<SmartCopy> device_copy_species1(n_product_species);
136 amrex::Gpu::DeviceVector<SmartCopy> device_copy_species2(n_product_species);
137 amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, copy_species1.begin(),
138 copy_species1.end(), device_copy_species1.begin());
139 amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, copy_species2.begin(),
140 copy_species2.end(), device_copy_species2.begin());
141 amrex::Gpu::streamSynchronize();
142 auto copy_species1_data = device_copy_species1.data();
143 auto copy_species2_data = device_copy_species2.data();
145 auto copy_species1_data = copy_species1.data();
146 auto copy_species2_data = copy_species2.data();
150 species2.defineAllParticleTiles();
154 amrex::MFItInfo info;
155 if (amrex::Gpu::notInLaunchRegion()) info.EnableTiling(
species1.tile_size);
158 for (
int lev = 0; lev <=
species1.finestLevel(); ++lev){
164 info.SetDynamic(
true);
165 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion()) 167 for (amrex::MFIter mfi =
species1.MakeMFIter(lev, info); mfi.isValid(); ++mfi){
170 amrex::Gpu::synchronize();
172 amrex::Real wt = amrex::second();
175 copy_species1_data, copy_species2_data);
179 amrex::Gpu::synchronize();
180 wt = amrex::second() - wt;
181 amrex::HostDevice::Atomic::Add( &(*cost)[mfi.index()], wt);
198 int const lev, amrex::MFIter
const& mfi,
201 amrex::Vector<WarpXParticleContainer*> product_species_vector,
207 int const ndt =
m_ndt;
213 amrex::Vector<SoaData_type> soa_products;
214 amrex::Vector<GetParticlePosition> get_position_products;
215 amrex::Vector<index_type> products_np;
216 constexpr
int getpos_offset = 0;
217 for (
int i = 0;
i < n_product_species;
i++)
219 ParticleTileType& ptile_product = product_species_vector[
i]->ParticlesAt(lev, mfi);
220 soa_products.push_back(ptile_product.getParticleTileData());
223 products_np.push_back(ptile_product.numParticles());
226 amrex::Gpu::DeviceVector<SoaData_type> device_soa_products(n_product_species);
227 amrex::Gpu::DeviceVector<GetParticlePosition> device_get_position_products(n_product_species);
228 amrex::Gpu::DeviceVector<index_type> device_products_np(n_product_species);
229 amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, soa_products.begin(),
231 device_soa_products.begin());
232 amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, get_position_products.begin(),
233 get_position_products.end(),
234 device_get_position_products.begin());
235 amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, products_np.begin(),
237 device_products_np.begin());
238 amrex::Gpu::streamSynchronize();
239 auto soa_products_data = device_soa_products.data();
240 auto get_position_products_data = device_get_position_products.data();
241 auto products_np_data = device_products_np.data();
243 auto soa_products_data = soa_products.data();
244 auto get_position_products_data = get_position_products.data();
245 auto products_np_data = products_np.data();
259 int const n_cells = bins_1.numBins();
261 const auto soa_1 = ptile_1.getParticleTileData();
262 index_type* indices_1 = bins_1.permutationPtr();
263 index_type const* cell_offsets_1 = bins_1.offsetsPtr();
265 amrex::Real m1 = species_1.
getMass();
270 #if defined WARPX_DIM_XZ 271 auto dV = geom.
CellSize(0) * geom.CellSize(1);
272 #elif defined WARPX_DIM_RZ 273 amrex::Box
const& cbx = mfi.tilebox(amrex::IntVect::TheZeroVector());
274 const auto lo = lbound(cbx);
275 const auto hi = ubound(cbx);
276 int const nz = hi.y-lo.y+1;
277 auto dr = geom.CellSize(0);
278 auto dz = geom.CellSize(1);
279 #elif (AMREX_SPACEDIM == 3) 280 auto dV = geom.CellSize(0) * geom.CellSize(1) * geom.CellSize(2);
287 const int n_cells_products = have_product_species ? n_cells: 0;
288 amrex::Gpu::DeviceVector<index_type> n_pairs_in_each_cell(n_cells_products);
289 auto p_n_pairs_in_each_cell = n_pairs_in_each_cell.dataPtr();
294 amrex::ParallelFor( n_cells_products,
295 [=] AMREX_GPU_DEVICE (
int i_cell) noexcept
297 const auto n_part_in_cell = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
299 p_n_pairs_in_each_cell[i_cell] = (n_part_in_cell == 1)? 0: (n_part_in_cell+1)/2;
304 amrex::Gpu::DeviceVector<index_type> pair_offsets(n_cells_products);
305 const auto n_total_pairs = amrex::Scan::ExclusiveSum(n_cells_products,
306 p_n_pairs_in_each_cell, pair_offsets.data());
307 auto p_pair_offsets = pair_offsets.dataPtr();
310 amrex::Gpu::DeviceVector<index_type> mask(n_total_pairs);
311 auto p_mask = mask.dataPtr();
313 amrex::Gpu::DeviceVector<index_type> pair_indices_1(n_total_pairs);
314 auto p_pair_indices_1 = pair_indices_1.dataPtr();
316 amrex::Gpu::DeviceVector<index_type> pair_indices_2(n_total_pairs);
317 auto p_pair_indices_2 = pair_indices_2.dataPtr();
320 amrex::Gpu::DeviceVector<amrex::ParticleReal> pair_reaction_weight(n_total_pairs);
321 auto p_pair_reaction_weight = pair_reaction_weight.dataPtr();
328 amrex::ParallelForRNG( n_cells,
329 [=] AMREX_GPU_DEVICE (
int i_cell, amrex::RandomEngine
const& engine) noexcept
333 index_type const cell_start_1 = cell_offsets_1[i_cell];
334 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
335 index_type const cell_half_1 = (cell_start_1+cell_stop_1)/2;
338 index_type const cell_start_pair = have_product_species?
339 p_pair_offsets[i_cell] : 0;
342 if ( cell_stop_1 - cell_start_1 <= 1 )
return;
346 indices_1, cell_start_1, cell_half_1, engine );
347 #if defined WARPX_DIM_RZ 348 int ri = (i_cell - i_cell%nz) / nz;
349 auto dV = MathConst::pi*(2.0_rt*ri+1.0_rt)*dr*dr*
dz;
354 binary_collision_functor(
355 cell_start_1, cell_half_1,
356 cell_half_1, cell_stop_1,
357 indices_1, indices_1,
358 soa_1, soa_1, get_position_1, get_position_1,
359 q1, q1, m1, m1, dt*ndt, dV,
360 cell_start_pair, p_mask, p_pair_indices_1, p_pair_indices_2,
361 p_pair_reaction_weight, engine );
369 get_position_1, get_position_1,
370 get_position_products_data,
371 p_mask, products_np_data,
372 copy_species1, copy_species2,
373 p_pair_indices_1, p_pair_indices_2,
374 p_pair_reaction_weight);
376 for (
int i = 0;
i < n_product_species;
i++)
378 ParticleTileType& ptile_product = product_species_vector[
i]->ParticlesAt(lev, mfi);
395 int const n_cells = bins_1.numBins();
397 const auto soa_1 = ptile_1.getParticleTileData();
398 index_type* indices_1 = bins_1.permutationPtr();
399 index_type const* cell_offsets_1 = bins_1.offsetsPtr();
401 amrex::Real m1 = species_1.
getMass();
404 const auto soa_2 = ptile_2.getParticleTileData();
405 index_type* indices_2 = bins_2.permutationPtr();
406 index_type const* cell_offsets_2 = bins_2.offsetsPtr();
408 amrex::Real m2 = species_2.
getMass();
413 #if defined WARPX_DIM_XZ 414 auto dV = geom.
CellSize(0) * geom.CellSize(1);
415 #elif defined WARPX_DIM_RZ 416 amrex::Box
const& cbx = mfi.tilebox(amrex::IntVect::TheZeroVector());
417 const auto lo = lbound(cbx);
418 const auto hi = ubound(cbx);
419 int nz = hi.y-lo.y+1;
420 auto dr = geom.CellSize(0);
421 auto dz = geom.CellSize(1);
422 #elif (AMREX_SPACEDIM == 3) 423 auto dV = geom.CellSize(0) * geom.CellSize(1) * geom.CellSize(2);
430 const int n_cells_products = have_product_species ? n_cells: 0;
431 amrex::Gpu::DeviceVector<index_type> n_pairs_in_each_cell(n_cells_products);
432 auto p_n_pairs_in_each_cell = n_pairs_in_each_cell.dataPtr();
437 amrex::ParallelFor( n_cells_products,
438 [=] AMREX_GPU_DEVICE (
int i_cell) noexcept
440 const auto n_part_in_cell_1 = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
441 const auto n_part_in_cell_2 = cell_offsets_2[i_cell+1] - cell_offsets_2[i_cell];
443 if (n_part_in_cell_1 == 0 || n_part_in_cell_2 == 0)
444 p_n_pairs_in_each_cell[i_cell] = 0;
446 p_n_pairs_in_each_cell[i_cell] =
447 amrex::max(n_part_in_cell_1,n_part_in_cell_2);
452 amrex::Gpu::DeviceVector<index_type> pair_offsets(n_cells_products);
453 auto n_total_pairs = amrex::Scan::ExclusiveSum(n_cells_products,
454 p_n_pairs_in_each_cell, pair_offsets.data());
455 auto p_pair_offsets = pair_offsets.dataPtr();
458 amrex::Gpu::DeviceVector<index_type> mask(n_total_pairs);
459 auto p_mask = mask.dataPtr();
461 amrex::Gpu::DeviceVector<index_type> pair_indices_1(n_total_pairs);
462 auto p_pair_indices_1 = pair_indices_1.dataPtr();
464 amrex::Gpu::DeviceVector<index_type> pair_indices_2(n_total_pairs);
465 auto p_pair_indices_2 = pair_indices_2.dataPtr();
468 amrex::Gpu::DeviceVector<amrex::ParticleReal> pair_reaction_weight(n_total_pairs);
469 auto p_pair_reaction_weight = pair_reaction_weight.dataPtr();
476 amrex::ParallelForRNG( n_cells,
477 [=] AMREX_GPU_DEVICE (
int i_cell, amrex::RandomEngine
const& engine) noexcept
481 index_type const cell_start_1 = cell_offsets_1[i_cell];
482 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
484 index_type const cell_start_2 = cell_offsets_2[i_cell];
485 index_type const cell_stop_2 = cell_offsets_2[i_cell+1];
487 index_type const cell_start_pair = have_product_species?
488 p_pair_offsets[i_cell] : 0;
495 if ( cell_stop_1 - cell_start_1 < 1 ||
496 cell_stop_2 - cell_start_2 < 1 )
return;
501 #if defined WARPX_DIM_RZ 502 int ri = (i_cell - i_cell%nz) / nz;
503 auto dV = MathConst::pi*(2.0_rt*ri+1.0_rt)*dr*dr*
dz;
508 binary_collision_functor(
509 cell_start_1, cell_stop_1, cell_start_2, cell_stop_2,
510 indices_1, indices_2,
511 soa_1, soa_2, get_position_1, get_position_2,
512 q1, q2, m1, m2, dt*ndt, dV,
513 cell_start_pair, p_mask, p_pair_indices_1, p_pair_indices_2,
514 p_pair_reaction_weight, engine );
523 get_position_1, get_position_2,
524 get_position_products_data,
525 p_mask, products_np_data,
526 copy_species1, copy_species2,
527 p_pair_indices_1, p_pair_indices_2,
528 p_pair_reaction_weight);
530 for (
int i = 0;
i < n_product_species;
i++)
532 ParticleTileType& ptile_product = product_species_vector[
i]->ParticlesAt(lev, mfi);
552 #endif // WARPX_PARTICLES_COLLISION_BINARYCOLLISION_H_
This class does nothing and is used as second template parameter for binary collisions that do not cr...
Definition: BinaryCollisionUtils.H:22
amrex::Vector< amrex::Real > getdt() const
Definition: WarpX.H:536
string species1
Definition: video_yt.py:32
bool m_have_product_species
Definition: BinaryCollision.H:543
static long load_balance_costs_update_algo
Definition: WarpX.H:145
AMREX_GPU_HOST_DEVICE AMREX_INLINE void ShuffleFisherYates(T_index *array, T_index const is, T_index const ie, amrex::RandomEngine const &engine)
Definition: ShuffleFisherYates.H:20
void doCollisionsWithinTile(int const lev, amrex::MFIter const &mfi, WarpXParticleContainer &species_1, WarpXParticleContainer &species_2, amrex::Vector< WarpXParticleContainer *> product_species_vector, SmartCopy *copy_species1, SmartCopy *copy_species2)
Definition: BinaryCollision.H:197
WarpXParticleContainer & GetParticleContainerFromName(std::string name) const
Definition: MultiParticleContainer.H:80
WarpXParticleContainer::ParticleType ParticleType
Definition: BinaryCollision.H:70
This class performs generic binary collisions.
Definition: BinaryCollision.H:66
void defineAllParticleTiles() noexcept
Definition: WarpXParticleContainer.cpp:1075
CopyTransformFunctorType m_copy_transform_functor
Definition: BinaryCollision.H:548
Definition: MultiParticleContainer.H:64
CollisionFunctorType m_binary_collision_functor
Definition: BinaryCollision.H:546
load balance according to in-code timer-based weights (i.e., with costs)
Definition: WarpXAlgorithmSelection.H:90
WarpXParticleContainer::ParticleTileType ParticleTileType
Definition: ParticleUtils.cpp:30
virtual ~BinaryCollision()=default
void doCollisions(amrex::Real cur_time, MultiParticleContainer *mypc) override
Definition: BinaryCollision.H:111
WarpXParticleContainer::ParticleTileType::ParticleTileDataType SoaData_type
Definition: BinaryCollision.H:73
int m_ndt
Definition: CollisionBase.H:33
amrex::ParticleReal getCharge() const
Definition: WarpXParticleContainer.H:317
ParticleBins findParticlesInEachCell(int const lev, MFIter const &mfi, ParticleTileType const &ptile)
Definition: ParticleUtils.cpp:37
amrex::ParticleReal getMass() const
Definition: WarpXParticleContainer.H:319
void setNewParticleIDs(PTile &ptile, int old_size, int num_added)
Sets the ids of newly created particles to the next values.
Definition: SmartUtils.H:51
amrex::DenseBins< ParticleType > ParticleBins
Definition: BinaryCollision.H:72
ParticleBins::index_type index_type
Definition: ParticleUtils.cpp:32
static amrex::LayoutData< amrex::Real > * getCosts(int lev)
Definition: WarpX.cpp:2140
amrex::Vector< std::string > m_species_names
Definition: CollisionBase.H:32
i
Definition: check_interp_points_and_weights.py:171
int dz
Definition: compute_domain.py:36
WarpXParticleContainer::ParticleTileType ParticleTileType
Definition: BinaryCollision.H:71
WarpXParticleContainer::ParticleType ParticleType
Definition: ParticleUtils.cpp:29
Definition: ParticleUtils.cpp:25
static WarpX & GetInstance()
Definition: WarpX.cpp:200
ParticleBins::index_type index_type
Definition: BinaryCollision.H:74
BinaryCollision(std::string collision_name)
Constructor of the BinaryCollision class.
Definition: BinaryCollision.H:83
amrex::Vector< std::string > m_product_species
Definition: BinaryCollision.H:544
Definition: CollisionBase.H:17
This is a functor for performing a "smart copy" that works in both host and device code...
Definition: SmartCopy.H:33
static std::array< amrex::Real, 3 > CellSize(int lev)
Definition: WarpX.cpp:1957
bool m_isSameSpecies
Definition: BinaryCollision.H:542
Functor that can be used to extract the positions of the macroparticles inside a ParallelFor kernel...
Definition: GetAndSetPosition.H:48
SmartCopy getSmartCopy() const noexcept
Definition: SmartCopy.H:153
A factory for creating SmartCopy functors.
Definition: SmartCopy.H:131
Definition: WarpXParticleContainer.H:110