@@ -359,11 +359,10 @@ mod tests {
359359 const R0 : f64 = 3.5 ;
360360 const R0_SQ : f64 = R0 * R0 ;
361361
362- // Buckingham parameters: A, B, C, r_fusion_sq
362+ // Buckingham parameters: A, B, C
363363 const BUCK_A : f64 = 1000.0 ;
364364 const BUCK_B : f64 = 3.0 ;
365365 const BUCK_C : f64 = 50.0 ;
366- const BUCK_FUSION_SQ : f64 = 0.5 ;
367366
368367 // ========================================================================
369368 // Lennard-Jones Tests
@@ -513,8 +512,23 @@ mod tests {
513512 mod buckingham {
514513 use super :: * ;
515514
516- fn params ( ) -> ( f64 , f64 , f64 , f64 ) {
517- ( BUCK_A , BUCK_B , BUCK_C , BUCK_FUSION_SQ )
515+ /// Computes the local maximum of the Buckingham potential via Newton's method.
516+ fn reflection_params ( a : f64 , b : f64 , c : f64 ) -> ( f64 , f64 ) {
517+ let mut r = 1.0_f64 ;
518+ for _ in 0 ..100 {
519+ let exp_term = ( -b * r) . exp ( ) ;
520+ let r7 = r. powi ( 7 ) ;
521+ let g = a * b * exp_term * r7 - 6.0 * c;
522+ let gp = a * b * exp_term * r. powi ( 6 ) * ( 7.0 - b * r) ;
523+ r -= g / gp;
524+ }
525+ let e_max = a * ( -b * r) . exp ( ) - c / r. powi ( 6 ) ;
526+ ( r * r, 2.0 * e_max)
527+ }
528+
529+ fn params ( ) -> ( f64 , f64 , f64 , f64 , f64 ) {
530+ let ( r_max_sq, two_e_max) = reflection_params ( BUCK_A , BUCK_B , BUCK_C ) ;
531+ ( BUCK_A , BUCK_B , BUCK_C , r_max_sq, two_e_max)
518532 }
519533
520534 // --------------------------------------------------------------------
@@ -534,15 +548,30 @@ mod tests {
534548 assert_relative_eq ! ( result. diff, diff_only, epsilon = 1e-12 ) ;
535549 }
536550
551+ #[ test]
552+ fn sanity_compute_equals_separate_reflected ( ) {
553+ let p = params ( ) ;
554+ let r_sq = 0.25_f64 ;
555+
556+ let result = Buckingham :: compute ( r_sq, p) ;
557+ let energy_only = Buckingham :: energy ( r_sq, p) ;
558+ let diff_only = Buckingham :: diff ( r_sq, p) ;
559+
560+ assert_relative_eq ! ( result. energy, energy_only, epsilon = 1e-12 ) ;
561+ assert_relative_eq ! ( result. diff, diff_only, epsilon = 1e-12 ) ;
562+ }
563+
537564 #[ test]
538565 fn sanity_f32_f64_consistency ( ) {
539566 let r_sq = 4.0 ;
540567 let p64 = params ( ) ;
568+ let ( r_max_sq_32, two_e_max_32) = reflection_params ( BUCK_A , BUCK_B , BUCK_C ) ;
541569 let p32 = (
542570 BUCK_A as f32 ,
543571 BUCK_B as f32 ,
544572 BUCK_C as f32 ,
545- BUCK_FUSION_SQ as f32 ,
573+ r_max_sq_32 as f32 ,
574+ two_e_max_32 as f32 ,
546575 ) ;
547576
548577 let e64 = Buckingham :: energy ( r_sq, p64) ;
@@ -556,13 +585,14 @@ mod tests {
556585 // --------------------------------------------------------------------
557586
558587 #[ test]
559- fn stability_fusion_region ( ) {
588+ fn stability_reflected_region ( ) {
560589 let r_sq = 0.1_f64 ;
561590 let result = Buckingham :: compute ( r_sq, params ( ) ) ;
562591
563592 assert ! ( result. energy. is_finite( ) ) ;
564593 assert ! ( result. diff. is_finite( ) ) ;
565- assert ! ( result. energy > 1e5 ) ;
594+ assert ! ( result. energy > 0.0 ) ;
595+ assert ! ( result. diff > 0.0 ) ;
566596 }
567597
568598 #[ test]
@@ -574,6 +604,16 @@ mod tests {
574604 assert ! ( result. diff. is_finite( ) ) ;
575605 }
576606
607+ #[ test]
608+ fn stability_near_zero ( ) {
609+ let r_sq = 1e-20_f64 ;
610+ let p = params ( ) ;
611+ let e = Buckingham :: energy ( r_sq, p) ;
612+
613+ assert ! ( e. is_finite( ) ) ;
614+ assert ! ( e > 0.0 ) ;
615+ }
616+
577617 // --------------------------------------------------------------------
578618 // 3. Finite Difference Verification
579619 // --------------------------------------------------------------------
@@ -595,7 +635,12 @@ mod tests {
595635 }
596636
597637 #[ test]
598- fn finite_diff_short_range ( ) {
638+ fn finite_diff_reflected_region ( ) {
639+ finite_diff_check ( 0.8 ) ;
640+ }
641+
642+ #[ test]
643+ fn finite_diff_normal_short_range ( ) {
599644 finite_diff_check ( 1.5 ) ;
600645 }
601646
@@ -610,15 +655,75 @@ mod tests {
610655 }
611656
612657 // --------------------------------------------------------------------
613- // 4. Buckingham-Specific
658+ // 4. Buckingham-Specific: Reflection Properties
614659 // --------------------------------------------------------------------
615660
616661 #[ test]
617- fn specific_exponential_dominates_short_range ( ) {
618- let e1 = Buckingham :: energy ( 0.81 , params ( ) ) ;
619- let e2 = Buckingham :: energy ( 1.0 , params ( ) ) ;
620- assert ! ( e1. is_finite( ) ) ;
621- assert ! ( e2. is_finite( ) ) ;
662+ fn specific_reflection_diverges ( ) {
663+ let p = params ( ) ;
664+ let e_close = Buckingham :: energy ( 0.01 , p) ;
665+ let e_far = Buckingham :: energy ( 0.25 , p) ;
666+ assert ! ( e_close > e_far) ;
667+ }
668+
669+ #[ test]
670+ fn specific_diff_at_maximum_is_zero ( ) {
671+ let p = params ( ) ;
672+ let r_max_sq = p. 3 ;
673+ let d = Buckingham :: diff ( r_max_sq, p) ;
674+ assert_relative_eq ! ( d, 0.0 , epsilon = 1e-6 ) ;
675+ }
676+
677+ #[ test]
678+ fn specific_c1_continuity_at_maximum ( ) {
679+ let p = params ( ) ;
680+ let r_max = p. 3 . sqrt ( ) ;
681+ let eps = 1e-8 ;
682+
683+ let r_inside = r_max - eps;
684+ let r_outside = r_max + eps;
685+
686+ let d_inside = Buckingham :: diff ( r_inside * r_inside, p) ;
687+ let d_outside = Buckingham :: diff ( r_outside * r_outside, p) ;
688+
689+ let de_dr_inside = -d_inside * r_inside;
690+ let de_dr_outside = -d_outside * r_outside;
691+
692+ assert_relative_eq ! ( de_dr_inside, de_dr_outside, epsilon = 1e-3 ) ;
693+ }
694+
695+ #[ test]
696+ fn specific_energy_continuity_at_maximum ( ) {
697+ let p = params ( ) ;
698+ let r_max = p. 3 . sqrt ( ) ;
699+ let eps = 1e-8 ;
700+
701+ let e_inside = Buckingham :: energy ( ( r_max - eps) . powi ( 2 ) , p) ;
702+ let e_outside = Buckingham :: energy ( ( r_max + eps) . powi ( 2 ) , p) ;
703+
704+ assert_relative_eq ! ( e_inside, e_outside, epsilon = 1e-4 ) ;
705+ }
706+
707+ #[ test]
708+ fn specific_finite_diff_across_boundary ( ) {
709+ let p = params ( ) ;
710+ let r_max = p. 3 . sqrt ( ) ;
711+
712+ let h = 1e-6 ;
713+
714+ let r_out = r_max + 0.01 ;
715+ let e_p = Buckingham :: energy ( ( r_out + h) . powi ( 2 ) , p) ;
716+ let e_m = Buckingham :: energy ( ( r_out - h) . powi ( 2 ) , p) ;
717+ let de_dr_num_out = ( e_p - e_m) / ( 2.0 * h) ;
718+ let de_dr_ana_out = -Buckingham :: diff ( r_out * r_out, p) * r_out;
719+ assert_relative_eq ! ( de_dr_num_out, de_dr_ana_out, epsilon = TOL_DIFF ) ;
720+
721+ let r_in = r_max - 0.01 ;
722+ let e_p = Buckingham :: energy ( ( r_in + h) . powi ( 2 ) , p) ;
723+ let e_m = Buckingham :: energy ( ( r_in - h) . powi ( 2 ) , p) ;
724+ let de_dr_num_in = ( e_p - e_m) / ( 2.0 * h) ;
725+ let de_dr_ana_in = -Buckingham :: diff ( r_in * r_in, p) * r_in;
726+ assert_relative_eq ! ( de_dr_num_in, de_dr_ana_in, epsilon = TOL_DIFF ) ;
622727 }
623728 }
624729
0 commit comments