143 return ((
mask[i] > 0) &
152 for (
int i = 0; i < 2; i++)
157 num_added_vec[i] =
static_cast<int>(no_product_total);
180 const index_type num_added = with_product_total * num_products;
181 num_added_vec[i] +=
static_cast<int>(num_added);
192 products_np[i] = tile_products[i]->numParticles();
193 tile_products[i]->resize(products_np[i] + num_added_vec[i]);
196 const auto soa_0 = ptile0.getParticleTileData();
197 const auto soa_1 = ptile1.getParticleTileData();
203 soa_products.push_back(tile_products[i]->getParticleTileData());
211 device_soa_products.
begin());
214 device_products_np.
begin());
230 if (num_product_species > 2) {
231 mass_slot2 = pc_products[2]->getMass();
232 mass_slot3 = pc_products[3]->getMass();
241 const auto slot0_idx = products_np_data[0] + no_product_offsets_data[i];
243 copy_species0[0](soa_products_data[0], soa_0,
static_cast<int>(p_pair_indices_0[i]),
244 static_cast<int>(slot0_idx), engine);
246 soa_products_data[0].m_rdata[
PIdx::w][slot0_idx] = p_pair_reaction_weight[i];
248 const auto slot1_idx = products_np_data[1] + no_product_offsets_data[i];
250 copy_species1[1](soa_products_data[1], soa_1,
static_cast<int>(p_pair_indices_1[i]),
251 static_cast<int>(slot1_idx), engine);
253 soa_products_data[1].m_rdata[
PIdx::w][slot1_idx] = p_pair_reaction_weight[i];
256 auto& ux0 = soa_products_data[0].m_rdata[
PIdx::ux][slot0_idx];
257 auto& uy0 = soa_products_data[0].m_rdata[
PIdx::uy][slot0_idx];
258 auto& uz0 = soa_products_data[0].m_rdata[
PIdx::uz][slot0_idx];
259 auto& ux1 = soa_products_data[1].m_rdata[
PIdx::ux][slot1_idx];
260 auto& uy1 = soa_products_data[1].m_rdata[
PIdx::uy][slot1_idx];
261 auto& uz1 = soa_products_data[1].m_rdata[
PIdx::uz][slot1_idx];
263#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
274 soa_products_data[1].m_rdata[PIdx::theta][slot1_idx]
275 - soa_products_data[0].m_rdata[PIdx::theta][slot0_idx]
278 ux0 = ux0buf*std::cos(theta) - uy0*std::sin(theta);
279 uy0 = ux0buf*std::sin(theta) + uy0*std::cos(theta);
286 auto const uCOM_x = (m0 * ux0 + m1 * ux1) / (m0 + m1);
287 auto const uCOM_y = (m0 * uy0 + m1 * uy1) / (m0 + m1);
288 auto const uCOM_z = (m0 * uz0 + m1 * uz1) / (m0 + m1);
301 ux0, uy0, uz0, std::sqrt(ux0*ux0 + uy0*uy0 + uz0*uz0), engine
305 ux1 = -ux0 * m0 / m1;
306 uy1 = -uy0 * m0 / m1;
307 uz1 = -uz0 * m0 / m1;
317 amrex::Abort(
"Forward scattering with DSMC not implemented yet.");
330#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
333 ux0 = ux0buf_new*std::cos(-theta) - uy0*std::sin(-theta);
334 uy0 = ux0buf_new*std::sin(-theta) + uy0*std::cos(-theta);
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];
358 TwoProductComputeProductMomenta(
361 soa_0.m_rdata[
PIdx::uz][src0_idx], m0,
364 soa_1.m_rdata[
PIdx::uz][src1_idx], m1,
365 soa_products_data[2].m_rdata[
PIdx::ux][slot2_idx],
366 soa_products_data[2].m_rdata[
PIdx::uy][slot2_idx],
367 soa_products_data[2].m_rdata[
PIdx::uz][slot2_idx], mass_slot2,
368 soa_products_data[3].m_rdata[
PIdx::ux][slot3_idx],
369 soa_products_data[3].m_rdata[
PIdx::uy][slot3_idx],
370 soa_products_data[3].m_rdata[
PIdx::uz][slot3_idx], mass_slot3,
381 const auto slot0_idx = products_np_data[0] + no_product_total + with_product_offsets_data[i];
383 copy_species0[0](soa_products_data[0], soa_0,
static_cast<int>(p_pair_indices_0[i]),
384 static_cast<int>(slot0_idx), engine);
386 soa_products_data[0].m_rdata[
PIdx::w][slot0_idx] = p_pair_reaction_weight[i];
390 const auto slot2_idx = products_np_data[2] + with_product_offsets_data[i];
391 copy_species1[2](soa_products_data[2], soa_1,
static_cast<int>(p_pair_indices_1[i]),
392 static_cast<int>(slot2_idx), engine);
394 soa_products_data[2].m_rdata[
PIdx::w][slot2_idx] = p_pair_reaction_weight[i];
398 const auto slot3_idx = products_np_data[3] + with_product_offsets_data[i];
399 copy_species1[3](soa_products_data[3], soa_1,
static_cast<int>(p_pair_indices_1[i]),
400 static_cast<int>(slot3_idx), engine);
402 soa_products_data[3].m_rdata[
PIdx::w][slot3_idx] = p_pair_reaction_weight[i];
407 auto& ux0 = soa_products_data[0].m_rdata[
PIdx::ux][slot0_idx];
408 auto& uy0 = soa_products_data[0].m_rdata[
PIdx::uy][slot0_idx];
409 auto& uz0 = soa_products_data[0].m_rdata[
PIdx::uz][slot0_idx];
410 auto& ux2 = soa_products_data[2].m_rdata[
PIdx::ux][slot2_idx];
411 auto& uy2 = soa_products_data[2].m_rdata[
PIdx::uy][slot2_idx];
412 auto& uz2 = soa_products_data[2].m_rdata[
PIdx::uz][slot2_idx];
413 auto& ux3 = soa_products_data[3].m_rdata[
PIdx::ux][slot3_idx];
414 auto& uy3 = soa_products_data[3].m_rdata[
PIdx::uy][slot3_idx];
415 auto& uz3 = soa_products_data[3].m_rdata[
PIdx::uz][slot3_idx];
417#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
428 soa_products_data[2].m_rdata[PIdx::theta][slot2_idx]
429 - soa_products_data[0].m_rdata[PIdx::theta][slot0_idx]
432 ux0 = ux0buf*std::cos(theta) - uy0*std::sin(theta);
433 uy0 = ux0buf*std::sin(theta) + uy0*std::cos(theta);
439 auto const uCOM_x = (m0 * ux0 + m1 * ux3) / (m0 + m1);
440 auto const uCOM_y = (m0 * uy0 + m1 * uy3) / (m0 + m1);
441 auto const uCOM_z = (m0 * uz0 + m1 * uz3) / (m0 + m1);
493 const double n_2 = std::min<double>(E2 / E_coll, 0.5 *
amrex::Random(engine));
496 const double a = 0.5 * (1.0 - n_2);
497 const double b = 0.5 * std::sqrt(1.0 - 2.0 * n_2);
501 const double y2 = b*b - b*b/(a*a) * x*x;
502 const double n_0 = std::sqrt(y2 + x*x - x*n_2 + 0.25*n_2*n_2);
503 const double n_1 = 1.0 - n_0 - n_2;
506 const double C = std::sqrt(E_out / (
507 n_0*n_0 / (2.0 * m0) + n_1*n_1 / (2.0 * mass_slot2) + n_2*n_2 / (2.0 * mass_slot3)
515 const double cos_alpha = (n_0*n_0 + n_1*n_1 - n_2*n_2) / (2.0 * n_0 * n_1);
516 const double sin_alpha = std::sqrt(1.0 - cos_alpha*cos_alpha);
517 const double cos_gamma = (n_0*n_0 + n_2*n_2 - n_1*n_1) / (2.0 * n_0 * n_2);
518 const double sin_gamma = std::sqrt(1.0 - cos_gamma*cos_gamma);
524 const double cos_theta = std::cos(Theta);
525 const double sin_theta = std::sin(Theta);
526 const double cos_phi = std::cos(phi);
527 const double sin_phi = std::sin(phi);
534 ux2 =
static_cast<amrex::ParticleReal>(C * n_1 / mass_slot2 * (-cos_alpha * cos_theta * cos_phi - sin_alpha * sin_phi));
535 uy2 =
static_cast<amrex::ParticleReal>(C * n_1 / mass_slot2 * (-cos_alpha * cos_theta * sin_phi + sin_alpha * cos_phi));
538 ux3 =
static_cast<amrex::ParticleReal>(C * n_2 / mass_slot3 * (-cos_gamma * cos_theta * cos_phi + sin_gamma * sin_phi));
539 uy3 =
static_cast<amrex::ParticleReal>(C * n_2 / mass_slot3 * (-cos_gamma * cos_theta * sin_phi - sin_gamma * cos_phi));
553#if defined(WARPX_DIM_RZ) || defined(WARPX_DIM_RCYLINDER)
556 ux0 = ux0buf_new*std::cos(-theta) - uy0*std::sin(-theta);
557 uy0 = ux0buf_new*std::sin(-theta) + uy0*std::cos(-theta);
565 const int start_index =
int(products_np[i]);
566 const int stop_index =
int(products_np[i] + num_added_vec[i]);
568 *pc_products[i], start_index, stop_index);
572 return num_added_vec;