@@ -393,94 +393,38 @@ public:
393393 uz_p2 -= uCOM_z;
394394
395395 if (mask[i] == int (ScatteringProcessType::IONIZATION)) {
396- // calculate kinetic energy of the collision (in eV)
397- const amrex::ParticleReal E1 = (
398- 0 .5_prt * m1 * (ux1*ux1 + uy1*uy1 + uz1*uz1) / PhysConst::q_e
399- );
400- const amrex::ParticleReal E2 = (
401- 0 .5_prt * m2 * (ux_p2*ux_p2 + uy_p2*uy_p2 + uz_p2*uz_p2) / PhysConst::q_e
402- );
403- const amrex::ParticleReal E_coll = E1 + E2 ;
404-
405- // subtract the energy cost for ionization
406- const amrex::ParticleReal E_out = (E_coll - ionization_energy) * PhysConst::q_e;
407-
408- // Momentum and energy division after the ionization event
409- // is done as follows:
410- // Three numbers are generated that satisfy the triangle
411- // inequality. These numbers will be scaled to give the
412- // momentum for each particle (satisfying the triangle
413- // inequality ensures that the momentum vectors can be
414- // arranged such that the net linear momentum is zero).
415- // Product 2 is definitely an ion, so we first choose its
416- // proportion to be n_2 = min(E2 / E_coll, 0.5 * R), where
417- // R is a random number between 0 and 1.
418- // The other two numbers (n_0 & n_1) are then found
419- // by choosing a random point on the ellipse characterized
420- // by the semi-major and semi-minor axes
421- // a = (1 - n_0) / 2.0
422- // b = 0.5 * sqrt(1 - 2 * n_0)
423- // The numbers are found by randomly sampling an x value
424- // between -a and a, and finding the corresponding y value
425- // that falls on the ellipse: y^2 = b^2 - b^2/a^2 * x^2.
426- // Then n_0 = sqrt(y^2 + (x - n_2/2)^2) and
427- // n_1 = 1 - n_2 - n_0.
428- // Next, we need to find the number C, such that if
429- // p_i = C * n_i, we would have E_0 + E_1 + E_2 = E_out
430- // where E_i = p_i^2 / (2 M_i), i.e.,
431- // C^2 * \sum_i [n_i^2 / (2 M_i)] = E_out
432- // After C is determined the momentum vectors are arranged
433- // such that the net linear momentum is zero.
434-
435- const amrex::ParticleReal n_2 = std::min (E2 / E_coll, 0 .5_prt * amrex::Random (engine));
436-
437- // find ellipse semi-major and minor axis
438- const amrex::ParticleReal a = 0 .5_prt * (1 .0_prt - n_2);
439- const amrex::ParticleReal b = 0 .5_prt * std::sqrt (1 .0_prt - 2 .0_prt * n_2);
440-
441- // sample random x value and calculate y
442- const amrex::ParticleReal x = (2 ._prt * amrex::Random (engine) - 1 .0_prt) * a;
443- const amrex::ParticleReal y2 = b*b - b*b/(a*a) * x*x;
444- const amrex::ParticleReal n_0 = std::sqrt (y2 + x*x - x*n_2 + 0 .25_prt*n_2*n_2);
445- const amrex::ParticleReal n_1 = 1 .0_prt - n_0 - n_2;
446-
447- // calculate the value of C
448- const amrex::ParticleReal C = std::sqrt (E_out / (
449- n_0*n_0 / (2 .0_prt * m1) + n_1*n_1 / (2 .0_prt * m_ioniz_product1) + n_2*n_2 / (2 .0_prt * m_ioniz_product2)
450- ));
451-
452- // Now that appropriate momenta are set for each outgoing species
453- // the directions for the velocity vectors must be chosen such
454- // that the net linear momentum in the current frame is 0.
455- // This is achieved by arranging the momentum vectors in
456- // a triangle and finding the required angles between the vectors.
457- const amrex::ParticleReal cos_alpha = (n_0*n_0 + n_1*n_1 - n_2*n_2) / (2 .0_prt * n_0 * n_1);
458- const amrex::ParticleReal sin_alpha = std::sqrt (1 .0_prt - cos_alpha*cos_alpha);
459- const amrex::ParticleReal cos_gamma = (n_0*n_0 + n_2*n_2 - n_1*n_1) / (2 .0_prt * n_0 * n_2);
460- const amrex::ParticleReal sin_gamma = std::sqrt (1 .0_prt - cos_gamma*cos_gamma);
461-
462- // choose random theta and phi values (orientation of the triangle)
463- const amrex::ParticleReal Theta = amrex::Random (engine) * 2 .0_prt * MathConst::pi;
464- const amrex::ParticleReal phi = amrex::Random (engine) * MathConst::pi;
465-
466- const amrex::ParticleReal cos_theta = std::cos (Theta);
467- const amrex::ParticleReal sin_theta = std::sin (Theta);
468- const amrex::ParticleReal cos_phi = std::cos (phi);
469- const amrex::ParticleReal sin_phi = std::sin (phi);
470-
471- // calculate the velocity components for each particle
472- ux1 = C * n_0 / m1 * cos_theta * cos_phi;
473- uy1 = C * n_0 / m1 * cos_theta * sin_phi;
474- uz1 = -C * n_0 / m1 * sin_theta;
475-
476- ux_p1 = C * n_1 / m_ioniz_product1 * (-cos_alpha * cos_theta * cos_phi - sin_alpha * sin_phi);
477- uy_p1 = C * n_1 / m_ioniz_product1 * (-cos_alpha * cos_theta * sin_phi + sin_alpha * cos_phi);
478- uz_p1 = C * n_1 / m_ioniz_product1 * (cos_alpha * sin_theta);
479-
480- ux_p2 = C * n_2 / m_ioniz_product2 * (-cos_gamma * cos_theta * cos_phi + sin_gamma * sin_phi);
481- uy_p2 = C * n_2 / m_ioniz_product2 * (-cos_gamma * cos_theta * sin_phi - sin_gamma * cos_phi);
482- uz_p2 = C * n_2 / m_ioniz_product2 * (cos_gamma * sin_theta);
483-
396+ // calculate kinetic energy of the collision
397+ const amrex::ParticleReal p_non_target_in = m1 * std::sqrt (ux1*ux1 + uy1*uy1 + uz1*uz1);
398+ const amrex::ParticleReal E_coll = 0 .5_prt * p_non_target_in * (1 .0_prt/m1 + 1 .0_prt/m2);
399+ // subtract the energy cost for ionization (converted from eV to J)
400+ const amrex::ParticleReal E_out = E_coll - ionization_energy * PhysConst::q_e;
401+
402+ // Momentum and energy division after the ionization event is done as follows:
403+ // we assume that, in the center of mass frame, the two products (the ion and the electron)
404+ // have equal velocity in and that their velocity vector is aligned with that of the target particle
405+
406+ // With these assumptions, conservation of momentum in the center of mass frame allows to express the momenta
407+ // of the products, as a function of the outcoming momentum of the non-target particle:
408+ // p_product1 = - p_non_target_out * m_ioniz_product1 / m2
409+ // p_product2 = - p_non_target_out * m_ioniz_product2 / m2
410+ // (with m2 = m_ioniz_product1 + m_ioniz_product2, by conservation of mass)
411+
412+ // Amplitude of the momentum of the non-target particle
413+ const amrex::ParticleReal p_non_target_out = std::sqrt ( 2 .0_prt * E_out / (1 .0_prt / m1 + 1 .0_prt / m2 ) );
414+
415+ // Reduce the velocity of the non-target particle accordingly
416+ const amrex::ParticleReal reduce_factor = p_non_target_out / p_non_target_in;
417+ ux1 *= reduce_factor;
418+ uy1 *= reduce_factor;
419+ uz1 *= reduce_factor;
420+ // Obtain the other velocity vectors by conservation of momentum
421+ const amrex::ParticleReal mass_ratio = m1 / m2;
422+ ux_p1 = mass_ratio * m_ioniz_product1 * ux1;
423+ uy_p1 = mass_ratio * m_ioniz_product1 * uy1;
424+ uz_p1 = mass_ratio * m_ioniz_product1 * uz1;
425+ ux_p2 = mass_ratio * m_ioniz_product2 * ux1;
426+ uy_p2 = mass_ratio * m_ioniz_product2 * uy1;
427+ uz_p2 = mass_ratio * m_ioniz_product2 * uz1;
484428 }
485429 else {
486430 amrex::Abort (" Unknown scattering process." );
0 commit comments