chematic-ff 0.5.0

DREIDING force field atom typing and parameters for chematic — pure-Rust cheminformatics
Documentation
//! MMFF94 van der Waals parameters (Halgren 1996 Table VII, Slater-Kirkwood).

use super::VdwEnergyParams;

/// 95 vdW entries (Halgren 1996 Table VII). One entry per MMFF94 numeric atom type.
pub static MMFF94_VDW_ENERGY: &[(u8, f64, f64, f64, f64, u8)] = &[
    (1, 1.0500, 2.4900, 3.8900, 1.2820, 0),
    (2, 1.3500, 2.4900, 3.8900, 1.2820, 0),
    (3, 1.1000, 2.4900, 3.8900, 1.2820, 0),
    (4, 1.3000, 2.4900, 3.8900, 1.2820, 0),
    (5, 0.2500, 0.8000, 4.2000, 1.2090, 0),
    (6, 0.7000, 3.1500, 3.8900, 1.2820, 2),
    (7, 0.6500, 3.1500, 3.8900, 1.2820, 2),
    (8, 1.1500, 2.8200, 3.8900, 1.2820, 2),
    (9, 0.9000, 2.8200, 3.8900, 1.2820, 2),
    (10, 1.0000, 2.8200, 3.8900, 1.2820, 2),
    (11, 0.3500, 3.4800, 3.8900, 1.2820, 2),
    (12, 2.3000, 5.1000, 3.3200, 1.3450, 2),
    (13, 3.4000, 6.0000, 3.1900, 1.3590, 2),
    (14, 5.5000, 6.9500, 3.0800, 1.4040, 2),
    (15, 3.0000, 4.8000, 3.3200, 1.3450, 2),
    (16, 3.9000, 4.8000, 3.3200, 1.3450, 2),
    (17, 2.7000, 4.8000, 3.3200, 1.3450, 0),
    (18, 2.1000, 4.8000, 3.3200, 1.3450, 0),
    (19, 4.5000, 4.2000, 3.3200, 1.3450, 0),
    (20, 1.0500, 2.4900, 3.8900, 1.2820, 0),
    (21, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (22, 1.1000, 2.4900, 3.8900, 1.2820, 0),
    (23, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (24, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (25, 1.6000, 4.5000, 3.3200, 1.3450, 0),
    (26, 3.6000, 4.5000, 3.3200, 1.3450, 2),
    (27, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (28, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (29, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (30, 1.3500, 2.4900, 3.8900, 1.2820, 0),
    (31, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (32, 0.7500, 3.1500, 3.8900, 1.2820, 2),
    (33, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (34, 1.0000, 2.8200, 3.8900, 1.2820, 0),
    (35, 1.5000, 3.1500, 3.8900, 1.2820, 2),
    (36, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (37, 1.3500, 2.4900, 3.8900, 1.2820, 0),
    (38, 0.8500, 2.8200, 3.8900, 1.2820, 2),
    (39, 1.1000, 2.8200, 3.8900, 1.2820, 0),
    (40, 1.0000, 2.8200, 3.8900, 1.2820, 2),
    (41, 1.1000, 2.4900, 3.8900, 1.2820, 0),
    (42, 1.0000, 2.8200, 3.8900, 1.2820, 2),
    (43, 1.0000, 2.8200, 3.8900, 1.2820, 2),
    (44, 3.0000, 4.8000, 3.3200, 1.3450, 2),
    (45, 1.1500, 2.8200, 3.8900, 1.2820, 0),
    (46, 1.3000, 2.8200, 3.8900, 1.2820, 0),
    (47, 1.0000, 2.8200, 3.8900, 1.2820, 2),
    (48, 1.2000, 2.8200, 3.8900, 1.2820, 2),
    (49, 1.0000, 3.1500, 3.8900, 1.2820, 0),
    (50, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (51, 0.4000, 3.1500, 3.8900, 1.2820, 0),
    (52, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (53, 1.0000, 2.8200, 3.8900, 1.2820, 0),
    (54, 1.3000, 2.8200, 3.8900, 1.2820, 0),
    (55, 0.8000, 2.8200, 3.8900, 1.2820, 0),
    (56, 0.8000, 2.8200, 3.8900, 1.2820, 0),
    (57, 1.0000, 2.4900, 3.8900, 1.2820, 0),
    (58, 0.8000, 2.8200, 3.8900, 1.2820, 0),
    (59, 0.6500, 3.1500, 3.8900, 1.2820, 2),
    (60, 1.8000, 2.4900, 3.8900, 1.2820, 2),
    (61, 0.8000, 2.8200, 3.8900, 1.2820, 2),
    (62, 1.3000, 2.8200, 3.8900, 1.2820, 2),
    (63, 1.3500, 2.4900, 3.8900, 1.2820, 0),
    (64, 1.3500, 2.4900, 3.8900, 1.2820, 0),
    (65, 1.0000, 2.8200, 3.8900, 1.2820, 2),
    (66, 0.7500, 2.8200, 3.8900, 1.2820, 2),
    (67, 0.9500, 2.8200, 3.8900, 1.2820, 2),
    (68, 0.9000, 2.8200, 3.8900, 1.2820, 2),
    (69, 0.9500, 2.8200, 3.8900, 1.2820, 2),
    (70, 0.8700, 3.1500, 3.8900, 1.2820, 2),
    (71, 0.1500, 0.8000, 4.2000, 1.2090, 1),
    (72, 4.0000, 4.8000, 3.3200, 1.3450, 2),
    (73, 3.0000, 4.8000, 3.3200, 1.3450, 0),
    (74, 3.0000, 4.8000, 3.3200, 1.3450, 0),
    (75, 4.0000, 4.5000, 3.3200, 1.3450, 2),
    (76, 1.2000, 2.8200, 3.8900, 1.2820, 2),
    (77, 1.5000, 5.1000, 3.3200, 1.3450, 2),
    (78, 1.3500, 2.4900, 3.8900, 1.2820, 0),
    (79, 1.0000, 2.8200, 3.8900, 1.2820, 2),
    (80, 1.0000, 2.4900, 3.8900, 1.2820, 0),
    (81, 0.8000, 2.8200, 3.8900, 1.2820, 0),
    (82, 0.9500, 2.8200, 3.8900, 1.2820, 2),
    (87, 0.4500, 6.0000, 4.0000, 1.4000, 0),
    (88, 0.5500, 6.0000, 4.0000, 1.4000, 0),
    (89, 1.4000, 3.4800, 3.8900, 1.2820, 2),
    (90, 4.5000, 5.1000, 3.3200, 1.3450, 2),
    (91, 6.0000, 6.0000, 3.1900, 1.3590, 2),
    (92, 0.1500, 2.0000, 4.0000, 1.3000, 0),
    (93, 0.4000, 3.5000, 4.0000, 1.3000, 0),
    (94, 1.0000, 5.0000, 4.0000, 1.3000, 0),
    (95, 0.4300, 6.0000, 4.0000, 1.4000, 0),
    (96, 0.9000, 5.0000, 4.0000, 1.4000, 0),
    (97, 0.3500, 6.0000, 4.0000, 1.4000, 0),
    (98, 0.4000, 6.0000, 4.0000, 1.4000, 0),
    (99, 0.3500, 3.5000, 4.0000, 1.3000, 0),
];

/// Look up vdW parameters by MMFF94 numeric atom type.
pub fn mmff94_vdw_energy(type_i: u8) -> Option<VdwEnergyParams> {
    MMFF94_VDW_ENERGY
        .binary_search_by_key(&type_i, |&(ti, _, _, _, _, _)| ti)
        .ok()
        .map(|idx| {
            let (_, alpha_i, n_i, a_i, g_i, da) = MMFF94_VDW_ENERGY[idx];
            VdwEnergyParams {
                alpha_i,
                n_i,
                a_i,
                g_i,
                da,
            }
        })
}

/// Compute combined vdW well parameters using MMFF94 Slater-Kirkwood combining rules
/// (Halgren 1996, MMFF.I eq. 2).
///
/// Returns `(r_star_ij, eps_ij)` in Å and kcal/mol respectively.
pub fn mmff94_vdw_combined(type_i: u8, type_j: u8) -> Option<(f64, f64)> {
    let pi = mmff94_vdw_energy(type_i)?;
    let pj = mmff94_vdw_energy(type_j)?;

    // r*_ii = A_i × alpha_i^(1/4)
    let r_ii = pi.a_i * pi.alpha_i.powf(0.25);
    let r_jj = pj.a_i * pj.alpha_i.powf(0.25);

    // Arithmetic mean + London asymmetry correction (MMFF94 eq. 2)
    let r_ij_unscaled = 0.5 * (r_ii + r_jj);
    let delta = (r_ii - r_jj) / (r_ii + r_jj);
    let r_star_ij = r_ij_unscaled * (1.0 + 0.2 * (1.0 - (-12.0 * delta * delta).exp()));

    // Epsilon combining rule: Slater-Kirkwood (eq. 3)
    let eps_ij = 181.16 * pi.g_i * pj.g_i * pi.alpha_i * pj.alpha_i
        / ((pi.alpha_i / pi.n_i).sqrt() + (pj.alpha_i / pj.n_i).sqrt())
        / r_star_ij.powi(6);

    // Donor-acceptor scaling
    let (r_star_ij, eps_ij) = if pi.da == 1 && pj.da == 2 || pi.da == 2 && pj.da == 1 {
        (0.8 * r_star_ij, 0.5 * eps_ij)
    } else {
        (r_star_ij, eps_ij)
    };

    Some((r_star_ij, eps_ij))
}