forked from 1b-agent/fieldcraft-upstream
2D elements: plane stress, plane strain and axisymmetric sections on the DOF framework; mesh.planar (M4) (#39)
Model: planar section kinds with Extent, element edges in sets, edge-weighted 2D loads,
centrifugal load, 2D model checks. fem: Plane kernels on Basis::{Tri3,Tri6,Quad4,Quad8}
declaring ElementDofs::new(DofSet::PLANE); QM6 incompatible modes with the
Wilson-Ibrahimbegovic correction. Solver: Kernel enum on the DofLayout; 3D results
bit-identical (hash-checked). Decks: Abaqus CPS/CPE/CAX, Nastran membranes and RFORCE,
LS-DYNA ELFORM 12/13. Mesh: free triangle mesher, planar region meshing, face boundaries.
Engine: mesh.planar with tagged edges. Analytic verification suite in solver/tests/plane.rs.
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
42 files changed
+3270
-128
No files matched your search
@@ -537,3 +537,34 @@ fn unsmoothed_meshes_are_valid() {
|
||||
let m = free_quad_mesh(&loops, &UniformSize(0.2), &QuadOptions { smoothing_sweeps: 0, ..opts() }).unwrap();
|
||||
check(&m, &loops);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn free_triangle_mesh_of_a_plate_with_a_hole() {
|
||||
// Odd point counts are fine for triangles.
|
||||
let outer = rect(0.0, 0.0, 10.0, 6.0, 9, 5);
|
||||
let hole: Vec<[f64; 2]> = circle(4.0, 3.0, 1.5, 17).into_iter().rev().collect();
|
||||
let loops = vec![outer.clone(), hole.clone()];
|
||||
let m = free_tri_mesh(&loops, &UniformSize(0.7), &opts()).unwrap();
|
||||
assert_eq!(m.boundary_nodes, outer.len() + hole.len());
|
||||
let boundary: Vec<[f64; 2]> = outer.iter().chain(&hole).copied().collect();
|
||||
assert_eq!(&m.nodes[..m.boundary_nodes], boundary.as_slice(), "boundary nodes are the input points");
|
||||
let area: f64 = m
|
||||
.triangles
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let [a, b, c] = t.map(|v| m.nodes[v as usize]);
|
||||
let s = 0.5 * ((b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]));
|
||||
assert!(s > 0.0, "counterclockwise");
|
||||
s
|
||||
})
|
||||
.sum();
|
||||
let want = signed_area(&outer).abs() - signed_area(&hole).abs();
|
||||
assert!((area - want).abs() < 1e-9 * want, "{area} vs {want}");
|
||||
assert!(m.triangles.len() > 100, "refined to the size: {}", m.triangles.len());
|
||||
// Deterministic.
|
||||
assert_eq!(free_tri_mesh(&loops, &UniformSize(0.7), &opts()).unwrap(), m);
|
||||
// Hostile.
|
||||
assert!(free_tri_mesh(&[vec![[0.0, 0.0], [1.0, 0.0]]], &UniformSize(0.5), &opts()).is_err());
|
||||
assert!(free_tri_mesh(std::slice::from_ref(&outer), &UniformSize(0.001), &QuadOptions { max_elements: 100, ..opts() }).is_err());
|
||||
assert!(free_tri_mesh(&[vec![[0.0, 0.0], [f64::NAN, 0.0], [0.0, 1.0]]], &UniformSize(0.5), &opts()).is_err());
|
||||
}
|
||||
Reference in new issue
Block a user