simkit.energies.stable_neo_hookean#

Smith-Goes-Kim stable Neo-Hookean elastic energy.

Implements the final stable Neo-Hookean formulation from Smith, de Goes, and Kim, “Stable Neo-Hookean Flesh Simulation” (TOG / SIGGRAPH 2018): https://dl.acm.org/doi/10.1145/3180491

Per-element energy density:

psi(F) = (mu / 2) * (I_C - dim)
  • (mu / 2) * log(I_C + 1)

  • (lam / 2) * (det(F) - alpha)**2

alpha = 1 + dim * mu / ((dim + 1) * lam) (dim-dependent shift) I_C = ||F||_F**2 = sum_{i,j} F_{ij}**2

The alpha shift makes the rest configuration (F = I) a critical point of the energy: dpsi/dF |_{F=I} = 0. Unlike Macklin-Mueller, the rest energy psi(F=I) is a non-zero constant (this is a feature of the formulation, not a bug). The log term penalises shrink toward F = 0 without diverging there, so the energy remains finite even at collapsed configurations – the “stable” property of the paper.

Follows the standardized three-tier layout (see simkit.energies.arap for the reference). This energy has only the deformation gradient (F) representation, so there is no _S tier:

Element tier (*_element_F)

Per-element density and derivative blocks. Material parameters mu and lam only: no quadrature weight vol, no summation, no operator.

Global explicit tier (*_x)

Takes a prebuilt deformation Jacobian J and weights vol, calls the element tier, weights, and assembles.

Self-contained tier (no suffix)

Builds J and vol from rest geometry (X, T).

Notes

Closed-form gradient and Hessian derived symbolically by scripts/derive_stable_neo_hookean.py. The mat2py ordering helpers reindex from the column-major (MATLAB/C++) flat layout to the row-major F layout used throughout the library.

Functions#

stable_neo_hookean_energy_element_F(→ numpy.ndarray)

Per-element Smith-Goes-Kim stable Neo-Hookean energy density.

stable_neo_hookean_gradient_element_F(→ numpy.ndarray)

Per-element first Piola-Kirchhoff stress (gradient w.r.t. F).

stable_neo_hookean_hessian_element_F(→ numpy.ndarray)

Per-element Hessian of the density w.r.t. F (vectorized blocks).

stable_neo_hookean_energy_x(→ float)

Assembled stable Neo-Hookean energy at positions X.

stable_neo_hookean_gradient_x(→ numpy.ndarray)

Assembled stable Neo-Hookean gradient w.r.t. positions X.

stable_neo_hookean_hessian_x(→ scipy.sparse.spmatrix)

Assembled stable Neo-Hookean Hessian w.r.t. positions X.

stable_neo_hookean_energy_u(→ float)

Assembled stable Neo-Hookean energy at displacement u from a reference x_bar.

stable_neo_hookean_gradient_u(→ numpy.ndarray)

Assembled stable Neo-Hookean gradient w.r.t. displacement u.

stable_neo_hookean_hessian_u(→ scipy.sparse.spmatrix)

Assembled stable Neo-Hookean Hessian w.r.t. displacement u.

stable_neo_hookean_energy(→ float)

Stable Neo-Hookean energy, building the operator and weights from rest geometry.

stable_neo_hookean_gradient(→ numpy.ndarray)

Stable Neo-Hookean gradient, building the operator and weights from rest geometry.

stable_neo_hookean_hessian(→ scipy.sparse.spmatrix)

Stable Neo-Hookean Hessian, building the operator and weights from rest geometry.

Module Contents#

simkit.energies.stable_neo_hookean.stable_neo_hookean_energy_element_F(F: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray) numpy.ndarray#

Per-element Smith-Goes-Kim stable Neo-Hookean energy density.

Parameters:
  • F (np.ndarray (t, dim, dim)) – Per-element deformation gradients.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

Returns:

psi – Per-element energy densities. No quadrature weighting applied. Note: psi(F=I) is a non-zero constant; the rest state is a stationary point (gradient zero) but not the zero of the energy.

Return type:

np.ndarray (t, 1)

