use nalgebra::Vector3; use rtx_fsi::{FluidFace, WettedSurface}; /// A face on a smoothly curved, nearly collinear edge (the deformed-flag /// neighbourhood that broke the fixed-count recruitment): the transfer must /// widen the neighbourhood until the opposite face's nodes give it a /// two-dimensional spread, and the verified constraints must then hold. #[test] fn nearly_collinear_curved_edge_recruits_wider() { let mut nodes = Vec::new(); let mut x = 0.255; // Deformed edges: y = y0 + kappa * (x - 0.25)^2 with the FSI1 scale. while x < 0.6 + 1e-9 { let bend = 0.013 * (x - 0.25) * (x - 0.25) / 2.0; nodes.push(Vector3::new(x, 0.19 + bend, 0.0)); nodes.push(Vector3::new(x, 0.21 + bend, 0.0)); x += 0.005; } let bend = |x: f64| 0.013 * (x - 0.25) * (x - 0.25) / 2.0; let faces: Vec = (0..60) .map(|k| { let x = 0.26 + 0.005 * k as f64 + 0.00125; FluidFace { centroid: Vector3::new(x, 0.19 + bend(x), 0.0), normal: Vector3::new(0.0, -1.0, 0.0), area: 0.0025, } }) .collect(); let surface = WettedSurface::build(&faces, &nodes).expect("adaptive recruitment must succeed"); for face in 0..faces.len() { let weights = surface.weights_for(face); let unity: f64 = weights.iter().map(|(_, w)| w).sum(); assert!((unity - 1.0).abs() < 1e-9, "face {face}: unity {unity}"); let max_weight = weights.iter().map(|(_, w)| w.abs()).fold(0.0, f64::max); assert!( max_weight < 100.0, "face {face}: weight blow-up {max_weight}" ); } }