spin_sim/statistics/
results.rs1use super::equilibration::EquilCheckpoint;
2use super::overlap::OverlapStats;
3
4pub struct ClusterStats {
5 pub fk_csd: Vec<Vec<u64>>,
7 pub overlap_csd: Vec<Vec<Vec<u64>>>,
9 pub top_cluster_sizes: Vec<Vec<[f64; 4]>>,
11}
12
13pub struct Diagnostics {
14 pub mags2_tau: Vec<f64>,
17 pub overlap2_tau: Vec<f64>,
20 pub equil_checkpoints: Vec<EquilCheckpoint>,
23}
24
25pub struct SweepResult {
30 pub mags: Vec<f64>,
32 pub mags2: Vec<f64>,
34 pub mags4: Vec<f64>,
36 pub energies: Vec<f64>,
38 pub energies2: Vec<f64>,
40 pub overlap_stats: OverlapStats,
41 pub cluster_stats: ClusterStats,
42 pub diagnostics: Diagnostics,
43}
44
45impl SweepResult {
46 pub fn aggregate(results: &[Self]) -> Self {
48 let n = results.len() as f64;
49 let n_temps = results[0].mags.len();
50 let n_fk_csd = results[0].cluster_stats.fk_csd.len();
51
52 let fk_len = results[0]
53 .cluster_stats
54 .fk_csd
55 .first()
56 .map_or(0, |v| v.len());
57
58 let n_modes = results[0].cluster_stats.overlap_csd.len();
59 let ov_inner_len = results[0]
60 .cluster_stats
61 .overlap_csd
62 .first()
63 .and_then(|v| v.first())
64 .map_or(0, |v| v.len());
65 let ov_inner_temps = results[0]
66 .cluster_stats
67 .overlap_csd
68 .first()
69 .map_or(0, |v| v.len());
70
71 let n_top_modes = results[0].cluster_stats.top_cluster_sizes.len();
72 let n_top_temps = results[0]
73 .cluster_stats
74 .top_cluster_sizes
75 .first()
76 .map_or(0, |v| v.len());
77
78 let m2_tau_len = results[0].diagnostics.mags2_tau.len();
79 let q2_tau_len = results[0].diagnostics.overlap2_tau.len();
80 let n_ckpts = results[0].diagnostics.equil_checkpoints.len();
81
82 let overlap_stats =
83 OverlapStats::aggregate(&results.iter().map(|r| &r.overlap_stats).collect::<Vec<_>>());
84
85 let mut agg = SweepResult {
86 mags: vec![0.0; n_temps],
87 mags2: vec![0.0; n_temps],
88 mags4: vec![0.0; n_temps],
89 energies: vec![0.0; n_temps],
90 energies2: vec![0.0; n_temps],
91 overlap_stats,
92 cluster_stats: ClusterStats {
93 fk_csd: (0..n_fk_csd).map(|_| vec![0u64; fk_len]).collect(),
94 overlap_csd: (0..n_modes)
95 .map(|_| {
96 (0..ov_inner_temps)
97 .map(|_| vec![0u64; ov_inner_len])
98 .collect()
99 })
100 .collect(),
101 top_cluster_sizes: (0..n_top_modes)
102 .map(|_| vec![[0.0; 4]; n_top_temps])
103 .collect(),
104 },
105 diagnostics: Diagnostics {
106 mags2_tau: vec![0.0; m2_tau_len],
107 overlap2_tau: vec![0.0; q2_tau_len],
108 equil_checkpoints: (0..n_ckpts)
109 .map(|i| EquilCheckpoint {
110 sweep: results[0].diagnostics.equil_checkpoints[i].sweep,
111 energy_avg: vec![0.0; n_temps],
112 link_overlap_avg: vec![0.0; n_temps],
113 })
114 .collect(),
115 },
116 };
117
118 for r in results {
119 for (a, &v) in agg.mags.iter_mut().zip(r.mags.iter()) {
120 *a += v;
121 }
122 for (a, &v) in agg.mags2.iter_mut().zip(r.mags2.iter()) {
123 *a += v;
124 }
125 for (a, &v) in agg.mags4.iter_mut().zip(r.mags4.iter()) {
126 *a += v;
127 }
128 for (a, &v) in agg.energies.iter_mut().zip(r.energies.iter()) {
129 *a += v;
130 }
131 for (a, &v) in agg.energies2.iter_mut().zip(r.energies2.iter()) {
132 *a += v;
133 }
134 for (a, s) in agg
135 .cluster_stats
136 .fk_csd
137 .iter_mut()
138 .zip(r.cluster_stats.fk_csd.iter())
139 {
140 for (ah, &sh) in a.iter_mut().zip(s.iter()) {
141 *ah += sh;
142 }
143 }
144 for (am, sm) in agg
145 .cluster_stats
146 .overlap_csd
147 .iter_mut()
148 .zip(r.cluster_stats.overlap_csd.iter())
149 {
150 for (a, s) in am.iter_mut().zip(sm.iter()) {
151 for (ah, &sh) in a.iter_mut().zip(s.iter()) {
152 *ah += sh;
153 }
154 }
155 }
156 for (am, sm) in agg
157 .cluster_stats
158 .top_cluster_sizes
159 .iter_mut()
160 .zip(r.cluster_stats.top_cluster_sizes.iter())
161 {
162 for (a, &s) in am.iter_mut().zip(sm.iter()) {
163 for k in 0..4 {
164 a[k] += s[k];
165 }
166 }
167 }
168 for (a, &v) in agg
169 .diagnostics
170 .mags2_tau
171 .iter_mut()
172 .zip(r.diagnostics.mags2_tau.iter())
173 {
174 *a += v;
175 }
176 for (a, &v) in agg
177 .diagnostics
178 .overlap2_tau
179 .iter_mut()
180 .zip(r.diagnostics.overlap2_tau.iter())
181 {
182 *a += v;
183 }
184 for (ac, rc) in agg
185 .diagnostics
186 .equil_checkpoints
187 .iter_mut()
188 .zip(r.diagnostics.equil_checkpoints.iter())
189 {
190 for (a, &v) in ac.energy_avg.iter_mut().zip(rc.energy_avg.iter()) {
191 *a += v;
192 }
193 for (a, &v) in ac
194 .link_overlap_avg
195 .iter_mut()
196 .zip(rc.link_overlap_avg.iter())
197 {
198 *a += v;
199 }
200 }
201 }
202
203 for v in agg
204 .mags
205 .iter_mut()
206 .chain(agg.mags2.iter_mut())
207 .chain(agg.mags4.iter_mut())
208 .chain(agg.energies.iter_mut())
209 .chain(agg.energies2.iter_mut())
210 {
211 *v /= n;
212 }
213
214 for mode_tops in agg.cluster_stats.top_cluster_sizes.iter_mut() {
215 for arr in mode_tops.iter_mut() {
216 for v in arr.iter_mut() {
217 *v /= n;
218 }
219 }
220 }
221
222 for v in agg.diagnostics.mags2_tau.iter_mut() {
223 *v /= n;
224 }
225 for v in agg.diagnostics.overlap2_tau.iter_mut() {
226 *v /= n;
227 }
228 for ckpt in agg.diagnostics.equil_checkpoints.iter_mut() {
229 for v in ckpt.energy_avg.iter_mut() {
230 *v /= n;
231 }
232 for v in ckpt.link_overlap_avg.iter_mut() {
233 *v /= n;
234 }
235 }
236
237 agg
238 }
239}