rtx-cfd: cylinder_flag_patch_deformed_from — the warm-started regeneration (P5's cost lever): the previous patch's interior and its outer ring projected onto the new offset polygon as the start, and an IDEMPOTENT build (one Winslow sweep alternating with the ray re-spacing; the P4-0 one-shot is not a fixed point — measured as the interior moving 0.05 h per build at rest), so a base converged as that map's fixed point stays put (9e-11 h at rest) and each build tracks the outline (interior/wall motion 0.99–1.14, worst angle 74.7°, wall row 0.37 h) 4.5× faster than the cold build; the rigid generator untouched (pins pass); fsi2 overset harness: RTX_FSI2O_WARM_SWEEPS with the converged base as the initial patch and the committed step's mesh as each step's warm start
Documentation / Build User Guide (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (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
Documentation / Build API Documentation (push) Canceled after 0s
CI / CI Success (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
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
Documentation / Build User Guide (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (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
Documentation / Build API Documentation (push) Canceled after 0s
CI / CI Success (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
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_0116sg1Qz1gMv9hdcKP1XUam
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
62f1d4bf9b
commit
3a68048934
@@ -589,7 +589,16 @@ pub fn cylinder_flag_patch(
|
||||
// 1.74 → 1.31 with fillet = h/2 on the ny = 41/62/82 ladder).
|
||||
let inner = cylinder_flag_outline(centre, r, t, x_tip, fillet, 3, 16, h, 1.15);
|
||||
let hull_src = hull_source(centre, r, [x_tip - t, centre[1]], t, [1.0, 0.0]);
|
||||
o_grid_from_outline(inner, hull_src, h, offset, nn, stretch, winslow_sweeps)
|
||||
o_grid_from_outline(
|
||||
inner,
|
||||
hull_src,
|
||||
h,
|
||||
offset,
|
||||
nn,
|
||||
stretch,
|
||||
winslow_sweeps,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
/// The FEA flag's wetted edges, deformed: `bottom` from the root to the
|
||||
@@ -622,11 +631,62 @@ pub fn cylinder_flag_patch_deformed(
|
||||
nn: usize,
|
||||
stretch: f64,
|
||||
winslow_sweeps: usize,
|
||||
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
||||
cylinder_flag_patch_deformed_from(
|
||||
None,
|
||||
centre,
|
||||
r,
|
||||
t,
|
||||
edges,
|
||||
x_tip_ref,
|
||||
h,
|
||||
fillet,
|
||||
offset,
|
||||
nn,
|
||||
stretch,
|
||||
winslow_sweeps,
|
||||
)
|
||||
}
|
||||
|
||||
/// [`cylinder_flag_patch_deformed`] warm-started from `prev` (the same
|
||||
/// topology: its interior rows are the Winslow start instead of the
|
||||
/// transfinite one, so a few sweeps suffice when the outline moved a
|
||||
/// little — P5's per-pass regeneration). `None` is the cold build.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn cylinder_flag_patch_deformed_from(
|
||||
prev: Option<&PatchMesh>,
|
||||
centre: [f64; 2],
|
||||
r: f64,
|
||||
t: f64,
|
||||
edges: &FlagEdges,
|
||||
x_tip_ref: f64,
|
||||
h: f64,
|
||||
fillet: f64,
|
||||
offset: f64,
|
||||
nn: usize,
|
||||
stretch: f64,
|
||||
winslow_sweeps: usize,
|
||||
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
||||
let (inner, tip) =
|
||||
cylinder_flag_outline_deformed(centre, r, t, edges, x_tip_ref, fillet, 3, 16, h, 1.15);
|
||||
let hull_src = hull_source(centre, r, tip.centre, tip.radius, tip.axis);
|
||||
o_grid_from_outline(inner, hull_src, h, offset, nn, stretch, winslow_sweeps)
|
||||
let start = prev.and_then(|m| {
|
||||
(m.ns() == inner.len() && m.nn() == nn).then(|| {
|
||||
(0..=nn)
|
||||
.map(|k| (0..=m.ns()).map(|i| m.node_xy(m.node(k, i))).collect())
|
||||
.collect::<Vec<Vec<[f64; 2]>>>()
|
||||
})
|
||||
});
|
||||
o_grid_from_outline(
|
||||
inner,
|
||||
hull_src,
|
||||
h,
|
||||
offset,
|
||||
nn,
|
||||
stretch,
|
||||
winslow_sweeps,
|
||||
start,
|
||||
)
|
||||
}
|
||||
|
||||
/// The deformed flag's rounded tip: the semicircle's centre, radius and
|
||||
@@ -857,6 +917,7 @@ fn hull_source(
|
||||
/// The O-grid body shared by the rigid and the deformed generators: the
|
||||
/// inner ring (counter-clockwise in, reversed to clockwise), the outer
|
||||
/// ring on the hull offset, transfinite start, Winslow, re-spacing.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn o_grid_from_outline(
|
||||
mut inner: Vec<[f64; 2]>,
|
||||
hull_src: Vec<[f64; 2]>,
|
||||
@@ -865,6 +926,7 @@ fn o_grid_from_outline(
|
||||
nn: usize,
|
||||
stretch: f64,
|
||||
winslow_sweeps: usize,
|
||||
start: Option<Vec<Vec<[f64; 2]>>>,
|
||||
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
||||
inner.reverse(); // clockwise
|
||||
let ns = inner.len();
|
||||
@@ -892,23 +954,68 @@ fn o_grid_from_outline(
|
||||
.collect();
|
||||
let mut inner_closed = inner.clone();
|
||||
inner_closed.push(inner[0]);
|
||||
// Transfinite start.
|
||||
// Transfinite start, or the previous mesh's interior with the new
|
||||
// inner and outer rings (the warm start).
|
||||
let eta = stretched_fractions(nn, stretch);
|
||||
let mut x: Vec<Vec<[f64; 2]>> = eta
|
||||
.iter()
|
||||
.map(|&e| {
|
||||
(0..=ns)
|
||||
.map(|i| {
|
||||
[
|
||||
(1.0 - e) * inner_closed[i][0] + e * outer[i][0],
|
||||
(1.0 - e) * inner_closed[i][1] + e * outer[i][1],
|
||||
]
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let report = winslow_smooth(&mut x, ns, 1e-10 * h, winslow_sweeps, Some(&outer_poly));
|
||||
respace_rays(&mut x, ns, &eta);
|
||||
let warm = start.is_some();
|
||||
let mut x: Vec<Vec<[f64; 2]>> = match start {
|
||||
Some(mut rows) => {
|
||||
rows[0] = inner_closed.clone();
|
||||
// The outer ring warm-starts too: the previous ring's nodes
|
||||
// projected onto the new offset polygon keep the sliding
|
||||
// rows' converged distribution (the crude normal push would
|
||||
// undo it every build — measured as the interior moving
|
||||
// 0.05 h with the wall at rest).
|
||||
rows[nn] = rows[nn]
|
||||
.iter()
|
||||
.map(|&p| nearest_on_polyline(&outer_poly, p))
|
||||
.collect();
|
||||
rows
|
||||
}
|
||||
None => eta
|
||||
.iter()
|
||||
.map(|&e| {
|
||||
(0..=ns)
|
||||
.map(|i| {
|
||||
[
|
||||
(1.0 - e) * inner_closed[i][0] + e * outer[i][0],
|
||||
(1.0 - e) * inner_closed[i][1] + e * outer[i][1],
|
||||
]
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
// The cold build: Winslow, then the ray re-spacing (the P4-0 one-shot).
|
||||
// The warm build must be IDEMPOTENT at rest, and the one-shot is not
|
||||
// (the re-spaced mesh is not the smoother's fixed point: measured as
|
||||
// the interior moving 0.05 h per build with the wall at rest), so it
|
||||
// alternates one sweep with a re-spacing — the base converged as a
|
||||
// fixed point of that map stays put, and a moving outline is tracked.
|
||||
let report = if warm {
|
||||
let mut last = f64::INFINITY;
|
||||
let mut done = 0;
|
||||
for k in 0..winslow_sweeps {
|
||||
let before = x.clone();
|
||||
winslow_smooth(&mut x, ns, 0.0, 1, Some(&outer_poly));
|
||||
respace_rays(&mut x, ns, &eta);
|
||||
last = x
|
||||
.iter()
|
||||
.zip(&before)
|
||||
.flat_map(|(r, b)| r.iter().zip(b))
|
||||
.map(|(p, q)| ((p[0] - q[0]).powi(2) + (p[1] - q[1]).powi(2)).sqrt())
|
||||
.fold(0.0, f64::max);
|
||||
done = k + 1;
|
||||
if last < 1e-10 * h {
|
||||
break;
|
||||
}
|
||||
}
|
||||
(done, last)
|
||||
} else {
|
||||
let report = winslow_smooth(&mut x, ns, 1e-10 * h, winslow_sweeps, Some(&outer_poly));
|
||||
respace_rays(&mut x, ns, &eta);
|
||||
report
|
||||
};
|
||||
let mut xs = Vec::with_capacity((nn + 1) * (ns + 1));
|
||||
let mut ys = Vec::with_capacity(xs.capacity());
|
||||
for row in &x {
|
||||
|
||||
Reference in New Issue
Block a user