7 #ifndef WARPX_PARTICLES_COLLISION_BINARYCOLLISION_H_
8 #define WARPX_PARTICLES_COLLISION_BINARYCOLLISION_H_
33 #include <AMReX_Config.H>
69 template <
typename CollisionFunctor,
114 " does not produce species. Thus, `product_species` should not be specified in the input script." );
148 for (
int i = 0;
i < n_product_species;
i++)
152 product_species_vector.push_back(&product);
158 copy_species1.push_back(copy_factory_species1[
i].getSmartCopy());
159 copy_species2.push_back(copy_factory_species2[
i].getSmartCopy());
165 copy_species1.end(), device_copy_species1.
begin());
167 copy_species2.end(), device_copy_species2.
begin());
169 auto *copy_species1_data = device_copy_species1.
data();
170 auto *copy_species2_data = device_copy_species2.
data();
172 auto *copy_species1_data = copy_species1.data();
173 auto *copy_species2_data = copy_species2.data();
185 for (
int lev = 0; lev <=
species1.finestLevel(); ++lev){
192 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
202 copy_species1_data, copy_species2_data);
242 using namespace amrex::literals;
253 constexpr
int getpos_offset = 0;
254 for (
int i = 0;
i < n_product_species;
i++)
256 ParticleTileType& ptile_product = product_species_vector[
i]->ParticlesAt(lev, mfi);
257 tile_products.push_back(&ptile_product);
261 products_mass.push_back(product_species_vector[
i]->getMass());
263 auto *tile_products_data = tile_products.data();
276 auto const n_cells =
static_cast<int>(bins_1.
numBins());
281 const amrex::ParticleReal q1 = species_1.
getCharge();
282 const amrex::ParticleReal m1 = species_1.
getMass();
286 #if defined WARPX_DIM_1D_Z
288 #elif defined WARPX_DIM_XZ
290 #elif defined WARPX_DIM_RZ
294 int const nz = hi.y-lo.y+1;
297 #elif defined(WARPX_DIM_3D)
304 const int n_cells_products = have_product_species ? n_cells: 0;
314 const auto n_part_in_cell = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
316 p_n_pairs_in_each_cell[i_cell] = (n_part_in_cell == 1)? 0: (n_part_in_cell+1)/2;
322 const index_type n_total_pairs = (n_cells_products == 0) ? 0:
324 p_n_pairs_in_each_cell, pair_offsets.data());
333 const auto n_part_in_cell = (i_cell < n_cells)? cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell]: 0;
335 p_n_ind_pairs_in_each_cell[i_cell] = n_part_in_cell/2;
359 pair_reaction_weight.
dataPtr();
367 if (binary_collision_functor.m_computeSpeciesDensities) {
370 if (binary_collision_functor.m_computeSpeciesTemperatures) {
382 index_type const cell_start_1 = cell_offsets_1[i_cell];
383 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
386 if ( cell_stop_1 - cell_start_1 <= 1 ) {
return; }
389 if (binary_collision_functor.m_computeSpeciesDensities) {
390 amrex::ParticleReal wtot1 = 0.0;
391 amrex::ParticleReal * const AMREX_RESTRICT w1 = soa_1.m_rdata[PIdx::w];
392 for (index_type i1=cell_start_1; i1<cell_stop_1; ++i1) {
393 wtot1 += w1[ indices_1[i1] ];
395 #
if defined WARPX_DIM_RZ
396 const int ri = (i_cell - i_cell%nz) / nz;
397 auto dV = MathConst::pi*(2.0_prt*ri+1.0_prt)*dr*dr*
dz;
399 n1_in_each_cell[i_cell] = wtot1/dV;
403 if (binary_collision_functor.m_computeSpeciesTemperatures) {
404 amrex::ParticleReal * const AMREX_RESTRICT w1 = soa_1.m_rdata[PIdx::w];
405 amrex::ParticleReal * const AMREX_RESTRICT u1x = soa_1.m_rdata[PIdx::ux];
406 amrex::ParticleReal * const AMREX_RESTRICT u1y = soa_1.m_rdata[PIdx::uy];
407 amrex::ParticleReal * const AMREX_RESTRICT u1z = soa_1.m_rdata[PIdx::uz];
408 T1_in_each_cell[i_cell] = ComputeTemperature( cell_start_1, cell_stop_1, indices_1,
409 w1, u1x, u1y, u1z, m1 );
431 const int i_cell =
amrex::bisect( p_coll_offsets, 0, n_cells, ui_coll );
435 index_type const cell_start_1 = cell_offsets_1[i_cell];
436 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
437 index_type const cell_half_1 = (cell_start_1+cell_stop_1)/2;
440 const index_type coll_idx = ui_coll - p_coll_offsets[i_cell];
443 index_type const cell_start_pair = have_product_species?
444 p_pair_offsets[i_cell] : 0;
446 #if defined WARPX_DIM_RZ
447 const int ri = (i_cell - i_cell%nz) / nz;
448 auto dV = MathConst::pi*(2.0_prt*ri+1.0_prt)*dr*dr*
dz;
452 amrex::ParticleReal n1 = 0.0;
453 amrex::ParticleReal T1 = 0.0;
454 if (binary_collision_functor.m_computeSpeciesDensities) {
455 n1 = n1_in_each_cell[i_cell];
457 if (binary_collision_functor.m_computeSpeciesTemperatures) {
458 T1 = T1_in_each_cell[i_cell];
464 binary_collision_functor(
465 cell_start_1, cell_half_1,
466 cell_half_1, cell_stop_1,
467 indices_1, indices_1,
468 soa_1, soa_1, get_position_1, get_position_1,
470 q1, q1, m1, m1,
dt, dV, coll_idx,
471 cell_start_pair, p_mask, p_pair_indices_1, p_pair_indices_2,
472 p_pair_reaction_weight, engine);
480 product_species_vector,
483 products_mass, p_mask, products_np,
484 copy_species1, copy_species2,
485 p_pair_indices_1, p_pair_indices_2,
486 p_pair_reaction_weight);
488 for (
int i = 0;
i < n_product_species;
i++)
506 auto const n_cells =
static_cast<int>(bins_1.
numBins());
508 const auto soa_1 = ptile_1.getParticleTileData();
511 const amrex::ParticleReal q1 = species_1.getCharge();
512 const amrex::ParticleReal m1 = species_1.getMass();
515 const auto soa_2 = ptile_2.getParticleTileData();
518 const amrex::ParticleReal q2 = species_2.getCharge();
519 const amrex::ParticleReal m2 = species_2.getMass();
523 #if defined WARPX_DIM_1D_Z
525 #elif defined WARPX_DIM_XZ
527 #elif defined WARPX_DIM_RZ
529 const auto lo =
lbound(cbx);
530 const auto hi =
ubound(cbx);
531 const int nz = hi.y-lo.y+1;
534 #elif defined(WARPX_DIM_3D)
541 const int n_cells_products = have_product_species ? n_cells: 0;
549 [=] AMREX_GPU_DEVICE (
int i_cell) noexcept
551 const auto n_part_in_cell_1 = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
552 const auto n_part_in_cell_2 = cell_offsets_2[i_cell+1] - cell_offsets_2[i_cell];
554 if (n_part_in_cell_1 == 0 || n_part_in_cell_2 == 0) {
555 p_n_pairs_in_each_cell[i_cell] = 0;
557 p_n_pairs_in_each_cell[i_cell] =
558 amrex::max(n_part_in_cell_1,n_part_in_cell_2);
565 const index_type n_total_pairs = (n_cells_products == 0) ? 0:
567 p_n_pairs_in_each_cell, pair_offsets.data());
574 [=] AMREX_GPU_DEVICE (
int i_cell) noexcept
576 if (i_cell < n_cells)
578 const auto n_part_in_cell_1 = cell_offsets_1[i_cell+1] - cell_offsets_1[i_cell];
579 const auto n_part_in_cell_2 = cell_offsets_2[i_cell+1] - cell_offsets_2[i_cell];
580 p_n_ind_pairs_in_each_cell[i_cell] =
amrex::min(n_part_in_cell_1, n_part_in_cell_2);
584 p_n_ind_pairs_in_each_cell[i_cell] = 0;
609 pair_reaction_weight.dataPtr();
617 if (binary_collision_functor.m_computeSpeciesDensities) {
621 if (binary_collision_functor.m_computeSpeciesTemperatures) {
636 index_type const cell_start_1 = cell_offsets_1[i_cell];
637 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
639 index_type const cell_start_2 = cell_offsets_2[i_cell];
640 index_type const cell_stop_2 = cell_offsets_2[i_cell+1];
647 if (binary_collision_functor.m_computeSpeciesDensities) {
648 amrex::ParticleReal w1tot = 0.0;
649 amrex::ParticleReal w2tot = 0.0;
650 amrex::ParticleReal * const AMREX_RESTRICT w1 = soa_1.m_rdata[PIdx::w];
651 amrex::ParticleReal * const AMREX_RESTRICT w2 = soa_2.m_rdata[PIdx::w];
652 for (index_type i1=cell_start_1; i1<cell_stop_1; ++i1) {
653 w1tot += w1[ indices_1[i1] ];
655 for (
index_type i2=cell_start_2; i2<cell_stop_2; ++i2) {
656 w2tot += w2[ indices_2[i2] ];
658 #if defined WARPX_DIM_RZ
659 const int ri = (i_cell - i_cell%nz) / nz;
660 auto dV = MathConst::pi*(2.0_prt*ri+1.0_prt)*dr*dr*
dz;
662 n1_in_each_cell[i_cell] = w1tot/dV;
663 n2_in_each_cell[i_cell] = w2tot/dV;
667 if (binary_collision_functor.m_computeSpeciesTemperatures) {
673 w1, u1x, u1y, u1z, m1 );
680 w2, u2x, u2y, u2z, m2 );
684 if ( cell_stop_1 - cell_start_1 < 1 ||
685 cell_stop_2 - cell_start_2 < 1 ) {
return; }
707 const int i_cell =
amrex::bisect( p_coll_offsets, 0, n_cells, ui_coll );
711 index_type const cell_start_1 = cell_offsets_1[i_cell];
712 index_type const cell_stop_1 = cell_offsets_1[i_cell+1];
714 index_type const cell_start_2 = cell_offsets_2[i_cell];
715 index_type const cell_stop_2 = cell_offsets_2[i_cell+1];
718 const index_type coll_idx = ui_coll - p_coll_offsets[i_cell];
721 index_type const cell_start_pair = have_product_species?
722 p_pair_offsets[i_cell]: 0;
728 #if defined WARPX_DIM_RZ
729 const int ri = (i_cell - i_cell%nz) / nz;
730 auto dV = MathConst::pi*(2.0_prt*ri+1.0_prt)*dr*dr*
dz;
734 amrex::ParticleReal n1 = 0.0, n2 = 0.0;
735 amrex::ParticleReal T1 = 0.0, T2 = 0.0;
736 if (binary_collision_functor.m_computeSpeciesDensities) {
737 n1 = n1_in_each_cell[i_cell];
738 n2 = n2_in_each_cell[i_cell];
740 if (binary_collision_functor.m_computeSpeciesTemperatures) {
741 T1 = T1_in_each_cell[i_cell];
742 T2 = T2_in_each_cell[i_cell];
748 binary_collision_functor(
749 cell_start_1, cell_stop_1, cell_start_2, cell_stop_2,
750 indices_1, indices_2,
751 soa_1, soa_2, get_position_1, get_position_2,
753 q1, q2, m1, m2,
dt, dV, coll_idx,
754 cell_start_pair, p_mask, p_pair_indices_1, p_pair_indices_2,
755 p_pair_reaction_weight, engine);
763 product_species_vector,
766 products_mass, p_mask, products_np,
767 copy_species1, copy_species2,
768 p_pair_indices_1, p_pair_indices_2,
769 p_pair_reaction_weight);
771 for (
int i = 0;
i < n_product_species;
i++)
CollisionType
Definition: BinaryCollisionUtils.H:17
AMREX_GPU_HOST_DEVICE T_R ComputeTemperature(T_index const Is, T_index const Ie, T_index const *AMREX_RESTRICT I, T_R const *AMREX_RESTRICT w, T_R const *AMREX_RESTRICT ux, T_R const *AMREX_RESTRICT uy, T_R const *AMREX_RESTRICT uz, T_R const m)
Definition: ComputeTemperature.H:15
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 setNewParticleIDs(PTile &ptile, amrex::Long old_size, amrex::Long num_added)
Sets the ids of newly created particles to the next values.
Definition: SmartUtils.H:52
#define WARPX_ABORT_WITH_MESSAGE(MSG)
Definition: TextMsg.H:15
This class performs generic binary collisions.
Definition: BinaryCollision.H:73
bool m_have_product_species
Definition: BinaryCollision.H:783
ParticleBins::index_type index_type
Definition: BinaryCollision.H:79
CopyTransformFunctor m_copy_transform_functor
Definition: BinaryCollision.H:788
bool m_isSameSpecies
Definition: BinaryCollision.H:782
WarpXParticleContainer::ParticleType ParticleType
Definition: BinaryCollision.H:75
BinaryCollision(std::string collision_name, MultiParticleContainer const *const mypc)
Constructor of the BinaryCollision class.
Definition: BinaryCollision.H:89
~BinaryCollision() override=default
void doCollisions(amrex::Real cur_time, amrex::Real dt, MultiParticleContainer *mypc) override
Definition: BinaryCollision.H:134
void doCollisionsWithinTile(amrex::Real dt, 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:234
BinaryCollision & operator=(BinaryCollision const &)=default
amrex::Vector< std::string > m_product_species
Definition: BinaryCollision.H:784
CollisionFunctor m_binary_collision_functor
Definition: BinaryCollision.H:786
BinaryCollision(BinaryCollision const &)=default
BinaryCollision(BinaryCollision &&)=delete
Definition: CollisionBase.H:18
amrex::Vector< std::string > m_species_names
Definition: CollisionBase.H:36
Definition: MultiParticleContainer.H:66
WarpXParticleContainer & GetParticleContainerFromName(const std::string &name) const
Definition: MultiParticleContainer.cpp:392
This class does nothing and is used as second template parameter for binary collisions that do not cr...
Definition: ParticleCreationFunc.H:284
A factory for creating SmartCopy functors.
Definition: SmartCopy.H:133
static WarpX & GetInstance()
Definition: WarpX.cpp:231
static amrex::LayoutData< amrex::Real > * getCosts(int lev)
Definition: WarpX.cpp:3108
static short load_balance_costs_update_algo
Definition: WarpX.H:191
Definition: WarpXParticleContainer.H:111
void defineAllParticleTiles() noexcept
Definition: WarpXParticleContainer.cpp:1517
amrex::ParticleReal getCharge() const
Definition: WarpXParticleContainer.H:371
amrex::ParticleReal getMass() const
Definition: WarpXParticleContainer.H:373
const Vector< Geometry > & Geom() const noexcept
const Real * CellSize() const noexcept
index_type * offsetsPtr() noexcept
index_type * permutationPtr() noexcept
Long numBins() const noexcept
AMREX_GPU_HOST_DEVICE static constexpr AMREX_FORCE_INLINE IntVectND< dim > TheZeroVector() noexcept
Box tilebox() const noexcept
iterator begin() noexcept
void resize(size_type a_new_size)
int queryarr(const char *name, std::vector< int > &ref, int start_ix=FIRST, int num_val=ALL) const
ParticleTile< ParticleType, NArrayReal, NArrayInt, Allocator > ParticleTileType
const ParticleTileType & ParticlesAt(int lev, int grid, int tile) const
T_ParticleType ParticleType
CollisionType get_collision_type(const std::string &collision_name, MultiParticleContainer const *const mypc)
Definition: BinaryCollisionUtils.cpp:20
Definition: ParticleUtils.cpp:26
ParticleBins findParticlesInEachCell(int lev, MFIter const &mfi, ParticleTileType &ptile)
Find the particles and count the particles that are in each cell. More specifically this function ret...
Definition: ParticleUtils.cpp:40
typename WarpXParticleContainer::ParticleTileType ParticleTileType
Definition: ParticleUtils.cpp:32
typename ParticleBins::index_type index_type
Definition: ParticleUtils.cpp:35
void synchronize() noexcept
void copyAsync(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
static constexpr HostToDevice hostToDevice
void streamSynchronize() noexcept
bool notInLaunchRegion() noexcept
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void Add(T *const sum, T const value) noexcept
T ExclusiveSum(N n, T const *in, T *out, RetSum a_ret_sum=retSum)
AMREX_GPU_HOST_DEVICE constexpr AMREX_FORCE_INLINE const T & max(const T &a, const T &b) noexcept
AMREX_GPU_HOST_DEVICE constexpr AMREX_FORCE_INLINE const T & min(const T &a, const T &b) noexcept
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 ubound(Array4< T > const &a) noexcept
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T bisect(T lo, T hi, F f, T tol=1e-12, int max_iter=100)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 lbound(Array4< T > const &a) noexcept
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... >, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
AMREX_ATTRIBUTE_FLATTEN_FOR void ParallelForRNG(T n, L const &f) noexcept
i
Definition: check_interp_points_and_weights.py:174
int dz
Definition: compute_domain.py:36
float dt
Definition: stencil.py:442
string species1
Definition: video_yt.py:35
@ Timers
load balance according to in-code timer-based weights (i.e., with costs)
Definition: WarpXAlgorithmSelection.H:137
@ uz
Definition: NamedComponentParticleContainer.H:34
@ w
weight
Definition: NamedComponentParticleContainer.H:33
@ uy
Definition: NamedComponentParticleContainer.H:34
@ ux
Definition: NamedComponentParticleContainer.H:34
This is a functor for performing a "smart copy" that works in both host and device code.
Definition: SmartCopy.H:34
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int const * dataPtr() const noexcept
MFItInfo & EnableTiling(const IntVect &ts=FabArrayBase::mfiter_tile_size) noexcept
MFItInfo & SetDynamic(bool f) noexcept
ParticleTileData< StorageParticleType, NArrayReal, NArrayInt > ParticleTileDataType
ParticleTileDataType getParticleTileData()