|
15 | 15 | use crate::structure::Structure; |
16 | 16 | use coulomb::pairwise::{MultipoleEnergy, MultipolePotential, Plain}; |
17 | 17 | use coulomb::permittivity::ConstantPermittivity; |
| 18 | +use faunus::topology::CustomProperty; |
18 | 19 | use faunus::{energy::NonbondedMatrix, topology::AtomKind}; |
19 | 20 | use interatomic::{ |
20 | 21 | twobody::{IonIon, IonIonPolar, IsotropicTwobodyEnergy}, |
@@ -42,15 +43,45 @@ impl PairMatrix { |
42 | 43 | .get_potentials_mut() |
43 | 44 | .indexed_iter_mut() |
44 | 45 | .for_each(|((i, j), pairpot)| { |
45 | | - let charge_product = atomkinds[i].charge() * atomkinds[j].charge(); |
| 46 | + // Fetch excess polarizability for the two atom kinds from the |
| 47 | + // custom "alpha" field, if it exists. Add to topology atoms like this: |
| 48 | + // `custom: {alpha: 50.0}` |
| 49 | + let get_alpha = |atom: &AtomKind| { |
| 50 | + atom.get_property("alpha").map_or(0.0, |v| { |
| 51 | + f64::try_from(v).expect("Failed to convert alpha to f64") |
| 52 | + }) |
| 53 | + }; |
| 54 | + let alpha1 = get_alpha(&atomkinds[i]); |
| 55 | + let alpha2 = get_alpha(&atomkinds[j]); |
| 56 | + let charge1 = atomkinds[i].charge(); |
| 57 | + let charge2 = atomkinds[j].charge(); |
| 58 | + let charge_product = charge1 * charge2; |
| 59 | + let use_polarization = |
| 60 | + (alpha1 * charge2).abs() > 1e-6 || (alpha2 * charge1).abs() > 1e-6; |
| 61 | + |
| 62 | + if use_polarization { |
| 63 | + log::debug!( |
| 64 | + "Adding ion-induced dipole term for atom pair ({}, {}). Alphas: {}, {}", |
| 65 | + i, |
| 66 | + j, |
| 67 | + alpha1, |
| 68 | + alpha2 |
| 69 | + ); |
| 70 | + } |
46 | 71 | let coulomb = |
47 | 72 | IonIon::<T>::new(charge_product, permittivity, coulomb_method.clone()); |
48 | | - let coulomb = Box::new(IonIonPolar::<T>::new( |
49 | | - coulomb, |
50 | | - 50.0, |
51 | | - (atomkinds[i].charge(), atomkinds[j].charge()), |
| 73 | + let coulomb_polar = Box::new(IonIonPolar::<T>::new( |
| 74 | + coulomb.clone(), |
| 75 | + (charge1, charge2), |
| 76 | + (alpha1, alpha2), |
52 | 77 | )) as Box<dyn IsotropicTwobodyEnergy>; |
53 | | - let combined = coulomb + Box::new(pairpot.clone()); |
| 78 | + let combined = match use_polarization { |
| 79 | + true => coulomb_polar + Box::new(pairpot.clone()), |
| 80 | + false => { |
| 81 | + Box::new(coulomb) as Box<dyn IsotropicTwobodyEnergy> |
| 82 | + + Box::new(pairpot.clone()) |
| 83 | + } |
| 84 | + }; |
54 | 85 | *pairpot = std::sync::Arc::new(combined); |
55 | 86 | }); |
56 | 87 | Self { nonbonded } |
|
0 commit comments