P5-1: FSI2 with the fluid on the overset — fsi2_harness/overset.rs (the background without a body, the cylinder–flag patch regenerated around the deformed flag every pass via set_patch_mesh, the wall velocity from the interface velocities along the wetted polygon, the load from the patch's wall faces into WettedSurface::transfer_load — no probes, no clamp, no smoothing), fsi2_harness/overset_march.rs (the harness's rigid phase / release / subiterated coupling with its acceptance rule, no rescue machinery, death returned not panicked), tests/turek_hron_fsi2_overset.rs (RTX_FSI2O_* knobs); rtx-cfd: CurvilinearPisoSolver::wall_tractions (per-face pressure + full-stress traction, surface_force sums the same terms bit-identically); Interface::edges (bottom/tip/top for the generator); cylinder_flag_mms RTX_CF_BEND (P5-0 gate iv: Stokes orders 2.14 / 2.09 on the flag bent to 80 mm)
Documentation / Build API Documentation (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
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 / 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_0116sg1Qz1gMv9hdcKP1XUam
This commit is contained in:
Omar Sobh
2026-09-07 07:16:53 -07:00
co-authored by Claude Fable 5.1
parent c2451fbacf
commit f0b2563bf8
6 changed files with 1076 additions and 41 deletions
@@ -11,23 +11,25 @@
#![allow(dead_code)] // several test crates share this; each uses a subset
pub mod march;
pub mod overset;
pub mod overset_march;
pub mod rescue;
use std::cell::Cell;
use std::sync::{Arc, RwLock};
use nalgebra::Vector3;
use rtx_cfd::CfdConfig;
use rtx_cfd::solvers::incompressible::{
AleBoundaries, ConvectionScheme, EmbeddedBody, EmbeddedParameters, EmbeddedPisoSolver,
FlowField, PoissonSolverKind, PolygonSdf, SideBoundary, polygon_interface_velocity,
polygon_signed_distance,
polygon_interface_velocity, polygon_signed_distance, AleBoundaries, ConvectionScheme,
EmbeddedBody, EmbeddedParameters, EmbeddedPisoSolver, FlowField, PoissonSolverKind, PolygonSdf,
SideBoundary,
};
use rtx_cfd::CfdConfig;
use rtx_fea::assembly::dof_mapping::DofComponent;
use rtx_fea::boundary::dirichlet::{DirichletBC, DirichletType};
use rtx_fea::boundary::{BoundaryCondition, BoundaryConditionSet, SpatialFunction};
use rtx_fea::mesh::{Element, ElementType, MaterialId, Mesh, Node, NodeId};
use rtx_fsi::{FluidFace, WettedSurface, smooth_tractions};
use rtx_fsi::{smooth_tractions, FluidFace, WettedSurface};
pub const L: f64 = 2.5;
pub const H: f64 = 0.41;
@@ -183,6 +185,12 @@ pub struct Interface {
/// Ordered boundary walk: indices into `wetted` (`usize::MAX` marks
/// the fixed anchor vertices inside the cylinder / at the clamp).
pub walk: Vec<(usize, (f64, f64))>,
/// The three wetted edges as indices into `wetted`: bottom (root →
/// tip), tip (bottom corner → top corner, corners included), top
/// (tip → root) — the P5 patch generator's input.
pub bottom: Vec<usize>,
pub tip: Vec<usize>,
pub top: Vec<usize>,
}
impl Interface {
@@ -246,10 +254,20 @@ impl Interface {
walk.push((usize::MAX, (0.22, FLAG_Y1)));
let reference = wetted.iter().map(|(_, p)| *p).collect();
let bottom_idx: Vec<usize> = bottom.iter().map(|(id, _)| index_of(*id)).collect();
// The tip edge with its corners: the last bottom node, the tip's
// interior nodes (sorted by y), the first top node.
let mut tip_idx: Vec<usize> = vec![*bottom_idx.last().expect("bottom edge")];
tip_idx.extend(tip.iter().map(|(id, _)| index_of(*id)));
let top_idx: Vec<usize> = top.iter().map(|(id, _)| index_of(*id)).collect();
tip_idx.push(*top_idx.first().expect("top edge"));
Self {
wetted: wetted.into_iter().map(|(id, _)| id).collect(),
reference,
walk,
bottom: bottom_idx,
tip: tip_idx,
top: top_idx,
}
}
@@ -283,6 +301,21 @@ impl Interface {
.collect()
}
/// The deformed wetted edges for the P5 patch generator, each edge
/// starting / ending at the clamp line's fixed corner.
pub fn edges(&self, d: &[f64]) -> rtx_cfd::mesh::patch_gen::FlagEdges {
let at = |k: usize| -> [f64; 2] {
let (x0, y0) = self.reference[k];
[x0 + d[2 * k], y0 + d[2 * k + 1]]
};
let mut bottom = vec![[FLAG_X0, FLAG_Y0]];
bottom.extend(self.bottom.iter().map(|&k| at(k)));
let tip: Vec<[f64; 2]> = self.tip.iter().map(|&k| at(k)).collect();
let mut top: Vec<[f64; 2]> = self.top.iter().map(|&k| at(k)).collect();
top.push([FLAG_X0, FLAG_Y1]);
rtx_cfd::mesh::patch_gen::FlagEdges { bottom, tip, top }
}
/// Deformed wetted node positions for the transfer.
pub fn deformed_nodes(&self, d: &[f64]) -> Vec<Vector3<f64>> {
self.reference