solver: tie weights and constraint reduction independent of the structural mesh (#358)

The tie's mortar rows take any node numbering and degree-of-freedom kinds, and
Reduction takes a DofLayout, so heat transfer can reuse both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 08:27:01 -04:00
1 parent 507e8e32d2
commit 0ec1882697
4 files changed
+105 -49

No files matched your search

+7 -1
View File
@@ -321,6 +321,12 @@ fn volume(kind: ElementKind, x: &[Vec3]) -> Option<f64> {
}
}
/// The depth of element `kind` (corners `element`) under its face or edge `x` of measure `area`:
/// the element's volume over the area, or the face's size where the volume is unknown.
pub(crate) fn thickness(kind: ElementKind, element: &[Vec3], x: &[Vec3], area: f64) -> f64 {
volume(kind, element).filter(|v| *v > 0.0 && area > 0.0).map_or(size(x), |v| v / area)
}
/// The overlap integration of a face pair (`extent`: `None`) or an edge pair of a 2D model.
fn overlap<T: Real>(extent: Option<Extent>, xs: &[[T; 3]], xm: &[[T; 3]], f: impl FnMut(&Sample<T>)) -> Option<()> {
match extent {
@@ -420,7 +426,7 @@ fn surface_face(mesh: &Mesh, owner: &str, element: u32, labels: Vec<u32>, edge:
[a, b] if edge => norm([b[0] - a[0], b[1] - a[1], 0.0]),
_ => area_vector(&x).map_or(0.0, norm),
};
let thickness = volume(el.kind, &el.xyz).filter(|v| *v > 0.0 && area > 0.0).map_or(size(&x), |v| v / area);
let thickness = thickness(el.kind, &el.xyz, &x, area);
if !(thickness > 0.0 && thickness.is_finite()) {
return Err(at(format!("the {} has no size", if edge { "edge" } else { "face" })));
}