150 if (
mask[i] == 0) {
return 0; }
151 const auto selected_process_index =
mask[i] - 1;
152 auto const& scattering_process = scattering_processes[selected_process_index];
153 return !scattering_process.m_produces_products;
160 for (
int i = 0; i < 2; i++)
165 num_added_vec[i] =
static_cast<int>(no_product_total);
176 if (
mask[i] == 0) {
return 0; }
177 const auto selected_process_index =
mask[i] - 1;
178 auto const& scattering_process = scattering_processes[selected_process_index];
179 return scattering_process.m_produces_products;
189 const index_type num_added = with_product_total * num_products;
190 num_added_vec[i] +=
static_cast<int>(num_added);
201 products_np[i] = tile_products[i]->numParticles();
202 tile_products[i]->resize(products_np[i] + num_added_vec[i]);
205 const auto soa_0 = ptile0.getParticleTileData();
206 const auto soa_1 = ptile1.getParticleTileData();
212 soa_products.push_back(tile_products[i]->getParticleTileData());
220 device_soa_products.
begin());
223 device_products_np.
begin());
238 if (num_product_species > 2) {
239 mass_slot2 = pc_products[2]->getMass();
240 mass_slot3 = pc_products[3]->getMass();
248 if (
mask[i] == 0) {
return; }
251 const auto selected_process_index =
mask[i] - 1;
252 auto const& scattering_process = scattering_processes[selected_process_index];
253 const auto process_type = scattering_process.m_type;
255 if (!scattering_process.m_produces_products)
257 const auto slot0_idx = products_np_data[0] + no_product_offsets_data[i];
259 copy_species0[0](soa_products_data[0], soa_0,
static_cast<int>(p_pair_indices_0[i]),
260 static_cast<int>(slot0_idx), engine);
262 soa_products_data[0].m_rdata[
PIdx::w][slot0_idx] = p_pair_reaction_weight[i];
264 const auto slot1_idx = products_np_data[1] + no_product_offsets_data[i];
266 copy_species1[1](soa_products_data[1], soa_1,
static_cast<int>(p_pair_indices_1[i]),
267 static_cast<int>(slot1_idx), engine);
269 soa_products_data[1].m_rdata[
PIdx::w][slot1_idx] = p_pair_reaction_weight[i];
272 auto& ux0 = soa_products_data[0].m_rdata[
PIdx::ux][slot0_idx];
273 auto& uy0 = soa_products_data[0].m_rdata[
PIdx::uy][slot0_idx];
274 auto& uz0 = soa_products_data[0].m_rdata[
PIdx::uz][slot0_idx];
275 auto& ux1 = soa_products_data[1].m_rdata[
PIdx::ux][slot1_idx];
276 auto& uy1 = soa_products_data[1].m_rdata[
PIdx::uy][slot1_idx];
277 auto& uz1 = soa_products_data[1].m_rdata[
PIdx::uz][slot1_idx];
283 auto const uCOM_x = (m0 * ux0 + m1 * ux1) / (m0 + m1);
284 auto const uCOM_y = (m0 * uy0 + m1 * uy1) / (m0 + m1);
285 auto const uCOM_z = (m0 * uz0 + m1 * uz1) / (m0 + m1);
303 const auto u0_sq = ux0*ux0 + uy0*uy0 + uz0*uz0;
304 const auto E_com = 0.5_prt * m0 * u0_sq * (m0 + m1) / m1;
305 const auto E_out = E_com - scattering_process.m_energy_penalty *
PhysConst::q_e;
306 const auto u0_new = std::sqrt(u0_sq * E_out / E_com);
310 ux1 = -ux0 * m0 / m1;
311 uy1 = -uy0 * m0 / m1;
312 uz1 = -uz0 * m0 / m1;
322 amrex::Abort(
"Forward scattering with DSMC not implemented yet.");
342 const auto src0_idx =
static_cast<int>(p_pair_indices_0[i]);
343 const auto slot2_idx = products_np_data[2] + with_product_offsets_data[i];
344 copy_species0[2](soa_products_data[2], soa_0, src0_idx,
345 static_cast<int>(slot2_idx), engine);
347 soa_products_data[2].m_rdata[
PIdx::w][slot2_idx] = p_pair_reaction_weight[i];
350 const auto src1_idx =
static_cast<int>(p_pair_indices_1[i]);
351 const auto slot3_idx = products_np_data[3] + with_product_offsets_data[i];
352 copy_species1[3](soa_products_data[3], soa_1, src1_idx,
353 static_cast<int>(slot3_idx), engine);
355 soa_products_data[3].m_rdata[
PIdx::w][slot3_idx] = p_pair_reaction_weight[i];
362#if defined(WARPX_DIM_1D_Z)
363 constexpr std::array<int, 1> position_indices = {
PIdx::z};
364#elif defined(WARPX_DIM_XZ)
365 constexpr std::array<int, 2> position_indices = {
PIdx::x,
PIdx::z};
366#elif defined(WARPX_DIM_RZ)
367 constexpr std::array<int, 3> position_indices = {PIdx::r,
PIdx::z, PIdx::theta};
368#elif defined(WARPX_DIM_RCYLINDER)
369 constexpr std::array<int, 2> position_indices = {PIdx::r, PIdx::theta};
370#elif defined(WARPX_DIM_RSPHERE)
371 constexpr std::array<int, 3> position_indices = {PIdx::r, PIdx::theta, PIdx::phi};
372#elif defined(WARPX_DIM_3D)
373 constexpr std::array<int, 3> position_indices = {
PIdx::x, PIdx::y,
PIdx::z};
376 for (
int const idim : position_indices) {
377 soa_products_data[2].m_rdata[idim][slot2_idx] = soa_1.m_rdata[idim][src1_idx];
378 soa_products_data[3].m_rdata[idim][slot3_idx] = soa_0.m_rdata[idim][src0_idx];
383 TwoProductComputeProductMomenta(
386 soa_0.m_rdata[
PIdx::uz][src0_idx], m0,
389 soa_1.m_rdata[
PIdx::uz][src1_idx], m1,
390 soa_products_data[2].m_rdata[
PIdx::ux][slot2_idx],
391 soa_products_data[2].m_rdata[
PIdx::uy][slot2_idx],
392 soa_products_data[2].m_rdata[
PIdx::uz][slot2_idx], mass_slot2,
393 soa_products_data[3].m_rdata[
PIdx::ux][slot3_idx],
394 soa_products_data[3].m_rdata[
PIdx::uy][slot3_idx],
395 soa_products_data[3].m_rdata[
PIdx::uz][slot3_idx], mass_slot3,
406 const auto slot0_idx = products_np_data[0] + no_product_total + with_product_offsets_data[i];
408 copy_species0[0](soa_products_data[0], soa_0,
static_cast<int>(p_pair_indices_0[i]),
409 static_cast<int>(slot0_idx), engine);
411 soa_products_data[0].m_rdata[
PIdx::w][slot0_idx] = p_pair_reaction_weight[i];
415 const auto slot2_idx = products_np_data[2] + with_product_offsets_data[i];
416 copy_species1[2](soa_products_data[2], soa_1,
static_cast<int>(p_pair_indices_1[i]),
417 static_cast<int>(slot2_idx), engine);
419 soa_products_data[2].m_rdata[
PIdx::w][slot2_idx] = p_pair_reaction_weight[i];
423 const auto slot3_idx = products_np_data[3] + with_product_offsets_data[i];
424 copy_species1[3](soa_products_data[3], soa_1,
static_cast<int>(p_pair_indices_1[i]),
425 static_cast<int>(slot3_idx), engine);
427 soa_products_data[3].m_rdata[
PIdx::w][slot3_idx] = p_pair_reaction_weight[i];
432 auto& ux0 = soa_products_data[0].m_rdata[
PIdx::ux][slot0_idx];
433 auto& uy0 = soa_products_data[0].m_rdata[
PIdx::uy][slot0_idx];
434 auto& uz0 = soa_products_data[0].m_rdata[
PIdx::uz][slot0_idx];
435 auto& ux2 = soa_products_data[2].m_rdata[
PIdx::ux][slot2_idx];
436 auto& uy2 = soa_products_data[2].m_rdata[
PIdx::uy][slot2_idx];
437 auto& uz2 = soa_products_data[2].m_rdata[
PIdx::uz][slot2_idx];
438 auto& ux3 = soa_products_data[3].m_rdata[
PIdx::ux][slot3_idx];
439 auto& uy3 = soa_products_data[3].m_rdata[
PIdx::uy][slot3_idx];
440 auto& uz3 = soa_products_data[3].m_rdata[
PIdx::uz][slot3_idx];
442#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
453 soa_products_data[2].m_rdata[PIdx::theta][slot2_idx]
454 - soa_products_data[0].m_rdata[PIdx::theta][slot0_idx]
457 ux0 = ux0buf*std::cos(theta) - uy0*std::sin(theta);
458 uy0 = ux0buf*std::sin(theta) + uy0*std::cos(theta);
464 auto const uCOM_x = (m0 * ux0 + m1 * ux3) / (m0 + m1);
465 auto const uCOM_y = (m0 * uy0 + m1 * uy3) / (m0 + m1);
466 auto const uCOM_z = (m0 * uz0 + m1 * uz3) / (m0 + m1);
481 const amrex::ParticleReal E_coll = 0.5_prt * p_non_target_in * p_non_target_in * (1.0_prt/m0 + 1.0_prt/m1);
507 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) ) );
511 ux0 *= reduce_factor;
512 uy0 *= reduce_factor;
513 uz0 *= reduce_factor;
516 ux2 = -mass_ratio * ux0;
517 uy2 = -mass_ratio * uy0;
518 uz2 = -mass_ratio * uz0;
519 ux3 = -mass_ratio * ux0;
520 uy3 = -mass_ratio * uy0;
521 uz3 = -mass_ratio * uz0;
551 const amrex::ParticleReal scaled_u2_ion = scaled_ux_ion*scaled_ux_ion + scaled_uy_ion*scaled_uy_ion + scaled_uz_ion*scaled_uz_ion;
558 E_out / (1.0_prt/m0 + 0.5_prt*scaled_u2_ion/m_ion) );
564 ux0 = p_e/m0 * scaled_ux0;
565 uy0 = p_e/m0 * scaled_uy0;
566 uz0 = p_e/m0 * scaled_uz0;
567 if (mass_slot2 < mass_slot3) {
569 ux2 = p_e/m0 * scaled_ux_new;
570 uy2 = p_e/m0 * scaled_uy_new;
571 uz2 = p_e/m0 * scaled_uz_new;
572 ux3 = p_e/m_ion * scaled_ux_ion;
573 uy3 = p_e/m_ion * scaled_uy_ion;
574 uz3 = p_e/m_ion * scaled_uz_ion;
577 ux3 = p_e/m0 * scaled_ux_new;
578 uy3 = p_e/m0 * scaled_uy_new;
579 uz3 = p_e/m0 * scaled_uz_new;
580 ux2 = p_e/m_ion * scaled_ux_ion;
581 uy2 = p_e/m_ion * scaled_uy_ion;
582 uz2 = p_e/m_ion * scaled_uz_ion;
597#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
600 ux0 = ux0buf_new*std::cos(-theta) - uy0*std::sin(-theta);
601 uy0 = ux0buf_new*std::sin(-theta) + uy0*std::cos(-theta);
609 const int start_index =
int(products_np[i]);
610 const int stop_index =
int(products_np[i] + num_added_vec[i]);
612 *pc_products[i], start_index, stop_index);
616 return num_added_vec;