use std::{collections::HashSet, fmt};
#[cfg(feature = "encode")]
use bincode::{Decode, Encode};
use bio_files::{
gromacs::mdp::{ConstraintAlgorithm, Constraints},
md_params::{
AngleBendingParams, BondStretchingParams, ForceFieldParams, ForceFieldParamsIndexed,
LjParams, MassParams,
},
};
use itertools::Itertools;
use na_seq::Element::Hydrogen;
use crate::{AtomDynamics, MdState, ParamError};
pub fn merge_params(baseline: &ForceFieldParams, add_this: &ForceFieldParams) -> ForceFieldParams {
let mut merged = baseline.clone();
merged.mass.extend(add_this.mass.clone());
merged.lennard_jones.extend(add_this.lennard_jones.clone());
merged.bond.extend(add_this.bond.clone());
merged.angle.extend(add_this.angle.clone());
merged.dihedral.extend(add_this.dihedral.clone());
merged.improper.extend(add_this.improper.clone());
merged
}
#[cfg_attr(feature = "encode", derive(Encode, Decode))]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum HydrogenConstraint {
Linear {
order: u8,
iter: u8,
},
Shake {
shake_tolerance: f32,
},
Flexible,
}
impl Default for HydrogenConstraint {
fn default() -> Self {
HydrogenConstraint::Linear { order: 4, iter: 1 }
}
}
impl HydrogenConstraint {
pub fn to_gromacs(&self) -> Constraints {
match self {
Self::Linear { order, iter } => Constraints::HBonds(ConstraintAlgorithm::Lincs {
order: *order,
iter: *iter,
}),
Self::Shake {
shake_tolerance: tolerance,
} => Constraints::HBonds(ConstraintAlgorithm::Shake { tol: *tolerance }),
Self::Flexible => Constraints::None,
}
}
}
impl fmt::Display for HydrogenConstraint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
HydrogenConstraint::Linear { .. } => {
write!(f, "Constrained (LINCS)")
}
HydrogenConstraint::Shake { shake_tolerance: _ } => {
write!(f, "Constrained (SHAKE)")
}
HydrogenConstraint::Flexible => write!(f, "Flexible"),
}
}
}
impl MdState {
pub(crate) fn setup_nonbonded_exclusion_scale_flags(&mut self) {
let push = |set: &mut HashSet<(usize, usize)>, i: usize, j: usize| {
if i < j {
set.insert((i, j));
} else {
set.insert((j, i));
}
};
for indices in &self.force_field_params.bonds_topology {
push(&mut self.pairs_excluded_12_13, indices.0, indices.1);
}
for indices in self.force_field_params.angle.keys() {
push(&mut self.pairs_excluded_12_13, indices.0, indices.2);
}
for indices in self.force_field_params.dihedral.keys() {
push(&mut self.pairs_14_scaled, indices.0, indices.3);
}
for p in &self.pairs_14_scaled {
self.pairs_excluded_12_13.remove(p);
}
}
}