rtx-cfd: OversetPisoSolver::solver_metric_force — the box force in the predictor's own flux form (upwind convective, diffusive, cell pressure on the momentum control volumes' faces, minus the unsteady term); box-independent to rounding in the active region (five boxes spread 2e-12 at step 5 vs the CV formula's ±0.5 %); overset_cfd1 prints wall − box = ring Σr + rest and saves the settled fields under RTX_OVERSET_CFD1_SAVE
CI / Format Check (push) Canceled after 0s
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Clippy Check (push) Canceled after 0s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Build (ubuntu-latest) (push) Canceled after 0s
CI / Test (macos-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (push) Canceled after 0s
CI / Python Bindings (maturin) (macos-latest) (push) Canceled after 0s
CI / Python Bindings (maturin) (ubuntu-latest) (push) Canceled after 0s
CI / WASM Build + Size Check (push) Canceled after 0s
CI / Distributed Training Tests (push) Canceled after 0s
CI / CI Success (push) Canceled after 0s
Documentation / Build API Documentation (push) Canceled after 0s
Documentation / Build User Guide (push) Canceled after 0s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01X2GmJXeQ2njUecEKiJZ1G2
This commit is contained in:
Omar Sobh
2026-09-06 13:47:43 -07:00
co-authored by Claude Fable 5.1
parent 6f9b0d43b2
commit e31576d543
2 changed files with 157 additions and 0 deletions
@@ -329,6 +329,75 @@ async fn run_cfd1(ny: usize, max_steps: usize) -> CfdResult<Cfd1> {
mr.interface_u,
mr.interface_v
);
// The box force in the solver's own flux form on the five boxes (must
// agree to rounding — the gate), and the bookkeeping it allows: the
// numerical x-momentum source inside the box on the fluid is
// wall box; the ring's share is Σr; the rest is the patch region's
// (hole boundary → wall) plus the two meshes' metric difference.
let boxes = [
(0.10, 0.75, 0.05, 0.36),
(0.09, 0.70, 0.07, 0.34),
(0.08, 1.00, 0.03, 0.38),
(0.10, 1.50, 0.05, 0.36),
(0.10, 0.75, 0.02, 0.39),
];
let solver_forces: Vec<(f64, f64)> = boxes
.iter()
.map(|&(x0, x1, y0, y1)| {
solver.solver_metric_force(
&field,
dt,
(
(x0 / h).round() as usize,
(x1 / h).round() as usize,
(y0 / h).round() as usize,
(y1 / h).round() as usize,
),
)
})
.collect();
let sf = solver_forces[0];
let spread = solver_forces.iter().fold(0.0_f64, |m, f| {
m.max((f.0 - sf.0).abs()).max((f.1 - sf.1).abs())
});
let ring_sum = mr.fringe_fringe.fx + mr.fringe_hole.fx;
println!(
" solver-metric box force ny = {ny}: ({:.4}, {:.4}) [5 boxes spread {:.2e}; CV formula {drag_cv:.4}]; x-momentum sources on the fluid inside the box [N/m, % of wall drag]: total wall box {:+.4} ({:+.2}%) = ring Σr {:+.4} ({:+.2}%) + rest (patch region + metric) {:+.4} ({:+.2}%)",
sf.0,
sf.1,
spread,
wall[0] - sf.0,
100.0 * (wall[0] - sf.0) / wall[0],
ring_sum,
100.0 * ring_sum / wall[0],
wall[0] - sf.0 - ring_sum,
100.0 * (wall[0] - sf.0 - ring_sum) / wall[0],
);
// `RTX_OVERSET_CFD1_SAVE=dir`: the settled fields, for offline
// diagnostics without the march (background in `FlowField::save`'s
// format; patch u, v, p as raw little-endian f64 vectors).
if let Ok(dir) = std::env::var("RTX_OVERSET_CFD1_SAVE") {
let tag = format!(
"ny{ny}_{}",
if std::env::var("RTX_OVERSET_CFD1_TVD").is_ok() {
"tvd"
} else {
"upwind"
}
);
let dir = std::path::Path::new(&dir);
std::fs::create_dir_all(dir).expect("save dir");
field.background.save(&dir.join(format!("bg_{tag}.bin")))?;
for (name, vals) in [
("u", &field.patch.u),
("v", &field.patch.v),
("p", &field.patch.p),
] {
let bytes: Vec<u8> = vals.iter().flat_map(|x| x.to_le_bytes()).collect();
std::fs::write(dir.join(format!("patch_{tag}_{name}.bin")), bytes).expect("save patch");
}
println!(" saved settled fields to {} as {tag}", dir.display());
}
// The wall load split and the fringe ring's extent (the tight box in
// the sensitivity list must stay outside it).
let (mut jmin, mut jmax, mut imin, mut imax) = (usize::MAX, 0, usize::MAX, 0);