mod energy;
mod field;
mod force;
mod potential;
mod schemes;
use crate::DebyeLength;
pub use schemes::{
ewald::*, ewald_truncated::EwaldTruncated, plain::Plain, poisson::*,
reactionfield::ReactionField,
};
pub use {
energy::MultipoleEnergy, field::MultipoleField, force::MultipoleForce,
potential::MultipolePotential,
};
#[cfg(feature = "uom")]
mod uom;
#[cfg(feature = "uom")]
pub use {uom::MultipoleEnergySI, uom::MultipoleFieldSI, uom::MultipolePotentialSI};
impl<T: ShortRangeFunction + crate::Cutoff> MultipolePotential for T {}
impl<T: ShortRangeFunction + crate::Cutoff> MultipoleField for T {}
impl<T: MultipoleField> MultipoleForce for T {}
impl<T: MultipolePotential + MultipoleField> MultipoleEnergy for T {}
pub trait ShortRangeFunction: DebyeLength {
fn url() -> &'static str
where
Self: Sized;
fn short_range_f0(&self, q: f64) -> f64;
fn short_range_f1(&self, q: f64) -> f64 {
const EPS: f64 = 1e-6;
if q <= EPS {
(self.short_range_f0(EPS) - self.short_range_f0(0.0)) / EPS
} else if q >= 1.0 - EPS {
(self.short_range_f0(1.0) - self.short_range_f0(1.0 - EPS)) / EPS
} else {
(self.short_range_f0(q + EPS) - self.short_range_f0(q - EPS)) / (2.0 * EPS)
}
}
fn short_range_f2(&self, q: f64) -> f64 {
const EPS: f64 = 1e-6;
(self.short_range_f1(q + EPS) - self.short_range_f1(q - EPS)) / (2.0 * EPS)
}
fn short_range_f3(&self, q: f64) -> f64 {
const EPS: f64 = 1e-6;
(self.short_range_f2(q + EPS) - self.short_range_f2(q - EPS)) / (2.0 * EPS)
}
fn self_energy_prefactors(&self) -> SelfEnergyPrefactors {
SelfEnergyPrefactors::default()
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct SelfEnergyPrefactors {
monopole: Option<f64>,
dipole: Option<f64>,
}
#[cfg(test)]
mod tests {
use approx::assert_relative_eq;
#[test]
fn test_electric_constant() {
let _trait_object =
&crate::pairwise::Plain::default() as &dyn crate::pairwise::ShortRangeFunction;
let bjerrum_length = 7.1; let rel_dielectric_const = 80.0;
assert_relative_eq!(
crate::TO_CHEMISTRY_UNIT / rel_dielectric_const / bjerrum_length,
2.4460467895137676 );
}
}