Skip to main content

spin_sim/statistics/
equilibration.rs

1pub struct EquilCheckpoint {
2    pub sweep: usize,
3    pub energy_avg: Vec<f64>,
4    pub link_overlap_avg: Vec<f64>,
5}
6
7pub struct EquilDiagnosticAccum {
8    n_temps: usize,
9    checkpoints: Vec<usize>,
10    next_ckpt_idx: usize,
11    count: usize,
12    sum_energy: Vec<f64>,
13    sum_link_overlap: Vec<f64>,
14    snapshots: Vec<EquilCheckpoint>,
15}
16
17impl EquilDiagnosticAccum {
18    pub fn new(n_temps: usize, n_sweeps: usize) -> Self {
19        let mut checkpoints = Vec::new();
20        let mut p = 128usize;
21        while p < n_sweeps {
22            checkpoints.push(p);
23            p *= 2;
24        }
25        if checkpoints.last() != Some(&n_sweeps) {
26            checkpoints.push(n_sweeps);
27        }
28
29        Self {
30            n_temps,
31            checkpoints,
32            next_ckpt_idx: 0,
33            count: 0,
34            sum_energy: vec![0.0; n_temps],
35            sum_link_overlap: vec![0.0; n_temps],
36            snapshots: Vec::new(),
37        }
38    }
39
40    pub fn push(&mut self, energies: &[f32], link_overlaps: &[f32]) {
41        self.count += 1;
42        for t in 0..self.n_temps {
43            self.sum_energy[t] += energies[t] as f64;
44            self.sum_link_overlap[t] += link_overlaps[t] as f64;
45        }
46
47        if self.next_ckpt_idx < self.checkpoints.len()
48            && self.count == self.checkpoints[self.next_ckpt_idx]
49        {
50            let c = self.count as f64;
51            self.snapshots.push(EquilCheckpoint {
52                sweep: self.count,
53                energy_avg: self.sum_energy.iter().map(|&s| s / c).collect(),
54                link_overlap_avg: self.sum_link_overlap.iter().map(|&s| s / c).collect(),
55            });
56            self.next_ckpt_idx += 1;
57        }
58    }
59
60    pub fn finish(self) -> Vec<EquilCheckpoint> {
61        self.snapshots
62    }
63}