@@ -602,10 +602,12 @@ pub fn polynomial_rootfinder(Za: f64, Zb: f64, Ma: f64, Mb: f64, E0: f64, impact
602602}
603603
604604#[ cfg( feature = "cpr_rootfinder" ) ]
605- fn transform ( x : f64 ) -> f64 {
606- L /( x* PI /2. ) . tan ( ) . powi ( 2 )
605+ fn transform ( x : f64 , l : f64 ) -> f64 {
606+ l /( x* PI /2. ) . tan ( ) . powi ( 2 )
607607}
608608
609+
610+
609611#[ cfg( feature = "cpr_rootfinder" ) ]
610612/// Computes the distance of closest approach of two particles with atomic numbers `Za`, `Zb` and masses `Ma`, `Mb` for an arbitrary interaction potential (e.g., Morse) for a given impact parameter and incident energy `E0` using the Chebyshev-Proxy Root-Finder method.
611613///
@@ -633,10 +635,13 @@ pub fn cpr_rootfinder(Za: f64, Zb: f64, Ma: f64, Mb: f64, E0: f64, impact_parame
633635 //Lindhard screening length and reduced energy
634636 let a = interactions:: screening_length ( Za , Zb , interaction_potential) ;
635637 let relative_energy = E0 * Mb /( Ma + Mb ) ;
638+ // Guess at scaling for rootfinder - enforce p -> 0.5 in transformed coords
639+ // If smaller than defined constant L, default to L (which was found empirically)
640+ let l: f64 = ( impact_parameter* ( PI /4. ) . tan ( ) . powi ( 2 ) /a) . max ( L ) ;
636641
637- let g = |r : f64 | -> f64 {
638- interactions:: distance_of_closest_approach_function_singularity_free ( transform ( r) * a, a, Za , Zb , relative_energy, impact_parameter, interaction_potential) *
639- interactions:: scaling_function ( transform ( r) * a, a, interaction_potential)
642+ let g = |r : f64 | -> Result < f64 , std :: convert :: Infallible > {
643+ Ok ( interactions:: distance_of_closest_approach_function_singularity_free ( transform ( r, l ) * a, a, Za , Zb , relative_energy, impact_parameter, interaction_potential) *
644+ interactions:: scaling_function ( transform ( r, l ) * a, a, interaction_potential) )
640645 } ;
641646
642647 let lower_bound = CPR_ROOTFINDER_LOWER_BOUND ;
@@ -658,12 +663,12 @@ pub fn cpr_rootfinder(Za: f64, Zb: f64, Ma: f64, Mb: f64, E0: f64, impact_parame
658663 // Since above the arg to doca is transform(r)*a, this is already scaled as output
659664 //let max_root = roots.iter().map(|&x| transform(x)).fold(f64::NAN, f64::max);
660665 let max_root = roots. iter ( )
661- . map ( |& x| transform ( x) )
666+ . map ( |& x| transform ( x, l ) )
662667 . max_by ( f64:: total_cmp)
663- . ok_or_else ( || { anyhow ! ( "Numerical error: failed to find maximum root. F(a): {}, F(b): {}" , g( lower_bound) , g( upper_bound) ) } ) ?;
668+ . ok_or_else ( || { anyhow ! ( "Numerical error: failed to find maximum root. F(a): {}, F(b): {}" , g( lower_bound) . unwrap ( ) , g( upper_bound) . unwrap ( ) ) } ) ?;
664669
665670 if roots. is_empty ( ) || max_root. is_nan ( ) {
666- return Err ( anyhow ! ( "Numerical error: CPR rootfinder failed to find root. x0: {}, F(a): {}, F(b): {};" , max_root, g( lower_bound) , g( upper_bound) ) ) ;
671+ return Err ( anyhow ! ( "Numerical error: CPR rootfinder failed to find root. x0: {}, F(a): {}, F(b): {};" , max_root, g( lower_bound) . unwrap ( ) , g( upper_bound) . unwrap ( ) ) ) ;
667672 } else {
668673 return Ok ( max_root) ;
669674 }
0 commit comments