R8-c: drop zero summands from cut_wall_loads; extrapolation diagnostics beyond FAR_OUTSIDE with the worst point
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9c2ae32061
commit
05bf4c74a0
@@ -79,18 +79,17 @@ impl Mask {
|
|||||||
if self.grad_weights.is_some() {
|
if self.grad_weights.is_some() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
// The loops visit every fluid cell and face; only the non-zero
|
||||||
|
// summands are loads (the zero ones change no sum).
|
||||||
let mut raw: Vec<(LoadKind, [f64; 3], [f64; 3])> = Vec::new();
|
let mut raw: Vec<(LoadKind, [f64; 3], [f64; 3])> = Vec::new();
|
||||||
let (p, s) = self
|
let mut keep = |k: LoadKind, x: [f64; 3], v: [f64; 3]| {
|
||||||
.cut_wall_force_parts_sink(body, f, mu, t, None, &mut |k, x, v| raw.push((k, x, v)))?;
|
if v != [0.0; 3] {
|
||||||
let (d, c) = self.cut_wall_exchange_parts_sink(
|
raw.push((k, x, v));
|
||||||
body,
|
}
|
||||||
f,
|
};
|
||||||
mu,
|
let (p, s) = self.cut_wall_force_parts_sink(body, f, mu, t, None, &mut keep)?;
|
||||||
self.density,
|
let (d, c) =
|
||||||
t,
|
self.cut_wall_exchange_parts_sink(body, f, mu, self.density, t, None, &mut keep)?;
|
||||||
None,
|
|
||||||
&mut |k, x, v| raw.push((k, x, v)),
|
|
||||||
)?;
|
|
||||||
let xch = [d[0] + c[0], d[1] + c[1], d[2] + c[2]];
|
let xch = [d[0] + c[0], d[1] + c[1], d[2] + c[2]];
|
||||||
let total = [
|
let total = [
|
||||||
p[0] + s[0] + xch[0],
|
p[0] + s[0] + xch[0],
|
||||||
@@ -209,6 +208,10 @@ pub struct Location {
|
|||||||
pub outside: f64,
|
pub outside: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The natural-coordinate distance outside an element from which a load
|
||||||
|
/// counts as extrapolated in [`PlateTransfer`] (0.02 of the half-element).
|
||||||
|
pub const FAR_OUTSIDE: f64 = 0.02;
|
||||||
|
|
||||||
/// The result of one load transfer (see [`HexPlate::transfer`]).
|
/// The result of one load transfer (see [`HexPlate::transfer`]).
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PlateTransfer {
|
pub struct PlateTransfer {
|
||||||
@@ -223,9 +226,13 @@ pub struct PlateTransfer {
|
|||||||
/// The largest Newton residual (m) and the largest outside-ness.
|
/// The largest Newton residual (m) and the largest outside-ness.
|
||||||
pub max_residual: f64,
|
pub max_residual: f64,
|
||||||
pub max_outside: f64,
|
pub max_outside: f64,
|
||||||
/// Loads located outside every element (extrapolated), and their Σ|F|.
|
/// Loads located outside every element by more than [`FAR_OUTSIDE`]
|
||||||
|
/// in natural coordinates (a foot off the plate by more than a few %
|
||||||
|
/// of an element — the surfaces' round-off-level mismatch is excluded),
|
||||||
|
/// their Σ|F|, and the worst one's point.
|
||||||
pub extrapolated: usize,
|
pub extrapolated: usize,
|
||||||
pub extrapolated_load: f64,
|
pub extrapolated_load: f64,
|
||||||
|
pub worst_point: [f64; 3],
|
||||||
/// The share of Σ|f_a| on nodes off the wetted surface (the interior
|
/// The share of Σ|f_a| on nodes off the wetted surface (the interior
|
||||||
/// layers and the clamped root face).
|
/// layers and the clamped root face).
|
||||||
pub interior_share: f64,
|
pub interior_share: f64,
|
||||||
@@ -481,6 +488,7 @@ impl HexPlate {
|
|||||||
let (mut force_in, mut moment_in) = ([0.0f64; 3], [0.0f64; 3]);
|
let (mut force_in, mut moment_in) = ([0.0f64; 3], [0.0f64; 3]);
|
||||||
let (mut max_residual, mut max_outside) = (0.0f64, f64::NEG_INFINITY);
|
let (mut max_residual, mut max_outside) = (0.0f64, f64::NEG_INFINITY);
|
||||||
let (mut extrapolated, mut extrapolated_load) = (0usize, 0.0f64);
|
let (mut extrapolated, mut extrapolated_load) = (0usize, 0.0f64);
|
||||||
|
let mut worst_point = [0.0f64; 3];
|
||||||
for (&(p, f), loc) in loads.iter().zip(&located) {
|
for (&(p, f), loc) in loads.iter().zip(&located) {
|
||||||
for (&n, &w) in loc.nodes.iter().zip(&loc.weights) {
|
for (&n, &w) in loc.nodes.iter().zip(&loc.weights) {
|
||||||
for c in 0..3 {
|
for c in 0..3 {
|
||||||
@@ -493,8 +501,11 @@ impl HexPlate {
|
|||||||
moment_in[c] += m[c];
|
moment_in[c] += m[c];
|
||||||
}
|
}
|
||||||
max_residual = max_residual.max(loc.residual);
|
max_residual = max_residual.max(loc.residual);
|
||||||
max_outside = max_outside.max(loc.outside);
|
if loc.outside > max_outside {
|
||||||
if loc.outside > 1e-9 {
|
max_outside = loc.outside;
|
||||||
|
worst_point = p;
|
||||||
|
}
|
||||||
|
if loc.outside > FAR_OUTSIDE {
|
||||||
extrapolated += 1;
|
extrapolated += 1;
|
||||||
extrapolated_load += norm(f);
|
extrapolated_load += norm(f);
|
||||||
}
|
}
|
||||||
@@ -524,6 +535,7 @@ impl HexPlate {
|
|||||||
max_outside,
|
max_outside,
|
||||||
extrapolated,
|
extrapolated,
|
||||||
extrapolated_load,
|
extrapolated_load,
|
||||||
|
worst_point,
|
||||||
interior_share: if total_abs > 0.0 {
|
interior_share: if total_abs > 0.0 {
|
||||||
interior_abs / total_abs
|
interior_abs / total_abs
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ pub use cut::CutGeometry;
|
|||||||
pub use export_vtk::write_vtk;
|
pub use export_vtk::write_vtk;
|
||||||
pub use field::Field;
|
pub use field::Field;
|
||||||
pub use grid::Grid;
|
pub use grid::Grid;
|
||||||
pub use interface::{HexPlate, LoadKind, PlateTransfer, WallLoad};
|
pub use interface::{FAR_OUTSIDE, HexPlate, LoadKind, PlateTransfer, WallLoad};
|
||||||
pub use loads::SurfaceForce;
|
pub use loads::SurfaceForce;
|
||||||
pub use plate::PlateSurface;
|
pub use plate::PlateSurface;
|
||||||
pub use step::{Boundaries, Fluid, Parameters, Side, Solver, StepResult};
|
pub use step::{Boundaries, Fluid, Parameters, Side, Solver, StepResult};
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ use embedded3_flag_kinematics::{Recorded, recorded};
|
|||||||
use rtx_cfd::solvers::incompressible::ConvectionScheme;
|
use rtx_cfd::solvers::incompressible::ConvectionScheme;
|
||||||
use rtx_cfd::solvers::incompressible::embedded3::step::device::DeviceStep;
|
use rtx_cfd::solvers::incompressible::embedded3::step::device::DeviceStep;
|
||||||
use rtx_cfd::solvers::incompressible::embedded3::{
|
use rtx_cfd::solvers::incompressible::embedded3::{
|
||||||
Body, Boundaries, DeviceSdf, Field, Fluid, Grid, HexPlate, Parameters, PlateSurface, Side,
|
Body, Boundaries, DeviceSdf, FAR_OUTSIDE, Field, Fluid, Grid, HexPlate, Parameters,
|
||||||
Solver, WallScheme, write_vtk,
|
PlateSurface, Side, Solver, WallScheme, write_vtk,
|
||||||
};
|
};
|
||||||
use std::io::Write as _;
|
use std::io::Write as _;
|
||||||
|
|
||||||
@@ -735,7 +735,7 @@ fn flag_wake_on_the_device() {
|
|||||||
let extrap_share = tr.extrapolated_load / abs_f.max(1e-300);
|
let extrap_share = tr.extrapolated_load / abs_f.max(1e-300);
|
||||||
let ms = lap.elapsed().as_secs_f64() * 1e3;
|
let ms = lap.elapsed().as_secs_f64() * 1e3;
|
||||||
println!(
|
println!(
|
||||||
" transfer t {t:.4}: {} loads ({} flag); route − Σ {:.1e} N; flag F {:+.4} {:+.4} {:+.4} N, M {:+.5} {:+.5} {:+.5} N m; |ΔF|/Σ|F| {rel_f:.1e}, |ΔM|/(Σ|F| L) {rel_m:.1e}; Newton ≤ {:.1e} m, outside ≤ {:.2e} ({} extrapolated, {:.1e} of Σ|F|), interior share {:.3}; {ms:.0} ms",
|
" transfer t {t:.4}: {} loads ({} flag); route − Σ {:.1e} N; flag F {:+.4} {:+.4} {:+.4} N, M {:+.5} {:+.5} {:+.5} N m; |ΔF|/Σ|F| {rel_f:.1e}, |ΔM|/(Σ|F| L) {rel_m:.1e}; Newton ≤ {:.1e} m, outside ≤ {:.2e} at ({:.4}, {:.4}, {:.4}) ({} beyond {FAR_OUTSIDE}, {:.1e} of Σ|F|), interior share {:.3}; {ms:.0} ms",
|
||||||
loads.len(),
|
loads.len(),
|
||||||
flag.len(),
|
flag.len(),
|
||||||
nrm([route[0] - sum[0], route[1] - sum[1], route[2] - sum[2]]),
|
nrm([route[0] - sum[0], route[1] - sum[1], route[2] - sum[2]]),
|
||||||
@@ -747,6 +747,9 @@ fn flag_wake_on_the_device() {
|
|||||||
tr.moment_in[2],
|
tr.moment_in[2],
|
||||||
tr.max_residual,
|
tr.max_residual,
|
||||||
tr.max_outside,
|
tr.max_outside,
|
||||||
|
tr.worst_point[0],
|
||||||
|
tr.worst_point[1],
|
||||||
|
tr.worst_point[2],
|
||||||
tr.extrapolated,
|
tr.extrapolated,
|
||||||
extrap_share,
|
extrap_share,
|
||||||
tr.interior_share
|
tr.interior_share
|
||||||
|
|||||||
Reference in New Issue
Block a user