145 return ((
mask[i] > 0) &&
155 for (
int i = 0; i < 2; i++)
160 num_added_vec[i] =
static_cast<int>(no_product_total);
184 const index_type num_added = with_product_total * num_products;
185 num_added_vec[i] +=
static_cast<int>(num_added);
196 products_np[i] = tile_products[i]->numParticles();
197 tile_products[i]->resize(products_np[i] + num_added_vec[i]);
200 const auto soa_0 = ptile0.getParticleTileData();
201 const auto soa_1 = ptile1.getParticleTileData();
207 soa_products.push_back(tile_products[i]->getParticleTileData());
215 device_soa_products.
begin());
218 device_products_np.
begin());
234 if (num_product_species > 2) {
235 mass_slot2 = pc_products[2]->getMass();
236 mass_slot3 = pc_products[3]->getMass();
245 const auto slot0_idx = products_np_data[0] + no_product_offsets_data[i];
247 copy_species0[0](soa_products_data[0], soa_0,
static_cast<int>(p_pair_indices_0[i]),
248 static_cast<int>(slot0_idx), engine);
250 soa_products_data[0].m_rdata[
PIdx::w][slot0_idx] = p_pair_reaction_weight[i];
252 const auto slot1_idx = products_np_data[1] + no_product_offsets_data[i];
254 copy_species1[1](soa_products_data[1], soa_1,
static_cast<int>(p_pair_indices_1[i]),
255 static_cast<int>(slot1_idx), engine);
257 soa_products_data[1].m_rdata[
PIdx::w][slot1_idx] = p_pair_reaction_weight[i];
260 auto& ux0 = soa_products_data[0].m_rdata[
PIdx::ux][slot0_idx];
261 auto& uy0 = soa_products_data[0].m_rdata[
PIdx::uy][slot0_idx];
262 auto& uz0 = soa_products_data[0].m_rdata[
PIdx::uz][slot0_idx];
263 auto& ux1 = soa_products_data[1].m_rdata[
PIdx::ux][slot1_idx];
264 auto& uy1 = soa_products_data[1].m_rdata[
PIdx::uy][slot1_idx];
265 auto& uz1 = soa_products_data[1].m_rdata[
PIdx::uz][slot1_idx];
271 auto const uCOM_x = (m0 * ux0 + m1 * ux1) / (m0 + m1);
272 auto const uCOM_y = (m0 * uy0 + m1 * uy1) / (m0 + m1);
273 auto const uCOM_z = (m0 * uz0 + m1 * uz1) / (m0 + m1);
286 ux0, uy0, uz0, std::sqrt(ux0*ux0 + uy0*uy0 + uz0*uz0), engine
290 ux1 = -ux0 * m0 / m1;
291 uy1 = -uy0 * m0 / m1;
292 uz1 = -uz0 * m0 / m1;
302 amrex::Abort(
"Forward scattering with DSMC not implemented yet.");
322 const auto src0_idx =
static_cast<int>(p_pair_indices_0[i]);
323 const auto slot2_idx = products_np_data[2] + with_product_offsets_data[i];
324 copy_species0[2](soa_products_data[2], soa_0, src0_idx,
325 static_cast<int>(slot2_idx), engine);
327 soa_products_data[2].m_rdata[
PIdx::w][slot2_idx] = p_pair_reaction_weight[i];
330 const auto src1_idx =
static_cast<int>(p_pair_indices_1[i]);
331 const auto slot3_idx = products_np_data[3] + with_product_offsets_data[i];
332 copy_species1[3](soa_products_data[3], soa_1, src1_idx,
333 static_cast<int>(slot3_idx), engine);
335 soa_products_data[3].m_rdata[
PIdx::w][slot3_idx] = p_pair_reaction_weight[i];
342#if defined(WARPX_DIM_1D_Z)
343 constexpr std::array<int, 1> position_indices = {
PIdx::z};
344#elif defined(WARPX_DIM_XZ)
345 constexpr std::array<int, 2> position_indices = {
PIdx::x,
PIdx::z};
346#elif defined(WARPX_DIM_RZ)
347 constexpr std::array<int, 3> position_indices = {PIdx::r,
PIdx::z, PIdx::theta};
348#elif defined(WARPX_DIM_RCYLINDER)
349 constexpr std::array<int, 2> position_indices = {PIdx::r, PIdx::theta};
350#elif defined(WARPX_DIM_RSPHERE)
351 constexpr std::array<int, 3> position_indices = {PIdx::r, PIdx::theta, PIdx::phi};
352#elif defined(WARPX_DIM_3D)
353 constexpr std::array<int, 3> position_indices = {
PIdx::x, PIdx::y,
PIdx::z};
356 for (
int const idim : position_indices) {
357 soa_products_data[2].m_rdata[idim][slot2_idx] = soa_1.m_rdata[idim][src1_idx];
358 soa_products_data[3].m_rdata[idim][slot3_idx] = soa_0.m_rdata[idim][src0_idx];
363 TwoProductComputeProductMomenta(
366 soa_0.m_rdata[
PIdx::uz][src0_idx], m0,
369 soa_1.m_rdata[
PIdx::uz][src1_idx], m1,
370 soa_products_data[2].m_rdata[
PIdx::ux][slot2_idx],
371 soa_products_data[2].m_rdata[
PIdx::uy][slot2_idx],
372 soa_products_data[2].m_rdata[
PIdx::uz][slot2_idx], mass_slot2,
373 soa_products_data[3].m_rdata[
PIdx::ux][slot3_idx],
374 soa_products_data[3].m_rdata[
PIdx::uy][slot3_idx],
375 soa_products_data[3].m_rdata[
PIdx::uz][slot3_idx], mass_slot3,
386 const auto slot0_idx = products_np_data[0] + no_product_total + with_product_offsets_data[i];
388 copy_species0[0](soa_products_data[0], soa_0,
static_cast<int>(p_pair_indices_0[i]),
389 static_cast<int>(slot0_idx), engine);
391 soa_products_data[0].m_rdata[
PIdx::w][slot0_idx] = p_pair_reaction_weight[i];
395 const auto slot2_idx = products_np_data[2] + with_product_offsets_data[i];
396 copy_species1[2](soa_products_data[2], soa_1,
static_cast<int>(p_pair_indices_1[i]),
397 static_cast<int>(slot2_idx), engine);
399 soa_products_data[2].m_rdata[
PIdx::w][slot2_idx] = p_pair_reaction_weight[i];
403 const auto slot3_idx = products_np_data[3] + with_product_offsets_data[i];
404 copy_species1[3](soa_products_data[3], soa_1,
static_cast<int>(p_pair_indices_1[i]),
405 static_cast<int>(slot3_idx), engine);
407 soa_products_data[3].m_rdata[
PIdx::w][slot3_idx] = p_pair_reaction_weight[i];
412 auto& ux0 = soa_products_data[0].m_rdata[
PIdx::ux][slot0_idx];
413 auto& uy0 = soa_products_data[0].m_rdata[
PIdx::uy][slot0_idx];
414 auto& uz0 = soa_products_data[0].m_rdata[
PIdx::uz][slot0_idx];
415 auto& ux2 = soa_products_data[2].m_rdata[
PIdx::ux][slot2_idx];
416 auto& uy2 = soa_products_data[2].m_rdata[
PIdx::uy][slot2_idx];
417 auto& uz2 = soa_products_data[2].m_rdata[
PIdx::uz][slot2_idx];
418 auto& ux3 = soa_products_data[3].m_rdata[
PIdx::ux][slot3_idx];
419 auto& uy3 = soa_products_data[3].m_rdata[
PIdx::uy][slot3_idx];
420 auto& uz3 = soa_products_data[3].m_rdata[
PIdx::uz][slot3_idx];
422#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
433 soa_products_data[2].m_rdata[PIdx::theta][slot2_idx]
434 - soa_products_data[0].m_rdata[PIdx::theta][slot0_idx]
437 ux0 = ux0buf*std::cos(theta) - uy0*std::sin(theta);
438 uy0 = ux0buf*std::sin(theta) + uy0*std::cos(theta);
444 auto const uCOM_x = (m0 * ux0 + m1 * ux3) / (m0 + m1);
445 auto const uCOM_y = (m0 * uy0 + m1 * uy3) / (m0 + m1);
446 auto const uCOM_z = (m0 * uz0 + m1 * uz3) / (m0 + m1);
461 const amrex::ParticleReal E_coll = 0.5_prt * p_non_target_in * p_non_target_in * (1.0_prt/m0 + 1.0_prt/m1);
486 const amrex::ParticleReal p_non_target_out = std::sqrt( 2.0_prt * E_out / (1.0_prt / m0 + 1.0_prt / (mass_slot2 + mass_slot3) ) );
490 ux0 *= reduce_factor;
491 uy0 *= reduce_factor;
492 uz0 *= reduce_factor;
495 ux2 = -mass_ratio * ux0;
496 uy2 = -mass_ratio * uy0;
497 uz2 = -mass_ratio * uz0;
498 ux3 = -mass_ratio * ux0;
499 uy3 = -mass_ratio * uy0;
500 uz3 = -mass_ratio * uz0;
530 const amrex::ParticleReal scaled_u2_ion = scaled_ux_ion*scaled_ux_ion + scaled_uy_ion*scaled_uy_ion + scaled_uz_ion*scaled_uz_ion;
537 E_out / (1.0_prt/m0 + 0.5_prt*scaled_u2_ion/m_ion) );
543 ux0 = p_e/m0 * scaled_ux0;
544 uy0 = p_e/m0 * scaled_uy0;
545 uz0 = p_e/m0 * scaled_uz0;
546 if (mass_slot2 < mass_slot3) {
548 ux2 = p_e/m0 * scaled_ux_new;
549 uy2 = p_e/m0 * scaled_uy_new;
550 uz2 = p_e/m0 * scaled_uz_new;
551 ux3 = p_e/m_ion * scaled_ux_ion;
552 uy3 = p_e/m_ion * scaled_uy_ion;
553 uz3 = p_e/m_ion * scaled_uz_ion;
556 ux3 = p_e/m0 * scaled_ux_new;
557 uy3 = p_e/m0 * scaled_uy_new;
558 uz3 = p_e/m0 * scaled_uz_new;
559 ux2 = p_e/m_ion * scaled_ux_ion;
560 uy2 = p_e/m_ion * scaled_uy_ion;
561 uz2 = p_e/m_ion * scaled_uz_ion;
576#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
579 ux0 = ux0buf_new*std::cos(-theta) - uy0*std::sin(-theta);
580 uy0 = ux0buf_new*std::sin(-theta) + uy0*std::cos(-theta);
588 const int start_index =
int(products_np[i]);
589 const int stop_index =
int(products_np[i] + num_added_vec[i]);
591 *pc_products[i], start_index, stop_index);
595 return num_added_vec;