59 const amrex::ParticleReal m1,
const amrex::ParticleReal m2,
68 const amrex::ParticleReal* )
const
70 using namespace amrex::literals;
86 return ((
mask[i] > 0) &
95 for (
int i = 0; i < 2; i++)
101 num_added_vec[i] =
static_cast<int>(no_product_total);
125 const index_type num_added = with_product_total * num_products;
126 num_added_vec[i] +=
static_cast<int>(num_added);
137 products_np[i] = tile_products[i]->numParticles();
138 tile_products[i]->resize(products_np[i] + num_added_vec[i]);
141 const auto soa_1 = ptile1.getParticleTileData();
142 const auto soa_2 = ptile2.getParticleTileData();
148 soa_products.push_back(tile_products[i]->getParticleTileData());
156 device_soa_products.
begin());
159 device_products_np.
begin());
173 amrex::ParticleReal mass_product1 = 0;
174 amrex::ParticleReal mass_product2 = 0;
175 if (num_product_species > 2) {
176 mass_product1 = pc_products[2]->getMass();
177 mass_product2 = pc_products[3]->getMass();
186 const auto product1_index = products_np_data[0] + no_product_p_offsets[i];
188 copy_species1[0](soa_products_data[0], soa_1,
static_cast<int>(p_pair_indices_1[i]),
189 static_cast<int>(product1_index), engine);
191 soa_products_data[0].m_rdata[
PIdx::w][product1_index] = p_pair_reaction_weight[i];
193 const auto product2_index = products_np_data[1] + no_product_p_offsets[i];
195 copy_species2[1](soa_products_data[1], soa_2,
static_cast<int>(p_pair_indices_2[i]),
196 static_cast<int>(product2_index), engine);
198 soa_products_data[1].m_rdata[
PIdx::w][product2_index] = p_pair_reaction_weight[i];
201 auto& ux1 = soa_products_data[0].m_rdata[
PIdx::ux][product1_index];
202 auto& uy1 = soa_products_data[0].m_rdata[
PIdx::uy][product1_index];
203 auto& uz1 = soa_products_data[0].m_rdata[
PIdx::uz][product1_index];
204 auto& ux2 = soa_products_data[1].m_rdata[
PIdx::ux][product2_index];
205 auto& uy2 = soa_products_data[1].m_rdata[
PIdx::uy][product2_index];
206 auto& uz2 = soa_products_data[1].m_rdata[
PIdx::uz][product2_index];
208#if (defined WARPX_DIM_RZ)
218 amrex::ParticleReal
const theta = (
219 soa_products_data[1].m_rdata[PIdx::theta][product2_index]
220 - soa_products_data[0].m_rdata[PIdx::theta][product1_index]
222 amrex::ParticleReal
const ux1buf = ux1;
223 ux1 = ux1buf*std::cos(theta) - uy1*std::sin(theta);
224 uy1 = ux1buf*std::sin(theta) + uy1*std::cos(theta);
231 auto const uCOM_x = (m1 * ux1 + m2 * ux2) / (m1 + m2);
232 auto const uCOM_y = (m1 * uy1 + m2 * uy2) / (m1 + m2);
233 auto const uCOM_z = (m1 * uz1 + m2 * uz2) / (m1 + m2);
246 ux1, uy1, uz1, std::sqrt(ux1*ux1 + uy1*uy1 + uz1*uz1), engine
250 ux2 = -ux1 * m1 / m2;
251 uy2 = -uy1 * m1 / m2;
252 uz2 = -uz1 * m1 / m2;
262 amrex::Abort(
"Forward scattering with DSMC not implemented yet.");
275#if (defined WARPX_DIM_RZ)
277 amrex::ParticleReal
const ux1buf_new = ux1;
278 ux1 = ux1buf_new*std::cos(-theta) - uy1*std::sin(-theta);
279 uy1 = ux1buf_new*std::sin(-theta) + uy1*std::cos(-theta);
287 const auto reactant1_index =
static_cast<int>(p_pair_indices_1[i]);
288 const auto product1_index = products_np_data[2] + with_product_p_offsets[i];
289 copy_species1[2](soa_products_data[2], soa_1, reactant1_index,
290 static_cast<int>(product1_index), engine);
292 soa_products_data[2].m_rdata[
PIdx::w][product1_index] = p_pair_reaction_weight[i];
295 const auto reactant2_index =
static_cast<int>(p_pair_indices_2[i]);
296 const auto product2_index = products_np_data[3] + with_product_p_offsets[i];
297 copy_species2[3](soa_products_data[3], soa_2, reactant2_index,
298 static_cast<int>(product2_index), engine);
300 soa_products_data[3].m_rdata[
PIdx::w][product2_index] = p_pair_reaction_weight[i];
303 TwoProductComputeProductMomenta(
304 soa_1.m_rdata[
PIdx::ux][reactant1_index],
305 soa_1.m_rdata[
PIdx::uy][reactant1_index],
306 soa_1.m_rdata[
PIdx::uz][reactant1_index], m1,
307 soa_2.m_rdata[
PIdx::ux][reactant2_index],
308 soa_2.m_rdata[
PIdx::uy][reactant2_index],
309 soa_2.m_rdata[
PIdx::uz][reactant2_index], m2,
310 soa_products_data[2].m_rdata[
PIdx::ux][product1_index],
311 soa_products_data[2].m_rdata[
PIdx::uy][product1_index],
312 soa_products_data[2].m_rdata[
PIdx::uz][product1_index], mass_product1,
313 soa_products_data[3].m_rdata[
PIdx::ux][product2_index],
314 soa_products_data[3].m_rdata[
PIdx::uy][product2_index],
315 soa_products_data[3].m_rdata[
PIdx::uz][product2_index], mass_product2,
326 const auto species1_index = products_np_data[0] + no_product_total + with_product_p_offsets[i];
328 copy_species1[0](soa_products_data[0], soa_1,
static_cast<int>(p_pair_indices_1[i]),
329 static_cast<int>(species1_index), engine);
331 soa_products_data[0].m_rdata[
PIdx::w][species1_index] = p_pair_reaction_weight[i];
335 const auto product1_index = products_np_data[2] + with_product_p_offsets[i];
336 copy_species2[2](soa_products_data[2], soa_2,
static_cast<int>(p_pair_indices_2[i]),
337 static_cast<int>(product1_index), engine);
339 soa_products_data[2].m_rdata[
PIdx::w][product1_index] = p_pair_reaction_weight[i];
343 const auto product2_index = products_np_data[3] + with_product_p_offsets[i];
344 copy_species2[3](soa_products_data[3], soa_2,
static_cast<int>(p_pair_indices_2[i]),
345 static_cast<int>(product2_index), engine);
347 soa_products_data[3].m_rdata[
PIdx::w][product2_index] = p_pair_reaction_weight[i];
352 auto& ux1 = soa_products_data[0].m_rdata[
PIdx::ux][species1_index];
353 auto& uy1 = soa_products_data[0].m_rdata[
PIdx::uy][species1_index];
354 auto& uz1 = soa_products_data[0].m_rdata[
PIdx::uz][species1_index];
355 auto& ux_p1 = soa_products_data[2].m_rdata[
PIdx::ux][product1_index];
356 auto& uy_p1 = soa_products_data[2].m_rdata[
PIdx::uy][product1_index];
357 auto& uz_p1 = soa_products_data[2].m_rdata[
PIdx::uz][product1_index];
358 auto& ux_p2 = soa_products_data[3].m_rdata[
PIdx::ux][product2_index];
359 auto& uy_p2 = soa_products_data[3].m_rdata[
PIdx::uy][product2_index];
360 auto& uz_p2 = soa_products_data[3].m_rdata[
PIdx::uz][product2_index];
362#if (defined WARPX_DIM_RZ)
372 amrex::ParticleReal
const theta = (
373 soa_products_data[2].m_rdata[PIdx::theta][product1_index]
374 - soa_products_data[0].m_rdata[PIdx::theta][species1_index]
376 amrex::ParticleReal
const ux1buf = ux1;
377 ux1 = ux1buf*std::cos(theta) - uy1*std::sin(theta);
378 uy1 = ux1buf*std::sin(theta) + uy1*std::cos(theta);
384 auto const uCOM_x = (m1 * ux1 + m2 * ux_p2) / (m1 + m2);
385 auto const uCOM_y = (m1 * uy1 + m2 * uy_p2) / (m1 + m2);
386 auto const uCOM_z = (m1 * uz1 + m2 * uz_p2) / (m1 + m2);
400 const amrex::ParticleReal E1 = (
403 const amrex::ParticleReal E2 = (
404 0.5_prt * m2 * (ux_p2*ux_p2 + uy_p2*uy_p2 + uz_p2*uz_p2) /
PhysConst::q_e
406 const amrex::ParticleReal E_coll = E1 + E2;
409 const amrex::ParticleReal E_out = (E_coll - reaction_energy) *
PhysConst::q_e;
438 const double n_2 = std::min<double>(E2 / E_coll, 0.5 *
amrex::Random(engine));
441 const double a = 0.5 * (1.0 - n_2);
442 const double b = 0.5 * std::sqrt(1.0 - 2.0 * n_2);
446 const double y2 = b*b - b*b/(a*a) * x*x;
447 const double n_0 = std::sqrt(y2 + x*x - x*n_2 + 0.25*n_2*n_2);
448 const double n_1 = 1.0 - n_0 - n_2;
451 const double C = std::sqrt(E_out / (
452 n_0*n_0 / (2.0 * m1) + n_1*n_1 / (2.0 * mass_product1) + n_2*n_2 / (2.0 * mass_product2)
460 const double cos_alpha = (n_0*n_0 + n_1*n_1 - n_2*n_2) / (2.0 * n_0 * n_1);
461 const double sin_alpha = std::sqrt(1.0 - cos_alpha*cos_alpha);
462 const double cos_gamma = (n_0*n_0 + n_2*n_2 - n_1*n_1) / (2.0 * n_0 * n_2);
463 const double sin_gamma = std::sqrt(1.0 - cos_gamma*cos_gamma);
469 const double cos_theta = std::cos(Theta);
470 const double sin_theta = std::sin(Theta);
471 const double cos_phi = std::cos(phi);
472 const double sin_phi = std::sin(phi);
475 ux1 =
static_cast<amrex::ParticleReal
>(C * n_0 / m1 * cos_theta * cos_phi);
476 uy1 =
static_cast<amrex::ParticleReal
>(C * n_0 / m1 * cos_theta * sin_phi);
477 uz1 =
static_cast<amrex::ParticleReal
>(-C * n_0 / m1 * sin_theta);
479 ux_p1 =
static_cast<amrex::ParticleReal
>(C * n_1 / mass_product1 * (-cos_alpha * cos_theta * cos_phi - sin_alpha * sin_phi));
480 uy_p1 =
static_cast<amrex::ParticleReal
>(C * n_1 / mass_product1 * (-cos_alpha * cos_theta * sin_phi + sin_alpha * cos_phi));
481 uz_p1 =
static_cast<amrex::ParticleReal
>(C * n_1 / mass_product1 * (cos_alpha * sin_theta));
483 ux_p2 =
static_cast<amrex::ParticleReal
>(C * n_2 / mass_product2 * (-cos_gamma * cos_theta * cos_phi + sin_gamma * sin_phi));
484 uy_p2 =
static_cast<amrex::ParticleReal
>(C * n_2 / mass_product2 * (-cos_gamma * cos_theta * sin_phi - sin_gamma * cos_phi));
485 uz_p2 =
static_cast<amrex::ParticleReal
>(C * n_2 / mass_product2 * (cos_gamma * sin_theta));
498#if (defined WARPX_DIM_RZ)
500 amrex::ParticleReal
const ux1buf_new = ux1;
501 ux1 = ux1buf_new*std::cos(-theta) - uy1*std::sin(-theta);
502 uy1 = ux1buf_new*std::sin(-theta) + uy1*std::cos(-theta);
510 const int start_index = int(products_np[i]);
511 const int stop_index = int(products_np[i] + num_added_vec[i]);
514 pc_products[i]->getUserRealAttribs(), pc_products[i]->getUserIntAttribs(),
515 pc_products[i]->GetRealSoANames(), pc_products[i]->GetIntSoANames(),
516 pc_products[i]->getUserRealAttribParser(),
517 pc_products[i]->getUserIntAttribParser(),
521 pc_products[i]->get_breit_wheeler_engine_ptr(),
522 pc_products[i]->get_quantum_sync_engine_ptr(),
524 pc_products[i]->getIonizationInitialLevel(),
525 start_index, stop_index);
529 return num_added_vec;