fem: pyramid5 element (solver, quality, decks, VTK)

A five-node pyramid, the conforming transition between a hexahedron's face
and tetrahedra: Bedrosian's rational shape functions with a collapsed (Duffy)
Gauss rule, a certified Jacobian on the base square with exact volume, a
scaled Jacobian, C3D5 / CPYRAM / LS-DYNA degenerate solid, VTK_PYRAMID and
the binary mesh code 13. A distorted hex8-pyramid5-tet4 transition mesh
passes the patch test and uniaxial tension exactly.

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-16 12:48:01 -04:00
1 parent 4e6fd59409
commit 3a5a8213a1
28 files changed
+325 -28

No files matched your search

+15 -2
View File
@@ -47,6 +47,7 @@ use crate::{Error, Result};
pub enum Family {
Tetrahedron,
Wedge,
Pyramid,
Hexahedron,
/// The 2D elements of plane and axisymmetric models ([`crate::plane`]).
Triangle,
@@ -74,7 +75,7 @@ pub struct ElementType {
}
/// The element table.
pub static ELEMENT_TYPES: [ElementType; 5] = [
pub static ELEMENT_TYPES: [ElementType; 6] = [
ElementType {
kind: ElementKind::Tet4,
family: Family::Tetrahedron,
@@ -108,6 +109,17 @@ pub static ELEMENT_TYPES: [ElementType; 5] = [
mass: Rule::Wedge,
incompatible_modes: false,
},
ElementType {
kind: ElementKind::Pyramid5,
family: Family::Pyramid,
nodes: 5,
corners: 5,
shape: shape::pyramid5,
full: Rule::Pyramid(2),
reduced: None,
mass: Rule::Pyramid(3),
incompatible_modes: false,
},
ElementType {
kind: ElementKind::Hex8,
family: Family::Hexahedron,
@@ -137,7 +149,7 @@ pub fn element_type(kind: ElementKind) -> Result<&'static ElementType> {
ELEMENT_TYPES
.iter()
.find(|t| t.kind == kind)
.ok_or_else(|| Error::NotSupported(format!("{} elements (the solver has tet4, tet10, wedge6, hex8 and hex20 so far)", kind.name())))
.ok_or_else(|| Error::NotSupported(format!("{} elements (the solver has tet4, tet10, wedge6, pyramid5, hex8 and hex20 so far)", kind.name())))
}
/// How a solid element is formulated.
@@ -730,6 +742,7 @@ pub fn extrapolation(ty: &ElementType, rule: Rule) -> Result<Extrapolation> {
let corner_basis = |xi: [f64; 3]| match ty.family {
Family::Tetrahedron => shape::tet4(xi),
Family::Wedge => shape::wedge6(xi),
Family::Pyramid => shape::pyramid5(xi),
Family::Hexahedron => shape::hex8(xi),
Family::Triangle => Basis::Tri3.eval(xi),
Family::Quadrilateral => Basis::Quad4.eval(xi),