Skip to main content

hyper-surrogate

Release Build status codecov License

Define hyperelastic materials in Python, deploy them in your finite element solver.

Table of Contents

Why hyper-surrogate?

Finite element solvers need constitutive models. Writing and maintaining those models — especially user-material subroutines for Abaqus, FEAP and similar Fortran-based solvers — is repetitive: kinematics, second Piola–Kirchhoff stress, consistent tangent, Jaumann correction, reference-configuration freedom, all in Fortran 77 or 90.

hyper-surrogate lets you define your material once in Python and emit a self-contained Fortran 90 user subroutine deployable in any Fortran-based FE solver. You choose how the material is defined:

  1. Built-in symbolic SEF — one of ten classical isotropic and anisotropic models (Neo-Hooke, Mooney-Rivlin, Yeoh, Holzapfel-Ogden, Gasser-Ogden-Holzapfel, …).
  2. Custom symbolic SEF — subclass Material with a sef property in SymPy and the framework derives stress and tangent automatically.
  3. Data-driven surrogate — train an MLP, ICNN, or polyconvex ICNN on energy and stress samples from any ground-truth source and emit a hybrid UMAT whose energy is the trained network and whose stress and tangent are computed analytically in Fortran.

All three paths produce the same artefact: a .f90 with Cauchy stress, analytical consistent tangent, and stress-freedom at the reference configuration enforced exactly at emission time. No Python runtime is required at solve time.

Architecture

Material ─> DeformationGenerator ─> Dataset ─> MLP / ICNN ─> HybridUMATEmitter ─> .f90
   │                                              │
   │         (symbolic SEF)                        │  (trained NN weights)
   │                                              │
   └──── UMATHandler ─────────────────────────────┘
         (analytical Fortran via SymPy CSE)

Features

  • Three entry points, one output — built-in SEF, custom SymPy SEF, or trained surrogate, all emit a structurally identical Fortran UMAT.
  • Symbolic mechanics — automatic PK2 stress and stiffness tensor derivation via SymPy; analytical Cauchy push-forward and Jaumann correction emitted with common-subexpression elimination.
  • NN architectures — MLP, Input-Convex NN, and polyconvex ICNN, trained with an energy-plus-stress dual loss that backpropagates the gradient target through autograd.
  • Hybrid UMAT — neural-network strain energy with closed-form analytical kinematics, stress, and consistent tangent in Fortran; layer-additive Hessian backpropagation verified against autograd at $10^{-5}$ tolerance.
  • Stress freedom at reference — enforced exactly at emission time by subtracting a compile-time offset; no surprise residual stress at $\mathbf{C} = \mathbf{I}$.
  • Anisotropic support — fiber pseudo-invariants $I_4, I_5$ for one or two fiber families with arbitrary orientations.

Quick Start

Three short pipelines, mirroring the three ways to define a material:

Path A — built-in symbolic SEF

from hyper_surrogate import NeoHooke, UMATHandler

UMATHandler(NeoHooke({"C10": 0.5, "KBULK": 1000.0})).generate("neohooke.f90")

Path B — custom user-defined SEF

import sympy as sp
from hyper_surrogate import Material, UMATHandler

class MyOgdenLike(Material):
    DEFAULT_PARAMS = {"mu": 1.0, "alpha": 2.0, "KBULK": 1000.0}

    def __init__(self, parameters=None):
        super().__init__({**self.DEFAULT_PARAMS, **(parameters or {})})

    @property
    def sef(self):
        h = self._handler
        mu, alpha, K = (self._symbols[k] for k in ("mu", "alpha", "KBULK"))
        return ((mu / alpha) * (h.isochoric_invariant1 ** (alpha / 2) - 3)
                + 0.5 * K * (sp.sqrt(h.invariant3) - 1) ** 2)

UMATHandler(MyOgdenLike()).generate("mysef.f90")

Path C — data-driven surrogate

from hyper_surrogate import (
    NeoHooke, MLP, Trainer, EnergyStressLoss,
    create_datasets, extract_weights, HybridUMATEmitter,
)

material = NeoHooke({"C10": 0.5, "KBULK": 1000.0})
train_ds, val_ds, in_norm, energy_norm = create_datasets(
    material, n_samples=4000, input_type="invariants",
    target_type="energy", deformation_mode="combined_compressible",
)
model = MLP(input_dim=3, output_dim=1, hidden_dims=[64, 64, 64], activation="softplus")
result = Trainer(model, train_ds, val_ds,
                 loss_fn=EnergyStressLoss(alpha=1.0, beta=1.0),
                 max_epochs=2000, patience=200).fit()
exported = extract_weights(result.model, in_norm, energy_norm)
HybridUMATEmitter(exported).write("neohooke_hybrid.f90")

See the documentation for the full tutorial set, including custom materials, anisotropic models, and the export-path decision tree.

Installation

pip install hyper-surrogate        # core (NumPy, SymPy)
pip install hyper-surrogate[ml]    # with PyTorch for ML surrogates

From source with uv:

git clone https://github.com/jpsferreira/hyper-surrogate.git
cd hyper-surrogate
uv sync --all-groups --extra ml

Examples

Runnable scripts are in the examples/ directory:

Script Path Description
analytical_umat.py A Built-in NeoHooke → analytical UMAT via UMATHandler
custom_sef.py B Custom Ogden-like SEF → analytical UMAT
export_hybrid_umat.py C End-to-end train + HybridUMATEmitter export
train_neohooke_sef.py C Train MLP on NeoHooke SEF with hybrid inference
train_icnn_energy.py C Train ICNN with EnergyStressLoss
train_polyconvex.py C Train PolyconvexICNN with per-invariant convexity
train_holzapfel_ogden.py C Anisotropic fiber-reinforced training pipeline

Run any example with:

uv run python examples/<script>.py

Contributing

Contributions are welcome! See CONTRIBUTING.md for setup instructions and guidelines.

Release files for hyper-surrogate 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hyper-surrogate 0.4.0
File Size Uploaded
hyper_surrogate-0.4.0.tar.gz 310.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hyper-surrogate 0.4.0
File Interpreter ABI Platform
hyper_surrogate-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 372.3 kB

Release files / hyper_surrogate-0.4.0.tar.gz

Download URL hyper_surrogate-0.4.0.tar.gz
Size 310.1 kB
Tags Source
SHA-256 checksum
How to use checksums
df7ee90e17b7c841b791c728df76e6e3dfdca8e211a1e5c5248ba3fed3f92cfd
BLAKE2b-256 checksum
How to use checksums
5300bc450bb455ee37c941b9b34bed03e444b538296b162edb1c3f6e47bc4fbf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / hyper_surrogate-0.4.0-py3-none-any.whl

Download URL hyper_surrogate-0.4.0-py3-none-any.whl
Size 62.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
33637e243bc081ee900ac1bd7e0aa4702262df397f88b8c5567a18255301da45
BLAKE2b-256 checksum
How to use checksums
8a1888f06d4bde57ae492e7d07f973e3e22758d1483f3c9c692d1da3f00b3bfa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page