use cartan_core::Manifold;
use cartan_dec::{Mesh, Operators};
use volterra_core::ActiveNematicParams;
use volterra_dec::stokes_dec::{StokesSolverDec, advect_q};
use volterra_dec::{molecular_field_dec, QFieldDec};
use crate::runner_dec::SnapStatsDec;
#[allow(clippy::too_many_arguments)]
pub fn run_wet_active_nematic_dec<M: Manifold>(
q_init: &QFieldDec,
params: &ActiveNematicParams,
ops: &Operators<M, 3, 2>,
mesh: &Mesh<M, 3, 2>,
curvature_correction: Option<&dyn Fn(usize) -> [[f64; 3]; 3]>,
n_steps: usize,
snap_every: usize,
) -> Result<(QFieldDec, Vec<SnapStatsDec>), String> {
let stokes = StokesSolverDec::new(ops, mesh)?;
let coords: Vec<[f64; 3]> = mesh.vertices.iter().map(|v| {
let s = format!("{:?}", v);
let nums: Vec<f64> = s
.chars()
.filter(|c| c.is_ascii_digit() || *c == '.' || *c == '-' || *c == ',' || *c == ' ' || *c == 'e' || *c == '+')
.collect::<String>()
.split(',')
.filter_map(|t| t.trim().parse::<f64>().ok())
.collect();
match nums.len() {
2 => [nums[0], nums[1], 0.0],
n if n >= 3 => [nums[0], nums[1], nums[2]],
_ => [0.0, 0.0, 0.0],
}
}).collect();
let mut q = q_init.clone();
let mut stats = Vec::new();
for step in 0..=n_steps {
if step % snap_every == 0 {
stats.push(SnapStatsDec {
time: step as f64 * params.dt,
mean_s: q.mean_order_param(),
n_vertices: q.n_vertices,
});
}
if step < n_steps {
let vel = stokes.solve(&q, params, ops, mesh);
let rhs = |qq: &QFieldDec| -> QFieldDec {
let h = molecular_field_dec(qq, params, ops, curvature_correction);
let mut dq = h.scale(params.gamma_r);
let adv = advect_q(
qq, &vel,
&mesh.boundaries,
&mesh.vertex_boundaries,
&coords,
);
for i in 0..qq.n_vertices {
dq.q1[i] -= adv.q1[i];
dq.q2[i] -= adv.q2[i];
}
dq
};
let k1 = rhs(&q);
let q2 = q.add(&k1.scale(0.5 * params.dt));
let k2 = rhs(&q2);
let q3 = q.add(&k2.scale(0.5 * params.dt));
let k3 = rhs(&q3);
let q4 = q.add(&k3.scale(params.dt));
let k4 = rhs(&q4);
let update = k1.add(&k2.scale(2.0)).add(&k3.scale(2.0)).add(&k4);
q = q.add(&update.scale(params.dt / 6.0));
}
}
Ok((q, stats))
}