@@ -40,6 +40,10 @@ pub fn interaction_potential(r: f64, a: f64, Za: f64, Zb: f64, interaction_poten
40
40
InteractionPotential :: KRC_MORSE { D, alpha, r0, k, x0} => {
41
41
krc_morse ( r, a, Za , Zb , D , alpha, r0, k, x0)
42
42
}
43
+ InteractionPotential :: FOUR_EIGHT { alpha, beta} => {
44
+ four_eight ( r, alpha, beta)
45
+ }
46
+
43
47
}
44
48
}
45
49
@@ -48,6 +52,7 @@ pub fn energy_threshold_single_root(interaction_potential: InteractionPotential)
48
52
match interaction_potential{
49
53
InteractionPotential :: LENNARD_JONES_12_6 { ..} | InteractionPotential :: LENNARD_JONES_65_6 { ..} => f64:: INFINITY ,
50
54
InteractionPotential :: MORSE { ..} | InteractionPotential :: KRC_MORSE { ..} => f64:: INFINITY ,
55
+ InteractionPotential :: FOUR_EIGHT { ..} => f64:: INFINITY ,
51
56
InteractionPotential :: WW => f64:: INFINITY ,
52
57
InteractionPotential :: COULOMB { ..} => f64:: INFINITY ,
53
58
InteractionPotential :: MOLIERE | InteractionPotential :: KR_C | InteractionPotential :: LENZ_JENSEN | InteractionPotential :: ZBL | InteractionPotential :: TRIDYN => 0. ,
@@ -103,6 +108,9 @@ pub fn distance_of_closest_approach_function(r: f64, a: f64, Za: f64, Zb: f64, r
103
108
InteractionPotential :: KRC_MORSE { D, alpha, r0, k, x0} => {
104
109
doca_krc_morse ( r, impact_parameter, relative_energy, a, Za , Zb , D , alpha, r0, k, x0)
105
110
} ,
111
+ InteractionPotential :: FOUR_EIGHT { alpha, beta} => {
112
+ doca_four_eight ( r, impact_parameter, relative_energy, alpha, beta)
113
+ }
106
114
InteractionPotential :: COULOMB { ..} => panic ! ( "Coulombic potential cannot be used with rootfinder." )
107
115
}
108
116
}
@@ -131,6 +139,9 @@ pub fn distance_of_closest_approach_function_singularity_free(r: f64, a: f64, Za
131
139
InteractionPotential :: KRC_MORSE { D, alpha, r0, k, x0} => {
132
140
doca_krc_morse ( r, impact_parameter, relative_energy, a, Za , Zb , D , alpha, r0, k, x0)
133
141
} ,
142
+ InteractionPotential :: FOUR_EIGHT { alpha, beta} => {
143
+ doca_four_eight ( r, impact_parameter, relative_energy, alpha, beta)
144
+ }
134
145
InteractionPotential :: WW => {
135
146
doca_tungsten_tungsten_cubic_spline ( r, impact_parameter, relative_energy)
136
147
} ,
@@ -152,6 +163,10 @@ pub fn scaling_function(r: f64, a: f64, interaction_potential: InteractionPotent
152
163
let n = 6. ;
153
164
1. /( 1. + ( r/sigma) . powf ( n) )
154
165
} ,
166
+ InteractionPotential :: FOUR_EIGHT { alpha, beta} => {
167
+ let n = 8. ;
168
+ 1. /( 1. + r. powi ( 8 ) /beta)
169
+ }
155
170
InteractionPotential :: MORSE { D, alpha, r0} => {
156
171
1. /( 1. + ( r* alpha) . powi ( 2 ) )
157
172
}
@@ -256,35 +271,65 @@ pub fn screening_length(Za: f64, Zb: f64, interaction_potential: InteractionPote
256
271
InteractionPotential :: MORSE { D, alpha, r0} => alpha,
257
272
InteractionPotential :: COULOMB { Za : Z1 , Zb : Z2 } => 0.88534 * A0 /( Z1 . powf ( 0.23 ) + Z2 . powf ( 0.23 ) ) ,
258
273
InteractionPotential :: KRC_MORSE { ..} => 0.8853 * A0 * ( Za . sqrt ( ) + Zb . sqrt ( ) ) . powf ( -2. /3. ) ,
274
+ InteractionPotential :: FOUR_EIGHT { ..} =>0.8853 * A0 * ( Za . sqrt ( ) + Zb . sqrt ( ) ) . powf ( -2. /3. ) ,
259
275
}
260
276
}
261
277
262
278
/// Coefficients of inverse-polynomial interaction potentials.
279
+ /// Note: these go in order of decreasing orders of r, e.g., [r^n, r^n-1, r^n-2, ... r, 1].
263
280
pub fn polynomial_coefficients ( relative_energy : f64 , impact_parameter : f64 , interaction_potential : InteractionPotential ) -> Vec < f64 > {
264
281
match interaction_potential {
265
282
InteractionPotential :: LENNARD_JONES_12_6 { sigma, epsilon} => {
266
- vec ! [ 1. , 0. , -impact_parameter. powi( 2 ) , 0. , 0. , 0. , 4. * epsilon* sigma. powf( 6. ) /relative_energy, 0. , 0. , 0. , 0. , 0. , -4. * epsilon* sigma. powf( 12. ) /relative_energy]
283
+ let impact_parameteter_angstroms = impact_parameter/ANGSTROM ;
284
+ let epsilon_ev = epsilon/EV ;
285
+ let sigma_angstroms = sigma/ANGSTROM ;
286
+ let relative_energy_ev = relative_energy/EV ;
287
+ vec ! [ 1. , 0. , -impact_parameteter_angstroms. powi( 2 ) , 0. , 0. , 0. , 4. * epsilon_ev* sigma_angstroms. powf( 6. ) /relative_energy_ev, 0. , 0. , 0. , 0. , 0. , -4. * epsilon_ev* sigma_angstroms. powf( 12. ) /relative_energy_ev]
267
288
} ,
268
289
InteractionPotential :: LENNARD_JONES_65_6 { sigma, epsilon} => {
269
- vec ! [ 1. , 0. , 0. , 0. , -impact_parameter. powi( 2 ) , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 4. * epsilon* sigma. powf( 6. ) /relative_energy, -4. * epsilon* sigma. powf( 6.5 ) /relative_energy]
270
- } ,
290
+ let impact_parameteter_angstroms = impact_parameter/ANGSTROM ;
291
+ let epsilon_ev = epsilon/EV ;
292
+ let sigma_angstroms = sigma/ANGSTROM ;
293
+ let relative_energy_ev = relative_energy/EV ;
294
+ vec ! [ 1. , 0. , 0. , 0. , -impact_parameteter_angstroms. powi( 2 ) , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 4. * epsilon_ev* sigma_angstroms. powf( 6. ) /relative_energy, -4. * epsilon_ev* sigma_angstroms. powf( 6.5 ) /relative_energy_ev]
295
+ } ,
296
+ InteractionPotential :: FOUR_EIGHT { alpha, beta} => {
297
+ //Note: I've transformed to angstroms here to help the rootfinder with numerical issues.
298
+ //The units on alpha [m^4 J] and beta [m^8 J] make them unreasonably small to use numerically.
299
+ let alpha_angstroms4_joule = alpha/ANGSTROM . powi ( 4 ) ;
300
+ let beta_angstroms8_joule = beta/ANGSTROM . powi ( 8 ) ;
301
+ let impact_parameteter_angstroms = impact_parameter/ANGSTROM ;
302
+ vec ! [ 1. , 0. , -( impact_parameteter_angstroms) . powi( 2 ) , 0. , alpha_angstroms4_joule/relative_energy, 0. , 0. , 0. , -beta_angstroms8_joule/relative_energy, ]
303
+ }
271
304
_ => panic ! ( "Input error: non-polynomial interaction potential used with polynomial root-finder." )
272
305
}
273
306
}
274
307
275
- /// Inverse-polynomial interaction potentials transformation to remove singularities for the CPR root-finder.
308
+ /// Inverse-polynomial interaction potentials transformation to reduce numercial issues for the polynomial rootfinder.
309
+ /// This is for if, for example, you have non-integer powers and need to multiply by a factor to get to integer powers.
310
+ /// E.g., the 6.5-6 potential needs to be squared (x*x) giving you a 13th order polynomial in polynomial_coefficients().
276
311
pub fn inverse_transform ( x : f64 , interaction_potential : InteractionPotential ) -> f64 {
277
312
match interaction_potential {
278
313
InteractionPotential :: LENNARD_JONES_12_6 { ..} => {
279
- x
314
+ x* ANGSTROM
280
315
} ,
281
316
InteractionPotential :: LENNARD_JONES_65_6 { ..} => {
282
317
x* x
283
318
} ,
319
+ | InteractionPotential :: FOUR_EIGHT { ..} => {
320
+ x* ANGSTROM
321
+ }
284
322
_ => panic ! ( "Input error: non-polynomial interaction potential used with polynomial root-finder transformation." )
285
323
}
286
324
}
287
325
326
+ /// Four-Eight potential (Born repulsion)
327
+ pub fn four_eight ( r : f64 , alpha : f64 , beta : f64 ) -> f64 {
328
+ let a = alpha. powf ( 1. /4. ) ;
329
+ let b = beta. powf ( 1. /8. ) ;
330
+ -( a/r) . powi ( 4 ) + ( b/r) . powi ( 8 )
331
+ }
332
+
288
333
/// Lennard-Jones 12-6
289
334
pub fn lennard_jones ( r : f64 , sigma : f64 , epsilon : f64 ) -> f64 {
290
335
4. * epsilon* ( ( sigma/r) . powf ( 12. ) - ( sigma/r) . powf ( 6. ) )
@@ -305,6 +350,14 @@ pub fn krc_morse(r: f64, a: f64, Za: f64, Zb: f64, D: f64, alpha: f64, r0: f64,
305
350
sigmoid ( r, k, x0) * morse ( r, D , alpha, r0) + sigmoid ( r, -k, x0) * screened_coulomb ( r, a, Za , Zb , InteractionPotential :: KR_C )
306
351
}
307
352
353
+ /// Distance of closest approach function for four-eight potential (Born repulsion)
354
+ pub fn doca_four_eight ( r : f64 , impact_parameter : f64 , relative_energy : f64 , alpha : f64 , beta : f64 ) -> f64 {
355
+ let a = alpha. powf ( 1. /4. ) ;
356
+ let b = beta. powf ( 1. /8. ) ;
357
+ let b4 = beta. sqrt ( ) ;
358
+ ( r/b) . powf ( 8. ) - ( -( a* r/b/b) + 1. ) /relative_energy - ( impact_parameter* r. powf ( 3. ) /b4)
359
+ }
360
+
308
361
/// Distance of closest approach function for Morse potential.
309
362
pub fn doca_morse ( r : f64 , impact_parameter : f64 , relative_energy : f64 , D : f64 , alpha : f64 , r0 : f64 ) -> f64 {
310
363
( r* alpha) . powi ( 2 ) - ( r* alpha) . powi ( 2 ) * D /relative_energy* ( ( -2. * alpha* ( r - r0) ) . exp ( ) - 2. * ( -alpha* ( r - r0) ) . exp ( ) ) - ( impact_parameter* alpha) . powi ( 2 )
@@ -463,5 +516,6 @@ pub fn first_screening_radius(interaction_potential: InteractionPotential) -> f6
463
516
InteractionPotential :: MORSE { ..} | InteractionPotential :: KRC_MORSE { ..} => 1. ,
464
517
InteractionPotential :: WW => 1. ,
465
518
InteractionPotential :: COULOMB { ..} => 0.3 ,
519
+ InteractionPotential :: FOUR_EIGHT { ..} => 1. ,
466
520
}
467
521
}
0 commit comments