overset mesh: the flat-tip outline (P5-3 option B) — cylinder_flag_outline_deformed_tip / cylinder_flag_patch_deformed{,_from}_tip take the tip's corner radius (t = the recorded semicircle, bit for bit; smaller = the benchmark's flat face between corner arcs sampled at the wall spacing, point count fixed across the deformation, the tip's corners kept off the hull source); pins: corner t reproduces the recorded outline, the 2.5 mm outline has the exact area excess with no collapsed spacing, the O-grid builds straight and at ± 80 mm cold and warm at ny 41/62; harness knob RTX_FSI2O_TIP_CORNER (default 0.01) on the cold and warm builds, printed in both headers; pinned-toolchain fmt on touched crates
Performance Benchmarks / Run Benchmarks (push) Failing after 10s
CI / Format Check (push) Failing after 10s
CI / Build (ubuntu-latest) (push) Failing after 10s
CI / Clippy Check (push) Failing after 10s
Documentation / Build User Guide (push) Successful in 9s
CI / Build CPU-Only (Explicit) (push) Failing after 1m13s
Documentation / Build API Documentation (push) Failing after 2m25s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Test (macos-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (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
Performance Benchmarks / Run Benchmarks (push) Failing after 10s
CI / Format Check (push) Failing after 10s
CI / Build (ubuntu-latest) (push) Failing after 10s
CI / Clippy Check (push) Failing after 10s
Documentation / Build User Guide (push) Successful in 9s
CI / Build CPU-Only (Explicit) (push) Failing after 1m13s
Documentation / Build API Documentation (push) Failing after 2m25s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Test (macos-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (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
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01LzcjQX7tvgn87CQCyg9Cfr
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
7224521309
commit
415c32ab04
@@ -667,8 +667,83 @@ pub fn cylinder_flag_patch_deformed_from(
|
||||
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);
|
||||
cylinder_flag_patch_deformed_from_tip(
|
||||
prev,
|
||||
centre,
|
||||
r,
|
||||
t,
|
||||
edges,
|
||||
x_tip_ref,
|
||||
h,
|
||||
fillet,
|
||||
offset,
|
||||
nn,
|
||||
stretch,
|
||||
winslow_sweeps,
|
||||
t,
|
||||
)
|
||||
}
|
||||
|
||||
/// [`cylinder_flag_patch_deformed`] with the flat tip of
|
||||
/// [`cylinder_flag_outline_deformed_tip`] (`tip_corner = t` is the recorded
|
||||
/// patch).
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn cylinder_flag_patch_deformed_tip(
|
||||
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,
|
||||
tip_corner: f64,
|
||||
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
||||
cylinder_flag_patch_deformed_from_tip(
|
||||
None,
|
||||
centre,
|
||||
r,
|
||||
t,
|
||||
edges,
|
||||
x_tip_ref,
|
||||
h,
|
||||
fillet,
|
||||
offset,
|
||||
nn,
|
||||
stretch,
|
||||
winslow_sweeps,
|
||||
tip_corner,
|
||||
)
|
||||
}
|
||||
|
||||
/// [`cylinder_flag_patch_deformed_from`] with the flat tip.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn cylinder_flag_patch_deformed_from_tip(
|
||||
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,
|
||||
tip_corner: f64,
|
||||
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
||||
let (inner, tip) = cylinder_flag_outline_deformed_tip(
|
||||
centre, r, t, edges, x_tip_ref, fillet, 3, 16, h, 1.15, tip_corner,
|
||||
);
|
||||
// With a flat tip the outline's corners would put 90° corners on the
|
||||
// hull, whose normal offset folds the rays at the tip; the tip disc
|
||||
// (already a hull source) covers the tip, so the inner points ahead of
|
||||
// the disc's centre plane are left out of the hull source.
|
||||
let flat = tip_corner < tip.radius - 1e-12;
|
||||
// The hull source carries the deformed outline itself: for a straight
|
||||
// flag the cylinder and the tip disc alone give the flag's surfaces as
|
||||
// the hull's tangents, for a BENT flag they give the chord under the
|
||||
@@ -676,7 +751,9 @@ pub fn cylinder_flag_patch_deformed_from(
|
||||
// where 6 h was asked, the acceptors' donors reaching into the fringe
|
||||
// (P5-2's first death).
|
||||
let mut hull_src = hull_source(centre, r, tip.centre, tip.radius, tip.axis);
|
||||
hull_src.extend(inner.iter().copied());
|
||||
hull_src.extend(inner.iter().copied().filter(|p| {
|
||||
!flat || (p[0] - tip.centre[0]) * tip.axis[0] + (p[1] - tip.centre[1]) * tip.axis[1] < 0.0
|
||||
}));
|
||||
let start = prev.and_then(|m| {
|
||||
(m.ns() == inner.len() && m.nn() == nn).then(|| {
|
||||
(0..=nn)
|
||||
@@ -767,11 +844,7 @@ fn arclength_at_x(pts: &[[f64; 2]], cum: &[f64], x0: f64, from_end: bool) -> f64
|
||||
return cum[i] + f * (cum[i + 1] - cum[i]);
|
||||
}
|
||||
}
|
||||
if from_end {
|
||||
cum[n - 1]
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
if from_end { cum[n - 1] } else { 0.0 }
|
||||
}
|
||||
|
||||
/// Points at the arclength fractions `fr` (`0 ..= 1`) along an open
|
||||
@@ -810,6 +883,33 @@ pub fn cylinder_flag_outline_deformed(
|
||||
k_tip: usize,
|
||||
d_straight: f64,
|
||||
grade: f64,
|
||||
) -> (Vec<[f64; 2]>, TipArc) {
|
||||
cylinder_flag_outline_deformed_tip(
|
||||
centre, r, t, edges, x_tip_ref, fillet, k_fillet, k_tip, d_straight, grade, t,
|
||||
)
|
||||
}
|
||||
|
||||
/// [`cylinder_flag_outline_deformed`] with the tip as the benchmark's FLAT
|
||||
/// face between two corner arcs of radius `tip_corner` (P5-3 option B):
|
||||
/// `tip_corner = t` is the recorded semicircle, bit for bit; smaller
|
||||
/// corners keep the along-wall spacing `d0` (the corner arcs and the flat
|
||||
/// face are sampled at it, so the fluid step does not collapse) and a
|
||||
/// point count fixed across the deformation (the flat face's count comes
|
||||
/// from the UNDEFORMED thickness). The returned [`TipArc`] is still the
|
||||
/// tip disc of radius half the tip edge — the hull source's shape.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn cylinder_flag_outline_deformed_tip(
|
||||
centre: [f64; 2],
|
||||
r: f64,
|
||||
t: f64,
|
||||
edges: &FlagEdges,
|
||||
x_tip_ref: f64,
|
||||
fillet: f64,
|
||||
k_fillet: usize,
|
||||
k_tip: usize,
|
||||
d_straight: f64,
|
||||
grade: f64,
|
||||
tip_corner: f64,
|
||||
) -> (Vec<[f64; 2]>, TipArc) {
|
||||
let (cx, cy) = (centre[0], centre[1]);
|
||||
// Root junction, as the rigid outline.
|
||||
@@ -852,9 +952,31 @@ pub fn cylinder_flag_outline_deformed(
|
||||
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;
|
||||
// Corner arc centres and the tangent points on the faces.
|
||||
let c_top = [
|
||||
tc[0] - rc * axis[0] - rc * normal[0],
|
||||
tc[1] - rc * axis[1] - rc * normal[1],
|
||||
];
|
||||
let c_bot = [
|
||||
b[0] - rc * axis[0] + rc * normal[0],
|
||||
b[1] - rc * axis[1] + rc * normal[1],
|
||||
];
|
||||
let (start_top, start_bot, s_top0, s_bot1) = if flat {
|
||||
(
|
||||
[c_top[0] + rc * normal[0], c_top[1] + rc * normal[1]],
|
||||
[c_bot[0] - rc * normal[0], c_bot[1] - rc * normal[1]],
|
||||
rc,
|
||||
rc,
|
||||
)
|
||||
} else {
|
||||
(start_top, start_bot, radius, radius)
|
||||
};
|
||||
let cum_t = open_cum(top);
|
||||
let s_root_t = arclength_at_x(top, &cum_t, x_f, true);
|
||||
let mut top_run = open_slice(top, &cum_t, radius, s_root_t);
|
||||
let mut top_run = open_slice(top, &cum_t, s_top0, s_root_t);
|
||||
top_run[0] = start_top;
|
||||
pts.extend(along_fractions(&top_run, &fr));
|
||||
// 2. Top fillet, 3. cylinder arc, 4. bottom fillet — the rigid construction.
|
||||
@@ -885,13 +1007,34 @@ pub fn cylinder_flag_outline_deformed(
|
||||
// to `radius` short of the corner, ending at the arc's bottom end.
|
||||
let cum_b = open_cum(bottom);
|
||||
let s_root_b = arclength_at_x(bottom, &cum_b, x_f, false);
|
||||
let mut bot_run = open_slice(bottom, &cum_b, s_root_b, cum_b[nb - 1] - radius);
|
||||
let mut bot_run = open_slice(bottom, &cum_b, s_root_b, cum_b[nb - 1] - s_bot1);
|
||||
let last = bot_run.len() - 1;
|
||||
bot_run[last] = start_bot;
|
||||
pts.extend(along_fractions(&bot_run, &fr));
|
||||
// 6. Tip semicircle from the bottom end through the apex to the top end.
|
||||
let a0 = (start_bot[1] - tip_c[1]).atan2(start_bot[0] - tip_c[0]);
|
||||
pts.extend(arc_points(tip_c, radius, a0, a0 + PI, k_tip));
|
||||
if flat {
|
||||
// 6'. Bottom corner arc (from the bottom face to the tip face), the
|
||||
// flat tip face, the top corner arc (to the top face, whose start
|
||||
// point opens the outline — excluded here). Counts from the
|
||||
// UNDEFORMED thickness so the topology is fixed.
|
||||
let k_c = ((PI * rc / 2.0) / d0).round().max(2.0) as usize;
|
||||
let k_f = ((2.0 * (t - rc)) / d0).round().max(1.0) as usize;
|
||||
let a_b0 = (-normal[1]).atan2(-normal[0]);
|
||||
pts.extend(arc_points(c_bot, rc, a_b0, a_b0 + PI / 2.0, k_c));
|
||||
let (p0, p1) = (
|
||||
[c_bot[0] + rc * axis[0], c_bot[1] + rc * axis[1]],
|
||||
[c_top[0] + rc * axis[0], c_top[1] + rc * axis[1]],
|
||||
);
|
||||
for m in 0..k_f {
|
||||
let f = m as f64 / k_f as f64;
|
||||
pts.push([p0[0] + f * (p1[0] - p0[0]), p0[1] + f * (p1[1] - p0[1])]);
|
||||
}
|
||||
let a_t0 = axis[1].atan2(axis[0]);
|
||||
pts.extend(arc_points(c_top, rc, a_t0, a_t0 + PI / 2.0, k_c));
|
||||
} else {
|
||||
// 6. Tip semicircle from the bottom end through the apex to the top end.
|
||||
let a0 = (start_bot[1] - tip_c[1]).atan2(start_bot[0] - tip_c[0]);
|
||||
pts.extend(arc_points(tip_c, radius, a0, a0 + PI, k_tip));
|
||||
}
|
||||
(
|
||||
pts,
|
||||
TipArc {
|
||||
|
||||
@@ -41,7 +41,7 @@ mod projection;
|
||||
use super::ale::{AleBoundaries, SideBoundary};
|
||||
use super::embedded_body::{EmbeddedBody, EmbeddedMask, FaceKind};
|
||||
use super::poisson::{
|
||||
solve_multigrid_pcg, MgPrecision, MultigridParameters, PoissonProblem, PoissonSolverKind,
|
||||
MgPrecision, MultigridParameters, PoissonProblem, PoissonSolverKind, solve_multigrid_pcg,
|
||||
};
|
||||
use super::simple::ConvectionScheme;
|
||||
use super::{FlowField, SolverResult};
|
||||
|
||||
@@ -53,8 +53,8 @@ pub use curvilinear::{
|
||||
};
|
||||
pub use embedded::{EmbeddedParameters, EmbeddedPisoSolver, EmbeddedResult, EmbeddedSolverState};
|
||||
pub use embedded_body::{
|
||||
polygon_interface_velocity, polygon_signed_distance, EmbeddedBody, EmbeddedMask, FaceKind,
|
||||
SurfaceForce, SurfaceSample,
|
||||
EmbeddedBody, EmbeddedMask, FaceKind, SurfaceForce, SurfaceSample, polygon_interface_velocity,
|
||||
polygon_signed_distance,
|
||||
};
|
||||
pub use flow_field::FlowField;
|
||||
pub use overset::{
|
||||
|
||||
Reference in New Issue
Block a user