#[derive(Debug, Clone)]
pub struct GeoForm {
pub data: Vec<f64>, pub alpha: f64, pub damping: f64, }
impl GeoForm {
pub fn from_leonov(len: usize, seed: u64) -> Self {
use rand::{Rng, SeedableRng};
use rand_pcg::Pcg64;
let mut rng = Pcg64::seed_from_u64(seed);
let mut data = vec![1.0, 1.0];
while data.len() < len {
let n = data.len();
let a = rng.random_range(-2.0..2.0);
let b = rng.random_range(-2.0..2.0);
let c = rng.random_range(-2.0..2.0);
let d = rng.random_range(1..=n.min(10));
let val = (a * data[n - 1] + b * data[n - 2] + c * data[n - d] / (1.0 + n as f64)).abs();
data.push(val);
}
Self {
data,
alpha: 0.1,
damping: 0.01,
}
}
pub fn adapt(&mut self, wave: &[f64], dt: f64) {
for (f, &psi) in self.data.iter_mut().zip(wave.iter()) {
*f += self.alpha * psi * psi * dt; *f -= self.damping * (*f - 1.0); }
}
}
#[derive(Debug, Clone)]
pub struct Wave {
pub psi_prev: Vec<f64>, pub psi: Vec<f64>, pub alpha: f64, }
impl Wave {
pub fn new(len: usize, impulse_pos: usize) -> Self {
let mut psi = vec![0.0; len];
psi[impulse_pos] = 1.0;
Self {
psi_prev: psi.clone(),
psi,
alpha: 0.5,
}
}
pub fn step(&mut self, form: &GeoForm) {
let len = self.psi.len();
let mut next = vec![0.0; len];
for i in 1..len - 1 {
let laplace = (self.psi[i + 1] - 2.0 * self.psi[i] + self.psi[i - 1]) / form.data[i].max(1e-6);
next[i] = 2.0 * self.psi[i] - self.psi_prev[i] + self.alpha * laplace;
}
self.psi_prev = self.psi.clone();
self.psi = next;
}
pub fn energy(&self) -> Vec<f64> {
self.psi.iter().map(|x| x * x).collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_adaptive_wave_memory() {
let mut form = GeoForm::from_leonov(64, 42);
let mut wave = Wave::new(64, 32);
for _ in 0..50 {
wave.step(&form);
let energy = wave.energy();
form.adapt(&energy, 0.1);
}
assert!(form.data.iter().any(|&f| f > 1.01));
}
}