rtx-fsi: spike-clamp the force-measurement probe
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Format Check (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
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Format Check (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
measure_force integrated raw traction samples while the coupling loads carried the 20x-median clamp — so the s = 1 benchmark run's REPORTED drag/lift were +-4,000-scale garbage against a +-78 reference while its displacements matched the benchmark to 0.1%. Collect, clamp, then integrate, both probes. Reporting only: the committed FSI2 default reproduces its trajectory to every printed digit (uy 3.7732 / 3.7920 mm) and its rigid-phase drag (121.4) with the clamp in. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Lnyrw33Lu6rUhW42E9KHwq
This commit is contained in:
co-authored by
Claude Fable 5
parent
c1bcdc408e
commit
555a72cbc0
@@ -449,8 +449,13 @@ impl Fsi2Harness {
|
|||||||
let mask = solver.mask().unwrap();
|
let mask = solver.mask().unwrap();
|
||||||
let body = solver.body().unwrap();
|
let body = solver.body().unwrap();
|
||||||
let vertices = self.shared.read().unwrap().0.clone();
|
let vertices = self.shared.read().unwrap().0.clone();
|
||||||
let mut drag = 0.0;
|
// Collect, then clamp, then integrate: the same 20x-median spike
|
||||||
let mut lift = 0.0;
|
// clamp the coupling loads carry. Without it the REPORTED
|
||||||
|
// drag/lift at large deformation are dominated by the rare wild
|
||||||
|
// reconstructions (the s = 1 benchmark run printed +-4,000-scale
|
||||||
|
// load swings against a +-78 reference while its displacements
|
||||||
|
// matched the benchmark to 0.1%).
|
||||||
|
let mut samples: Vec<(f64, f64, f64)> = Vec::new();
|
||||||
let poly_probe = EmbeddedBody::polygon(vertices.clone());
|
let poly_probe = EmbeddedBody::polygon(vertices.clone());
|
||||||
for s in poly_probe.surface_samples(0.5 * self.h) {
|
for s in poly_probe.surface_samples(0.5 * self.h) {
|
||||||
if circle_sdf(s.x, s.y) < 1e-9 {
|
if circle_sdf(s.x, s.y) < 1e-9 {
|
||||||
@@ -459,8 +464,7 @@ impl Fsi2Harness {
|
|||||||
if let Some((tx, ty)) = mask.traction_at(
|
if let Some((tx, ty)) = mask.traction_at(
|
||||||
body, &field.u, &field.v, &field.p, self.mu, 0.0, s.x, s.y, s.nx, s.ny,
|
body, &field.u, &field.v, &field.p, self.mu, 0.0, s.x, s.y, s.nx, s.ny,
|
||||||
) {
|
) {
|
||||||
drag += tx * s.ds;
|
samples.push((tx, ty, s.ds));
|
||||||
lift += ty * s.ds;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let circle_probe = EmbeddedBody::circle(0.2, 0.2, 0.05);
|
let circle_probe = EmbeddedBody::circle(0.2, 0.2, 0.05);
|
||||||
@@ -471,10 +475,28 @@ impl Fsi2Harness {
|
|||||||
if let Some((tx, ty)) = mask.traction_at(
|
if let Some((tx, ty)) = mask.traction_at(
|
||||||
body, &field.u, &field.v, &field.p, self.mu, 0.0, s.x, s.y, s.nx, s.ny,
|
body, &field.u, &field.v, &field.p, self.mu, 0.0, s.x, s.y, s.nx, s.ny,
|
||||||
) {
|
) {
|
||||||
drag += tx * s.ds;
|
samples.push((tx, ty, s.ds));
|
||||||
lift += ty * s.ds;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut magnitudes: Vec<f64> = samples
|
||||||
|
.iter()
|
||||||
|
.map(|(tx, ty, _)| (tx * tx + ty * ty).sqrt())
|
||||||
|
.collect();
|
||||||
|
magnitudes.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||||
|
let median = magnitudes.get(magnitudes.len() / 2).copied().unwrap_or(0.0);
|
||||||
|
let cap = 20.0 * median;
|
||||||
|
let mut drag = 0.0;
|
||||||
|
let mut lift = 0.0;
|
||||||
|
for (tx, ty, ds) in samples {
|
||||||
|
let norm = (tx * tx + ty * ty).sqrt();
|
||||||
|
let scale = if median > 0.0 && norm > cap {
|
||||||
|
cap / norm
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
drag += tx * scale * ds;
|
||||||
|
lift += ty * scale * ds;
|
||||||
|
}
|
||||||
(drag, lift)
|
(drag, lift)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user