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
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:
co-authored by
Claude Fable 5.1
parent
6f9b0d43b2
commit
e31576d543
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user