use std::time::Instant;
use cartan_core::bundle::EdgeTransport3D;
use cartan_core::fiber::{NematicFiber3D, Section, VecSection, FiberOps};
use cartan_dec::cartesian_connection::cartesian_3d_connection;
fn main() {
let nx = 32;
let ny = 32;
let nz = 32;
let dx = 1.0;
let dt = 0.01;
let n_steps = 2000;
let n = nx * ny * nz;
let k_frank = 1.0;
let a_eff = -1.5; let c_landau = 4.5;
let gamma_r = 1.0;
println!("=== 3D Beris-Edwards via Fiber Bundle Framework ===");
println!(" grid: {nx}x{ny}x{nz} = {n} vertices");
println!(" K = {k_frank}, a_eff = {a_eff}, c = {c_landau}");
println!(" dt = {dt}, steps = {n_steps}");
println!("Building Cartesian connection...");
let (transport, cov_lap) = cartesian_3d_connection(nx, ny, nz, dx);
println!(" {} edges", transport.edges.len());
let mut rng_seed = 42_u64;
let mut data: Vec<[f64; 5]> = (0..n)
.map(|i| {
let mut v = [0.0_f64; 5];
for c in 0..5 {
rng_seed = rng_seed.wrapping_mul(6364136223846793005).wrapping_add(1);
v[c] = 0.01 * ((rng_seed >> 33) as f64 / (1u64 << 31) as f64 - 0.5);
}
v
})
.collect();
let mean_s = |d: &[[f64; 5]]| -> f64 {
let sum: f64 = d.iter().map(|q| {
let q33 = -q[0] - q[3];
let tr2 = q[0]*q[0] + q[3]*q[3] + q33*q33
+ 2.0*(q[1]*q[1] + q[2]*q[2] + q[4]*q[4]);
(1.5 * tr2).sqrt()
}).sum::<f64>();
sum / d.len() as f64
};
println!("Running LdG relaxation...");
let t0 = Instant::now();
for step in 0..=n_steps {
if step % 200 == 0 {
let s = mean_s(&data);
let elapsed = t0.elapsed().as_secs_f64();
println!(" step {step:>5}/{n_steps} <S>={s:.4} wall={elapsed:.1}s");
}
if step < n_steps {
let section = VecSection::<NematicFiber3D>::from_vec(data.clone());
let lap = cov_lap.apply::<NematicFiber3D, 3, _>(§ion, &transport);
let bulk_linear = -a_eff; for i in 0..n {
let q = &data[i];
let q33 = -q[0] - q[3];
let tr_q2 = q[0]*q[0] + q[3]*q[3] + q33*q33
+ 2.0*(q[1]*q[1] + q[2]*q[2] + q[4]*q[4]);
let bulk = bulk_linear - 2.0 * c_landau * tr_q2;
let lap_v = lap.at(i);
for c in 0..5 {
let h_c = -k_frank * lap_v[c] + bulk * data[i][c];
data[i][c] += dt * gamma_r * h_c;
}
}
}
}
let elapsed = t0.elapsed().as_secs_f64();
let final_s = mean_s(&data);
println!("\nDone in {elapsed:.1}s");
println!("Final <S> = {final_s:.4}");
let s_eq = (1.5 * (-a_eff) / (2.0 * c_landau)).sqrt();
println!("Expected S_eq = {s_eq:.4}");
println!(
"Relative error: {:.2}%",
((final_s - s_eq) / s_eq * 100.0).abs()
);
}