hermit.fenics.kinematics

Basis transformations and Voigt notation for the R-M shell.

Ported from femo_alpha/rm_shell/linear_shell_fenicsx/kinematics.py (dev_coupling). Unchanged across DOLFINx 0.9 / 0.11 – these are pure UFL. Note there is no gradx / J / F: geometry sensitivity comes from differentiating w.r.t. SpatialCoordinate directly, so all gradients here are plain ufl.grad on the (possibly moved) mesh.

Functions

congruent_transform(T, X)

T^T X T for square UFL matrices (T orthogonal, X symmetric) --

constant_normal_bending_curvature(theta, E01)

Shallow-shell curvature with the cell normal held constant.

global_to_local_inplane(E0, E1)

2x3 change-of-basis matrix T; T[i, j] is the j-th component of the i-th basis vector.

gradv_local(gradv_global, T)

In-plane components of a rank-2 tensor in the local orthonormal frame.

local_basis_inplane(mesh)

Local orthonormal shell basis (E0, E1 in-plane; E2 = element normal).

membrane_strain(u_mid, E01)

Mid-surface membrane strain in the local in-plane frame.

orientation_cos_sin(fiber_angle, fiber_direction, E0, ...)

(cos theta, sin theta) of the in-plane angle from the element E0 to the

shear_rotation(c, s)

R(theta) -- 2x2 transverse-shear rotation, element -> laminate axes, standard

strain2D_local_to_global(strain_local, T)

2x2 local in-plane strain -> 3x3 global Cartesian tensor.

strain_rotation(c, s)

Teps(theta) -- 3x3 engineering-Voigt in-plane strain/curvature rotation,

unit(v)

Normalize the vector v.

vec2D_local_to_global(v_local, T)

length-2 local in-plane vector -> length-3 global Cartesian vector.

voigt2D(T[, strain])

2x2 symmetric tensor -> Voigt vector. strain doubles the shear component.

voigt3D(T[, strain])

3x3 symmetric tensor -> length-6 Voigt vector [xx, yy, zz, yz, xz, xy].

Module Contents

hermit.fenics.kinematics.congruent_transform(T, X)

T^T X T for square UFL matrices (T orthogonal, X symmetric) – rotates a laminate-axes constitutive matrix into the element frame, A_element = Teps^T A Teps (and As_element = R^T As R). Index notation (not ufl.transpose(T) * X * T) so it is unambiguous for any square size.

hermit.fenics.kinematics.constant_normal_bending_curvature(theta, E01)

Shallow-shell curvature with the cell normal held constant.

Only the rotation gradient enters. In particular, a rigid rotation is a constant theta and therefore has zero curvature structurally, including on a warped quadrilateral cell.

hermit.fenics.kinematics.global_to_local_inplane(E0, E1)

2x3 change-of-basis matrix T; T[i, j] is the j-th component of the i-th basis vector.

hermit.fenics.kinematics.gradv_local(gradv_global, T)

In-plane components of a rank-2 tensor in the local orthonormal frame.

hermit.fenics.kinematics.local_basis_inplane(mesh)

Local orthonormal shell basis (E0, E1 in-plane; E2 = element normal).

E0 is aligned with the 0-th parametric coordinate direction.

hermit.fenics.kinematics.membrane_strain(u_mid, E01)

Mid-surface membrane strain in the local in-plane frame.

hermit.fenics.kinematics.orientation_cos_sin(fiber_angle, fiber_direction, E0, E1, E2)

(cos theta, sin theta) of the in-plane angle from the element E0 to the fibre direction – from fiber_angle directly, or projected from a global fiber_direction vector (no atan2: it is more expensive and puts a branch cut at +/-pi right in the differentiated path). Exactly one of fiber_angle / fiber_direction must be given.

Degenerate only when fiber_direction is parallel to the shell normal E2 (the tangent-plane projection vanishes) – a UFL expression cannot raise, so callers must guard that numerically, with concrete values, before building the form.

hermit.fenics.kinematics.shear_rotation(c, s)

R(theta) – 2x2 transverse-shear rotation, element -> laminate axes, standard FSDT Voigt (xz, yz) ordering: gam_L = R @ gamma.

hermit.fenics.kinematics.strain2D_local_to_global(strain_local, T)

2x2 local in-plane strain -> 3x3 global Cartesian tensor.

hermit.fenics.kinematics.strain_rotation(c, s)

Teps(theta) – 3x3 engineering-Voigt in-plane strain/curvature rotation, element -> laminate axes: eps_L = Teps @ voigt2D(eps). Teps^T == Tsig^-1 for this convention (the identity hermit.csdl_helpers.rotate_abd also uses).

hermit.fenics.kinematics.unit(v)

Normalize the vector v.

hermit.fenics.kinematics.vec2D_local_to_global(v_local, T)

length-2 local in-plane vector -> length-3 global Cartesian vector.

hermit.fenics.kinematics.voigt2D(T, strain=True)

2x2 symmetric tensor -> Voigt vector. strain doubles the shear component.

hermit.fenics.kinematics.voigt3D(T, strain=True)

3x3 symmetric tensor -> length-6 Voigt vector [xx, yy, zz, yz, xz, xy]. strain doubles the three shear components (engineering convention, matching voigt2D()).