forked from 1b-agent/fieldcraft-upstream
fem: finite-strain material point, total Lagrangian elements and follower pressure
The material point interface returns the Kirchhoff stress and the spatial tangent of its Lie derivative from the deformation gradient, with per-point history committed by the solver: St Venant–Kirchhoff (pushed forward from S = D E) and the decoupled compressible neo-Hookean with its isochoric and volumetric parts. Total Lagrangian solids (tet4, tet10, wedge6, hex8, hex20 full and reduced) and plane strain and axisymmetric elements give internal forces and the consistent tangent with its geometric stiffness; hybrid solids use the Simo–Taylor–Pister three-field formulation on the existing pressure fields. Incompatible modes and plane stress are refused by name. Follower pressure on faces and 2D edges with its load stiffness. Every tangent is checked against central differences of its forces. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
1 parent
bc9fe2191a
commit
2321d75cc6
8 files changed
+1217
-16
No files matched your search
@@ -124,6 +124,55 @@ pub fn integrate_face(xyz: &[[f64; 3]], mut visit: impl FnMut(&[f64], [f64; 3]))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A quadrature point of a reference face or edge: the shape function values, their
|
||||
/// derivatives along the face's natural coordinates ξ and η (an edge has ξ only; its `deta` is
|
||||
/// empty) and the weight.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct QuadraturePoint {
|
||||
pub n: Vec<f64>,
|
||||
pub dxi: Vec<f64>,
|
||||
pub deta: Vec<f64>,
|
||||
pub weight: f64,
|
||||
}
|
||||
|
||||
/// The quadrature points of a face of `nodes` nodes (3, 4, 6 or 8), with the rule and shape
|
||||
/// functions of [`integrate_face`]: what a load on the deformed face (follower pressure)
|
||||
/// integrates with.
|
||||
pub fn face_points(nodes: usize) -> Result<Vec<QuadraturePoint>> {
|
||||
let (corners, shape): (usize, fn(usize, f64, f64) -> Shape) = match nodes {
|
||||
3 | 6 => (3, triangle),
|
||||
4 | 8 => (4, quadrilateral),
|
||||
n => return Err(Error::Invalid(format!("a face has 3, 4, 6 or 8 nodes, not {n}"))),
|
||||
};
|
||||
Ok(rule(corners)
|
||||
.into_iter()
|
||||
.map(|(xi, eta, weight)| {
|
||||
let s = shape(nodes, xi, eta);
|
||||
QuadraturePoint { n: s.n, dxi: s.dxi, deta: s.deta, weight }
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// The quadrature points of an element edge of `nodes` nodes (2 or 3), with the rule and shape
|
||||
/// functions of [`edge_normal_weights`].
|
||||
pub fn edge_points(nodes: usize) -> Result<Vec<QuadraturePoint>> {
|
||||
if !matches!(nodes, 2 | 3) {
|
||||
return Err(Error::Invalid(format!("an edge has 2 or 3 nodes, not {nodes}")));
|
||||
}
|
||||
let g = (0.6f64).sqrt();
|
||||
Ok([(-g, 5.0 / 9.0), (0.0, 8.0 / 9.0), (g, 5.0 / 9.0)]
|
||||
.into_iter()
|
||||
.map(|(s, weight)| {
|
||||
let (n, dn) = if nodes == 2 {
|
||||
(vec![(1.0 - s) / 2.0, (1.0 + s) / 2.0], vec![-0.5, 0.5])
|
||||
} else {
|
||||
(vec![s * (s - 1.0) / 2.0, s * (s + 1.0) / 2.0, 1.0 - s * s], vec![s - 0.5, s + 0.5, -2.0 * s])
|
||||
};
|
||||
QuadraturePoint { n, dxi: dn, deta: Vec::new(), weight }
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// ∫ Nᵢ n dA for every node of a face: the consistent nodal forces of a unit pressure pulling
|
||||
/// along the face's right-hand (outward, for solids) normal.
|
||||
pub fn face_normal_weights(xyz: &[[f64; 3]]) -> Result<Vec<[f64; 3]>> {
|
||||
|
||||
Reference in new issue
Block a user