use molrs::types::F;
use super::cell::VoronoiCells;
use crate::compute::error::ComputeError;
use crate::core::system::topology::Topology;
#[derive(Debug, Clone)]
pub struct DomainResult {
pub sizes: Vec<usize>,
pub count: usize,
pub largest_fraction: F,
pub domain_of: Vec<usize>,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct DomainAnalysis;
impl DomainAnalysis {
pub fn analyze(
&self,
cells: &VoronoiCells,
labels: &[i64],
) -> Result<DomainResult, ComputeError> {
let n = cells.len();
if labels.len() != n {
return Err(ComputeError::DimensionMismatch {
expected: n,
got: labels.len(),
what: "domain labels length",
});
}
let mut topo = Topology::with_atoms(n);
for i in 0..n {
for j in cells.neighbors(i) {
let j = j as usize;
if j < n && j > i && labels[i] == labels[j] {
topo.add_bond(i, j);
}
}
}
let component_of = topo.connected_components();
let mut domain_of = vec![0usize; n];
let mut size_of = vec![0usize; n];
for (i, d) in domain_of.iter_mut().enumerate() {
let c = component_of[i] as usize;
*d = c;
size_of[c] += 1;
}
let mut sizes: Vec<usize> = size_of.into_iter().filter(|&c| c > 0).collect();
sizes.sort_unstable_by(|a, b| b.cmp(a));
let count = sizes.len();
let largest_fraction = if n == 0 {
0.0
} else {
sizes.first().copied().unwrap_or(0) as F / n as F
};
Ok(DomainResult {
sizes,
count,
largest_fraction,
domain_of,
})
}
}