simkit.energies.stable_neo_hookean.stable_neo_hookean_gradient_element_F(F: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray) numpy.ndarray#

Per-element first Piola-Kirchhoff stress (gradient w.r.t. F).

Parameters:
  • F (np.ndarray (t, dim, dim)) – Per-element deformation gradients.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

Returns:

P – Per-element PK1 stress blocks. No quadrature weighting applied.

Return type:

np.ndarray (t, dim, dim)

simkit.energies.stable_neo_hookean.stable_neo_hookean_hessian_element_F(F: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray) numpy.ndarray#

Per-element Hessian of the density w.r.t. F (vectorized blocks).

Parameters:
  • F (np.ndarray (t, dim, dim)) – Per-element deformation gradients.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

Returns:

H – Per-element Hessian blocks in vectorized F layout. No quadrature weighting applied. Not PSD-projected; projection happens in the global tier.

Return type:

np.ndarray (t, dim*dim, dim*dim)

simkit.energies.stable_neo_hookean.stable_neo_hookean_energy_x(X: numpy.ndarray, J: scipy.sparse.spmatrix, mu: numpy.ndarray, lam: numpy.ndarray, vol: numpy.ndarray) float#

Assembled stable Neo-Hookean energy at positions X.

Parameters:
  • X (np.ndarray (n, dim)) – Current vertex positions.

  • J (scipy.sparse matrix (t*dim*dim, n*dim)) – Deformation Jacobian.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • vol (np.ndarray (t, 1)) – Per-element quadrature weights.

Returns:

E – Total stable Neo-Hookean energy.

Return type:

float

simkit.energies.stable_neo_hookean.stable_neo_hookean_gradient_x(X: numpy.ndarray, J: scipy.sparse.spmatrix, mu: numpy.ndarray, lam: numpy.ndarray, vol: numpy.ndarray) numpy.ndarray#

Assembled stable Neo-Hookean gradient w.r.t. positions X.

Parameters:
  • X (np.ndarray (n, dim)) – Current vertex positions.

  • J (scipy.sparse matrix (t*dim*dim, n*dim)) – Deformation Jacobian.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • vol (np.ndarray (t, 1)) – Per-element quadrature weights.

Returns:

g – Assembled energy gradient.

Return type:

np.ndarray (n*dim, 1)

simkit.energies.stable_neo_hookean.stable_neo_hookean_hessian_x(X: numpy.ndarray, J: scipy.sparse.spmatrix, mu: numpy.ndarray, lam: numpy.ndarray, vol: numpy.ndarray, psd: bool = True) scipy.sparse.spmatrix#

Assembled stable Neo-Hookean Hessian w.r.t. positions X.

Parameters:
  • X (np.ndarray (n, dim)) – Current vertex positions.

  • J (scipy.sparse matrix (t*dim*dim, n*dim)) – Deformation Jacobian.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • vol (np.ndarray (t, 1)) – Per-element quadrature weights.

  • psd (bool, optional) – If True (default), project each per-element block to the nearest positive semi-definite matrix before assembly.

Returns:

Q – Assembled energy Hessian.

Return type:

scipy.sparse.csc_matrix (n*dim, n*dim)

simkit.energies.stable_neo_hookean.stable_neo_hookean_energy_u(u: numpy.ndarray, J: scipy.sparse.spmatrix, Jx_bar: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray, vol: numpy.ndarray) float#

Assembled stable Neo-Hookean energy at displacement u from a reference x_bar.

Equivalent to stable_neo_hookean_energy_x() evaluated at x_bar + u but avoids recomputing J @ x_bar on every call. The reference x_bar is arbitrary (not required to be the rest pose).

Parameters:
  • u (np.ndarray (n, dim)) – Displacement from the reference configuration.

  • J (scipy.sparse matrix (t*dim*dim, n*dim)) – Deformation Jacobian.

  • Jx_bar (np.ndarray (t*dim*dim, 1)) – Precomputed J @ x_bar.reshape(-1, 1) – the flattened deformation gradient at the reference configuration.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • vol (np.ndarray (t, 1)) – Per-element quadrature weights.

Returns:

E – Total stable Neo-Hookean energy.

