Skip to main content

sci_form/forcefield/
traits.rs

1/// Interfaz conductiva fundamental para cualquier operador matemático empírico molecular
2pub trait ForceFieldContribution: Send + Sync {
3    /// Computa algebraicamente el escalar de energía asumiendo posición local
4    /// e injerta los gradientes geométricos acumulativamente a lo largo del array
5    fn evaluate_energy_and_inject_gradient(&self, coords: &[f64], grad: &mut [f64]) -> f64;
6}
7
8pub struct MolecularForceField {
9    pub iter_terms: Vec<Box<dyn ForceFieldContribution>>,
10}
11
12impl Default for MolecularForceField {
13    fn default() -> Self {
14        Self::new()
15    }
16}
17
18impl MolecularForceField {
19    pub fn new() -> Self {
20        MolecularForceField {
21            iter_terms: Vec::new(),
22        }
23    }
24
25    pub fn insert_dynamic_term(&mut self, term: Box<dyn ForceFieldContribution>) {
26        self.iter_terms.push(term);
27    }
28
29    /// Método de evaluación crítica masiva invocado exhaustivamente iteración por iteración.
30    pub fn compute_system_energy_and_gradients(&self, coords: &[f64], grad: &mut [f64]) -> f64 {
31        grad.fill(0.0);
32
33        // Parallel evaluation using rayon
34        // We use a mutex or temporary local gradients to avoid data races when writing to 'grad'
35        // For simplicity and matching r.md, we use a local grad vector per term if needed,
36        // or just sequential for now if the number of terms is small.
37        // Actually r.md suggests:
38        /*
39        let mut local_grads = vec![0.0; grad.len()];
40        let total_energy = self.iter_terms.iter().map(|term| {
41            term.evaluate_energy_and_inject_gradient(coords, &mut local_grads)
42        }).sum();
43        */
44        // But the above has a shared local_grads which is still a problem if parallel.
45
46        // Let's implement it sequentially first as a baseline, or use rayon's fold/reduce if parallel.
47        let mut total_energy = 0.0;
48        for term in &self.iter_terms {
49            total_energy += term.evaluate_energy_and_inject_gradient(coords, grad);
50        }
51
52        total_energy
53    }
54}