pub const COINCIDENT_TOL: f64 = 1e-6;
pub const AMPLITUDE: f64 = 0.1;
#[must_use]
pub fn van_der_corput(mut n: usize, base: usize) -> f64 {
debug_assert!(base >= 2, "基数至少是 2");
let mut q = 0.0;
let mut bk = 1.0 / base as f64;
while n > 0 {
q += (n % base) as f64 * bk;
n /= base;
bk /= base as f64;
}
q
}
pub fn break_coincidence(coords: &mut [[f64; 3]]) -> usize {
let n = coords.len();
let mut needs = vec![false; n];
for i in 0..n {
for j in (i + 1)..n {
let d2 = (0..3)
.map(|t| (coords[i][t] - coords[j][t]).powi(2))
.sum::<f64>();
if d2 <= COINCIDENT_TOL * COINCIDENT_TOL {
needs[i] = true;
needs[j] = true;
}
}
}
let mut moved = 0;
for (i, flag) in needs.iter().enumerate() {
if !flag {
continue;
}
let off = [
van_der_corput(i + 1, 2) - 0.5,
van_der_corput(i + 1, 3) - 0.5,
van_der_corput(i + 1, 5) - 0.5,
];
for t in 0..3 {
coords[i][t] += AMPLITUDE * off[t];
}
moved += 1;
}
moved
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn van_der_corput_的前几项() {
let want = [0.5, 0.25, 0.75, 0.125, 0.625, 0.375, 0.875];
for (k, w) in want.iter().enumerate() {
let got = van_der_corput(k + 1, 2);
assert!((got - w).abs() < 1e-15, "第 {} 项:{got} vs {w}", k + 1);
}
assert!((van_der_corput(1, 3) - 1.0 / 3.0).abs() < 1e-15);
assert!((van_der_corput(2, 3) - 2.0 / 3.0).abs() < 1e-15);
assert!((van_der_corput(3, 3) - 1.0 / 9.0).abs() < 1e-15);
assert_eq!(van_der_corput(0, 2), 0.0);
}
#[test]
fn 相邻下标的位移互不相同() {
let mut seen: Vec<[f64; 3]> = Vec::new();
for i in 1..=64 {
let o = [
van_der_corput(i, 2),
van_der_corput(i, 3),
van_der_corput(i, 5),
];
for prev in &seen {
let same = (0..3).all(|t| (prev[t] - o[t]).abs() < 1e-12);
assert!(!same, "下标 {i} 与前面某个撞了:{o:?}");
}
seen.push(o);
}
}
#[test]
fn 不重合就一个都不动() {
let mut c = vec![[0.0, 0.0, 0.0], [1.5, 0.0, 0.0], [0.0, 1.5, 0.0]];
let before = c.clone();
assert_eq!(break_coincidence(&mut c), 0);
assert_eq!(c, before, "没有重合时不许碰坐标");
}
#[test]
fn 重合的会被分开() {
let mut c = vec![[0.0; 3]; 4];
c.push([5.0, 0.0, 0.0]); let moved = break_coincidence(&mut c);
assert_eq!(moved, 4, "四个重合的都该动");
assert_eq!(c[4], [5.0, 0.0, 0.0], "不重合的那个不许动");
for i in 0..4 {
for j in (i + 1)..4 {
let d = (0..3)
.map(|t| (c[i][t] - c[j][t]).powi(2))
.sum::<f64>()
.sqrt();
assert!(d > COINCIDENT_TOL, "{i}/{j} 还是重合:{d}");
}
}
}
#[test]
fn 位移是确定的() {
let build = || {
let mut c = vec![[0.0; 3]; 6];
break_coincidence(&mut c);
c
};
assert_eq!(build(), build(), "两次跑出来的位移必须逐位相同");
}
#[test]
fn 幅度受控() {
let mut c = vec![[0.0; 3]; 32];
break_coincidence(&mut c);
for (i, p) in c.iter().enumerate() {
for (t, v) in p.iter().enumerate() {
assert!(
v.abs() <= AMPLITUDE / 2.0 + 1e-12,
"第 {i} 个原子第 {t} 分量位移 {v} 超过 {}",
AMPLITUDE / 2.0
);
}
}
}
}