rtx-cfd: the deformed-tip outline chooses the flat / semicircle branch against the UNDEFORMED half-thickness — at the semicircle setting the deformed tip's radius breathes by nanometres and flipped the topology (143 → 144 points) within the first steps of the P6-b ny 41 cap-12 release at every α; pin: the point count is fixed under ± 1e-6 thickness breathing at h 10 / 6.6 mm and ny 41, semicircle and flat
CI / Build (macos-latest) (push) Waiting to run
CI / Test (macos-latest) (push) Blocked by required conditions
CI / Test (ubuntu-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (macos-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (ubuntu-latest) (push) Blocked by required conditions
CI / WASM Build + Size Check (push) Blocked by required conditions
CI / Distributed Training Tests (push) Blocked by required conditions
CI / CI Success (push) Blocked by required conditions
CI / Format Check (push) Failing after 6s
Performance Benchmarks / Run Benchmarks (push) Failing after 6s
CI / Build (ubuntu-latest) (push) Failing after 7s
CI / Clippy Check (push) Failing after 7s
Documentation / Build User Guide (push) Successful in 17s
Documentation / Build API Documentation (push) Failing after 22s
CI / Build CPU-Only (Explicit) (push) Failing after 1m8s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YJPeT6WA2e7YvAnS875AHL
This commit is contained in:
Omar Sobh
2026-09-15 11:13:55 -05:00
co-authored by Claude Fable 5.1
parent c3dbd5040a
commit 1c98156653
2 changed files with 62 additions and 4 deletions
@@ -952,9 +952,16 @@ pub fn cylinder_flag_outline_deformed_tip(
let mut pts: Vec<[f64; 2]> = Vec::new();
// 1. Top edge: from the arc's top end toward the root, along the top
// polyline (given tip → root) from arclength `radius` to x = x_f.
// The corner radius: `radius` (the semicircle) or the flat tip's.
let rc = tip_corner.min(radius).max(0.0);
let flat = rc < radius - 1e-12;
// The corner radius: `radius` (the semicircle) or the flat tip's. The
// branch is chosen against the UNDEFORMED half-thickness `t`, never the
// deformed tip's `radius` (which breathes by nanometres under the FEA's
// deformation and flipped the topology at the semicircle setting).
let flat = tip_corner < t - 1e-9;
let rc = if flat {
tip_corner.min(radius).max(0.0)
} else {
radius
};
// Corner arc centres and the tangent points on the faces.
let c_top = [
tc[0] - rc * axis[0] - rc * normal[0],
@@ -25,7 +25,14 @@ const FILLET: f64 = 0.5 * 0.41 / 41.0;
const CORNER: f64 = 0.0025;
fn edges(a: f64, nx: usize, ny: usize) -> FlagEdges {
edges_breathing(a, nx, ny, 0.0)
}
/// The flag's edges with the thickness scaled by `1 + eps` (the FEA's
/// deformed tip is never exactly `t` thick).
fn edges_breathing(a: f64, nx: usize, ny: usize, eps: f64) -> FlagEdges {
let len = X1 - X0;
let th = T * (1.0 + eps);
let centre = |x: f64| {
let xi = (x - X0) / len;
let y = a * xi * xi * (3.0 - xi) / 2.0;
@@ -35,7 +42,7 @@ fn edges(a: f64, nx: usize, ny: usize) -> FlagEdges {
let edge = |x: f64, side: f64| -> [f64; 2] {
let (y, dy) = centre(x);
let n = (1.0 + dy * dy).sqrt();
[x - side * T * dy / n, CENTRE[1] + y + side * T / n]
[x - side * th * dy / n, CENTRE[1] + y + side * th / n]
};
let m = 2 * nx;
let bottom: Vec<[f64; 2]> = (0..=m)
@@ -234,3 +241,47 @@ fn flat_tip_patch_builds_straight_and_bent_cold_and_warm() -> CfdResult<()> {
}
Ok(())
}
/// The semicircle setting (`tip_corner = t`) must keep its topology when
/// the deformed tip is a few nanometres thicker or thinner than `t` (the
/// P6-b ny 41 cap-12 marches died at every α on "topology changed
/// 143x12 -> 144x12" within the first steps of the release — the flat /
/// semicircle branch was chosen against the DEFORMED half-thickness).
#[test]
fn semicircle_setting_keeps_its_topology_under_thickness_breathing() {
for &h in &[0.01, 0.41 / 41.0, 0.41 / 62.0] {
let n0 = outline_breathing(0.0, h, T, 0.0).len();
for &eps in &[-1e-6, -1e-9, 1e-12, 1e-9, 1e-6, 1e-4] {
for &a in &[0.0, 1e-5, -1e-5, 0.08] {
let n = outline_breathing(a, h, T, eps).len();
assert_eq!(n, n0, "h = {h}, eps = {eps:e}, a = {a}: {n} points vs {n0}");
}
}
// The flat tip is insensitive too.
let f0 = outline_breathing(0.0, h, CORNER, 0.0).len();
for &eps in &[-1e-6, 1e-6, 1e-4] {
assert_eq!(
outline_breathing(0.0, h, CORNER, eps).len(),
f0,
"flat, h = {h}, eps = {eps:e}"
);
}
}
}
fn outline_breathing(a: f64, h: f64, corner: f64, eps: f64) -> Vec<[f64; 2]> {
cylinder_flag_outline_deformed_tip(
CENTRE,
R,
T,
&edges_breathing(a, 35, 2, eps),
X1,
FILLET,
3,
16,
h,
1.15,
corner,
)
.0
}