58 const amrex::ParticleReal m1,
const amrex::ParticleReal m2,
67 const amrex::ParticleReal* )
const
69 using namespace amrex::literals;
85 return ((
mask[i] > 0) &
94 for (
int i = 0; i < 2; i++)
100 num_added_vec[i] =
static_cast<int>(no_product_total);
124 const index_type num_added = with_product_total * num_products;
125 num_added_vec[i] +=
static_cast<int>(num_added);
136 products_np[i] = tile_products[i]->numParticles();
137 tile_products[i]->resize(products_np[i] + num_added_vec[i]);
140 const auto soa_1 = ptile1.getParticleTileData();
141 const auto soa_2 = ptile2.getParticleTileData();
147 soa_products.push_back(tile_products[i]->getParticleTileData());
155 device_soa_products.
begin());
158 device_products_np.
begin());
172 amrex::ParticleReal mass_product1 = 0;
173 amrex::ParticleReal mass_product2 = 0;
174 if (num_product_species > 2) {
175 mass_product1 = pc_products[2]->getMass();
176 mass_product2 = pc_products[3]->getMass();
185 const auto product1_index = products_np_data[0] + no_product_p_offsets[i];
187 copy_species1[0](soa_products_data[0], soa_1,
static_cast<int>(p_pair_indices_1[i]),
188 static_cast<int>(product1_index), engine);
190 soa_products_data[0].m_rdata[
PIdx::w][product1_index] = p_pair_reaction_weight[i];
192 const auto product2_index = products_np_data[1] + no_product_p_offsets[i];
194 copy_species2[1](soa_products_data[1], soa_2,
static_cast<int>(p_pair_indices_2[i]),
195 static_cast<int>(product2_index), engine);
197 soa_products_data[1].m_rdata[
PIdx::w][product2_index] = p_pair_reaction_weight[i];
200 auto& ux1 = soa_products_data[0].m_rdata[
PIdx::ux][product1_index];
201 auto& uy1 = soa_products_data[0].m_rdata[
PIdx::uy][product1_index];
202 auto& uz1 = soa_products_data[0].m_rdata[
PIdx::uz][product1_index];
203 auto& ux2 = soa_products_data[1].m_rdata[
PIdx::ux][product2_index];
204 auto& uy2 = soa_products_data[1].m_rdata[
PIdx::uy][product2_index];
205 auto& uz2 = soa_products_data[1].m_rdata[
PIdx::uz][product2_index];
207#if (defined WARPX_DIM_RZ)
217 amrex::ParticleReal
const theta = (
218 soa_products_data[1].m_rdata[
PIdx::theta][product2_index]
219 - soa_products_data[0].m_rdata[
PIdx::theta][product1_index]
221 amrex::ParticleReal
const ux1buf = ux1;
222 ux1 = ux1buf*std::cos(theta) - uy1*std::sin(theta);
223 uy1 = ux1buf*std::sin(theta) + uy1*std::cos(theta);
229 auto const uCOM_x = (m1 * ux1 + m2 * ux2) / (m1 + m2);
230 auto const uCOM_y = (m1 * uy1 + m2 * uy2) / (m1 + m2);
231 auto const uCOM_z = (m1 * uz1 + m2 * uz2) / (m1 + m2);
244 ux1, uy1, uz1, std::sqrt(ux1*ux1 + uy1*uy1 + uz1*uz1), engine
248 ux2 = -ux1 * m1 / m2;
249 uy2 = -uy1 * m1 / m2;
250 uz2 = -uz1 * m1 / m2;
260 amrex::Abort(
"Forward scattering with DSMC not implemented yet.");
273#if (defined WARPX_DIM_RZ)
275 amrex::ParticleReal
const ux1buf_new = ux1;
276 ux1 = ux1buf_new*std::cos(-theta) - uy1*std::sin(-theta);
277 uy1 = ux1buf_new*std::sin(-theta) + uy1*std::cos(-theta);
285 const auto product1_index = products_np_data[2] + with_product_p_offsets[i];
286 copy_species1[2](soa_products_data[2], soa_1,
static_cast<int>(p_pair_indices_1[i]),
287 static_cast<int>(product1_index), engine);
289 soa_products_data[2].m_rdata[
PIdx::w][product1_index] = p_pair_reaction_weight[i];
292 const auto product2_index = products_np_data[3] + with_product_p_offsets[i];
293 copy_species2[3](soa_products_data[3], soa_2,
static_cast<int>(p_pair_indices_2[i]),
294 static_cast<int>(product2_index), engine);
296 soa_products_data[3].m_rdata[
PIdx::w][product2_index] = p_pair_reaction_weight[i];
300 const auto species1_index = products_np_data[0] + no_product_total + with_product_p_offsets[i];
302 copy_species1[0](soa_products_data[0], soa_1,
static_cast<int>(p_pair_indices_1[i]),
303 static_cast<int>(species1_index), engine);
305 soa_products_data[0].m_rdata[
PIdx::w][species1_index] = p_pair_reaction_weight[i];
309 const auto product1_index = products_np_data[2] + with_product_p_offsets[i];
310 copy_species2[2](soa_products_data[2], soa_2,
static_cast<int>(p_pair_indices_2[i]),
311 static_cast<int>(product1_index), engine);
313 soa_products_data[2].m_rdata[
PIdx::w][product1_index] = p_pair_reaction_weight[i];
317 const auto product2_index = products_np_data[3] + with_product_p_offsets[i];
318 copy_species2[3](soa_products_data[3], soa_2,
static_cast<int>(p_pair_indices_2[i]),
319 static_cast<int>(product2_index), engine);
321 soa_products_data[3].m_rdata[
PIdx::w][product2_index] = p_pair_reaction_weight[i];
326 auto& ux1 = soa_products_data[0].m_rdata[
PIdx::ux][species1_index];
327 auto& uy1 = soa_products_data[0].m_rdata[
PIdx::uy][species1_index];
328 auto& uz1 = soa_products_data[0].m_rdata[
PIdx::uz][species1_index];
329 auto& ux_p1 = soa_products_data[2].m_rdata[
PIdx::ux][product1_index];
330 auto& uy_p1 = soa_products_data[2].m_rdata[
PIdx::uy][product1_index];
331 auto& uz_p1 = soa_products_data[2].m_rdata[
PIdx::uz][product1_index];
332 auto& ux_p2 = soa_products_data[3].m_rdata[
PIdx::ux][product2_index];
333 auto& uy_p2 = soa_products_data[3].m_rdata[
PIdx::uy][product2_index];
334 auto& uz_p2 = soa_products_data[3].m_rdata[
PIdx::uz][product2_index];
336#if (defined WARPX_DIM_RZ)
346 amrex::ParticleReal
const theta = (
347 soa_products_data[2].m_rdata[
PIdx::theta][product1_index]
348 - soa_products_data[0].m_rdata[
PIdx::theta][species1_index]
350 amrex::ParticleReal
const ux1buf = ux1;
351 ux1 = ux1buf*std::cos(theta) - uy1*std::sin(theta);
352 uy1 = ux1buf*std::sin(theta) + uy1*std::cos(theta);
358 auto const uCOM_x = (m1 * ux1 + m2 * ux_p2) / (m1 + m2);
359 auto const uCOM_y = (m1 * uy1 + m2 * uy_p2) / (m1 + m2);
360 auto const uCOM_z = (m1 * uz1 + m2 * uz_p2) / (m1 + m2);
374 const amrex::ParticleReal E1 = (
377 const amrex::ParticleReal E2 = (
378 0.5_prt * m2 * (ux_p2*ux_p2 + uy_p2*uy_p2 + uz_p2*uz_p2) /
PhysConst::q_e
380 const amrex::ParticleReal E_coll = E1 + E2;
383 const amrex::ParticleReal E_out = (E_coll - ionization_energy) *
PhysConst::q_e;
412 const amrex::ParticleReal n_2 = std::min(E2 / E_coll, 0.5_prt *
static_cast<amrex::ParticleReal
>(
amrex::Random(engine)));
415 const amrex::ParticleReal a = 0.5_prt * (1.0_prt - n_2);
416 const amrex::ParticleReal b = 0.5_prt * std::sqrt(1.0_prt - 2.0_prt * n_2);
419 const amrex::ParticleReal x = (2._prt *
amrex::Random(engine) - 1.0_prt) * a;
420 const amrex::ParticleReal y2 = b*b - b*b/(a*a) * x*x;
421 const amrex::ParticleReal n_0 = std::sqrt(y2 + x*x - x*n_2 + 0.25_prt*n_2*n_2);
422 const amrex::ParticleReal n_1 = 1.0_prt - n_0 - n_2;
425 const amrex::ParticleReal C = std::sqrt(E_out / (
426 n_0*n_0 / (2.0_prt * m1) + n_1*n_1 / (2.0_prt * mass_product1) + n_2*n_2 / (2.0_prt * mass_product2)
434 const amrex::ParticleReal cos_alpha = (n_0*n_0 + n_1*n_1 - n_2*n_2) / (2.0_prt * n_0 * n_1);
435 const amrex::ParticleReal sin_alpha = std::sqrt(1.0_prt - cos_alpha*cos_alpha);
436 const amrex::ParticleReal cos_gamma = (n_0*n_0 + n_2*n_2 - n_1*n_1) / (2.0_prt * n_0 * n_2);
437 const amrex::ParticleReal sin_gamma = std::sqrt(1.0_prt - cos_gamma*cos_gamma);
443 const amrex::ParticleReal cos_theta = std::cos(Theta);
444 const amrex::ParticleReal sin_theta = std::sin(Theta);
445 const amrex::ParticleReal cos_phi = std::cos(phi);
446 const amrex::ParticleReal sin_phi = std::sin(phi);
449 ux1 = C * n_0 / m1 * cos_theta * cos_phi;
450 uy1 = C * n_0 / m1 * cos_theta * sin_phi;
451 uz1 = -C * n_0 / m1 * sin_theta;
453 ux_p1 = C * n_1 / mass_product1 * (-cos_alpha * cos_theta * cos_phi - sin_alpha * sin_phi);
454 uy_p1 = C * n_1 / mass_product1 * (-cos_alpha * cos_theta * sin_phi + sin_alpha * cos_phi);
455 uz_p1 = C * n_1 / mass_product1 * (cos_alpha * sin_theta);
457 ux_p2 = C * n_2 / mass_product2 * (-cos_gamma * cos_theta * cos_phi + sin_gamma * sin_phi);
458 uy_p2 = C * n_2 / mass_product2 * (-cos_gamma * cos_theta * sin_phi - sin_gamma * cos_phi);
459 uz_p2 = C * n_2 / mass_product2 * (cos_gamma * sin_theta);
472#if (defined WARPX_DIM_RZ)
474 amrex::ParticleReal
const ux1buf_new = ux1;
475 ux1 = ux1buf_new*std::cos(-theta) - uy1*std::sin(-theta);
476 uy1 = ux1buf_new*std::sin(-theta) + uy1*std::cos(-theta);
484 const int start_index = int(products_np[i]);
485 const int stop_index = int(products_np[i] + num_added_vec[i]);
488 pc_products[i]->getUserRealAttribs(), pc_products[i]->getUserIntAttribs(),
489 pc_products[i]->GetRealSoANames(), pc_products[i]->GetIntSoANames(),
490 pc_products[i]->getUserRealAttribParser(),
491 pc_products[i]->getUserIntAttribParser(),
495 pc_products[i]->get_breit_wheeler_engine_ptr(),
496 pc_products[i]->get_quantum_sync_engine_ptr(),
498 pc_products[i]->getIonizationInitialLevel(),
499 start_index, stop_index);
503 return num_added_vec;