Return type:

float

simkit.energies.stable_neo_hookean.stable_neo_hookean_gradient_u(u: numpy.ndarray, J: scipy.sparse.spmatrix, Jx_bar: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray, vol: numpy.ndarray) numpy.ndarray#

Assembled stable Neo-Hookean gradient w.r.t. displacement u.

Because dF/du = J (the same as dF/dX), this returns the same assembled vector as stable_neo_hookean_gradient_x() at x_bar + u.

Parameters:
  • u (np.ndarray (n, dim)) – Displacement from the reference configuration.

  • J (scipy.sparse matrix (t*dim*dim, n*dim)) – Deformation Jacobian.

  • Jx_bar (np.ndarray (t*dim*dim, 1)) – Precomputed J @ x_bar.reshape(-1, 1).

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • vol (np.ndarray (t, 1)) – Per-element quadrature weights.

Returns:

g – Assembled energy gradient.

Return type:

np.ndarray (n*dim, 1)

simkit.energies.stable_neo_hookean.stable_neo_hookean_hessian_u(u: numpy.ndarray, J: scipy.sparse.spmatrix, Jx_bar: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray, vol: numpy.ndarray, psd: bool = True) scipy.sparse.spmatrix#

Assembled stable Neo-Hookean Hessian w.r.t. displacement u.

Parameters:
  • u (np.ndarray (n, dim)) – Displacement from the reference configuration.

  • J (scipy.sparse matrix (t*dim*dim, n*dim)) – Deformation Jacobian.

  • Jx_bar (np.ndarray (t*dim*dim, 1)) – Precomputed J @ x_bar.reshape(-1, 1).

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • vol (np.ndarray (t, 1)) – Per-element quadrature weights.

  • psd (bool, optional) – If True (default), project each per-element block to the nearest positive semi-definite matrix before assembly.

Returns:

Q – Assembled energy Hessian.

Return type:

scipy.sparse.csc_matrix (n*dim, n*dim)

simkit.energies.stable_neo_hookean.stable_neo_hookean_energy(X: numpy.ndarray, T: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray, U: numpy.ndarray | None = None) float#

Stable Neo-Hookean energy, building the operator and weights from rest geometry.

Parameters:
  • X (np.ndarray (n, dim)) – Rest vertex positions. Used to build J and vol.

  • T (np.ndarray (t, dim+1)) – Element connectivity.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • U (np.ndarray (n, dim), optional) – Current vertex positions. Defaults to X.

Returns:

E – Total stable Neo-Hookean energy.

Return type:

float

simkit.energies.stable_neo_hookean.stable_neo_hookean_gradient(X: numpy.ndarray, T: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray, U: numpy.ndarray | None = None) numpy.ndarray#

Stable Neo-Hookean gradient, building the operator and weights from rest geometry.

Parameters:
  • X (np.ndarray (n, dim)) – Rest vertex positions.

  • T (np.ndarray (t, dim+1)) – Element connectivity.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • U (np.ndarray (n, dim), optional) – Current vertex positions. Defaults to X.

Returns:

g – Assembled energy gradient.

Return type:

np.ndarray (n*dim, 1)

simkit.energies.stable_neo_hookean.stable_neo_hookean_hessian(X: numpy.ndarray, T: numpy.ndarray, mu: numpy.ndarray, lam: numpy.ndarray, U: numpy.ndarray | None = None, psd: bool = True) scipy.sparse.spmatrix#

Stable Neo-Hookean Hessian, building the operator and weights from rest geometry.

Parameters:
  • X (np.ndarray (n, dim)) – Rest vertex positions.

  • T (np.ndarray (t, dim+1)) – Element connectivity.

  • mu (np.ndarray (t, 1)) – Per-element shear modulus.

  • lam (np.ndarray (t, 1)) – Per-element first Lame parameter.

  • U (np.ndarray (n, dim), optional) – Current vertex positions. Defaults to X.

  • psd (bool, optional) – Project per-element blocks to PSD before assembly. Default True.

Returns:

Q – Assembled energy Hessian.

Return type:

scipy.sparse.csc_matrix (n*dim, n*dim)