+
Skip to content

Add Total-Lagrange and Updated-Lagrange decorators for JAX #883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Nov 3, 2024
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ All notable changes to this project will be documented in this file. The format
- Add `math.inplane(A, vectors)` to return the in-plane components of a symmetric tensor `A`, where the plane is defined by its standard unit vectors.
- Add `constitution.jax.Hyperelastic` as a feature-equivalent alternative to `Hyperelastic` with `jax` as backend.
- Add `constitution.jax.Material` as a feature-equivalent alternative to `MaterialAD` with `jax` as backend.
- Add the MORPH-material formulation for a JAX-based material `felupe.constitution.jax.models.lagrange.morph()`.
- Add the material models for JAX-based materials `felupe.constitution.jax.models.hyperelastic.mooney_rivlin()`, `felupe.constitution.jax.models.hyperelastic.yeoh()`, `felupe.constitution.jax.models.hyperelastic.third_order_deformation()` and `felupe.constitution.jax.models.lagrange.morph()`.
- Add `felupe.constitution.jax.total_lagrange()` and `felupe.constitution.jax.updated_lagrange()` function decorators for JAX materials.

### Changed
- Change default `np.einsum(..., order="K")` to `np.einsum(..., order="C")` in the methods of `Field`, `FieldAxisymmetric`, `FieldPlaneStrain` and `FieldContainer`.
Expand Down
22 changes: 22 additions & 0 deletions docs/felupe/constitution/autodiff/jax.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ This page contains material model formulations with automatic differentiation us

constitution.jax.Hyperelastic
constitution.jax.Material
constitution.jax.total_lagrange
constitution.jax.updated_lagrange

**Material Models for** :class:`felupe.constitution.jax.Hyperelastic`

These material model formulations are defined by a strain energy density function.

.. autosummary::

felupe.constitution.jax.models.hyperelastic.mooney_rivlin
felupe.constitution.jax.models.hyperelastic.third_order_deformation
felupe.constitution.jax.models.hyperelastic.yeoh

**Material Models for** :class:`felupe.constitution.jax.Material`

Expand All @@ -38,6 +50,16 @@ This page contains material model formulations with automatic differentiation us
:undoc-members:
:inherited-members:

.. autofunction:: felupe.constitution.jax.total_lagrange

.. autofunction:: felupe.constitution.jax.updated_lagrange

.. autofunction:: felupe.constitution.jax.models.hyperelastic.mooney_rivlin

.. autofunction:: felupe.constitution.jax.models.hyperelastic.third_order_deformation

.. autofunction:: felupe.constitution.jax.models.hyperelastic.yeoh

.. autofunction:: felupe.constitution.jax.models.lagrange.morph

.. autofunction:: felupe.constitution.jax.vmap
1 change: 1 addition & 0 deletions docs/tutorial/examples/extut01_getting_started.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
created on the mesh. A vector-valued displacement field is initiated on the region.
Next, a field container is created on top of the displacement field.
"""

import felupe as fem

mesh = fem.Cube(n=6)
Expand Down
1 change: 1 addition & 0 deletions docs/tutorial/examples/extut02_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
argument of the (nearly) incompressible solid body instead of the constitutive
Neo-Hookean material definition.
"""

import felupe as fem

mesh = fem.Cube(n=6)
Expand Down
1 change: 1 addition & 0 deletions docs/tutorial/examples/extut03_building_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
.. image:: examples/extut03_building_blocks_sketch.svg
:width: 600px
"""

# sphinx_gallery_thumbnail_number = -1
import felupe as fem

Expand Down
1 change: 1 addition & 0 deletions examples/ex02_plate-with-hole.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
.. image:: ../../examples/ex02_plate-with-hole_sketch.svg
:width: 400px
"""

# sphinx_gallery_thumbnail_number = -2
h = 1
L = 2
Expand Down
1 change: 1 addition & 0 deletions examples/ex03_plasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
per axis. A three-dimensional vector-valued displacement field is initiated on the
numeric region.
"""

import numpy as np

import felupe as fem
Expand Down
1 change: 1 addition & 0 deletions examples/ex04_balloon.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
\text{tr}(\boldsymbol{C}) - \ln(\det(\boldsymbol{C}))
\right)
"""

# sphinx_gallery_thumbnail_number = -1
import contique
import numpy as np
Expand Down
1 change: 1 addition & 0 deletions examples/ex05_rubber-metal-bushing.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
An elastic bearing is subjected to combined multiaxial radial-torsional-cardanic
loading. First the meshes for the rubber and the metal sheet rings are created.
"""

# sphinx_gallery_thumbnail_number = -2
import numpy as np
import pypardiso
Expand Down
1 change: 1 addition & 0 deletions examples/ex06_rubber-metal-spring.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
Simplified elastic-to-rigid contact definitions simulate the end stops caused by steel
plates at the bottom and the top in direction :math:`z`.
"""

# sphinx_gallery_thumbnail_number = -3
import numpy as np
import pypardiso
Expand Down
1 change: 1 addition & 0 deletions examples/ex07_engine-mount.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* a `mesh for the air <../_static/ex07_engine-mount_mesh-air.vtk>`_ inside the
engine mount.
"""

# sphinx_gallery_thumbnail_number = -1
import numpy as np

Expand Down
1 change: 1 addition & 0 deletions examples/ex08_shear.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
:attr:`Mesh.points_without_cells` and adds them to the list of inactive
degrees of freedom. Hence, we have to drop our MPC-centerpoint from that list.
"""

# sphinx_gallery_thumbnail_number = -2
import numpy as np

Expand Down
1 change: 1 addition & 0 deletions examples/ex11_notch-stress.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
implemented and hence, the quadratic wedges in the mesh are converted to quadratic
hexahedrons.
"""

# sphinx_gallery_thumbnail_number = -1
import numpy as np
import pypardiso
Expand Down
1 change: 1 addition & 0 deletions examples/ex13_morph-rubber-wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
variables are stored in the solid body.

"""

# sphinx_gallery_thumbnail_number = -1
# sphinx_gallery_start_ignore
PYVISTA_GALLERY_FORCE_STATIC_IN_DOCUMENT = True
Expand Down
1 change: 1 addition & 0 deletions examples/ex14_hyperelasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
The :func:`Extended Tube <felupe.extended_tube>` material model formulation [1]_ is
best-fitted on Treloar's uniaxial and biaxial tension data [2]_.
"""

import numpy as np
import tensortrax.math as tm

Expand Down
1 change: 1 addition & 0 deletions examples/ex15_hexmesh-metacone.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

* create a :class:`~felupe.MeshContainer` for meshes associated to two materials
"""

import numpy as np

import felupe as fem
Expand Down
1 change: 1 addition & 0 deletions examples/ex16_deeplearning-torch.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

pip install torch
"""

# sphinx_gallery_thumbnail_number = -1
import numpy as np

Expand Down
1 change: 1 addition & 0 deletions examples/ex20_third-medium-contact.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
body. All sub meshes are merged by stacking the meshes of the
:class:`mesh container <felupe.MeshContainer>` into a :class:`mesh <felupe.Mesh>`.
"""

import numpy as np

import felupe as fem
Expand Down
11 changes: 10 additions & 1 deletion src/felupe/constitution/jax/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,14 @@
from ._hyperelastic import Hyperelastic
from ._material import Material
from ._tools import vmap
from ._total_lagrange import total_lagrange
from ._updated_lagrange import updated_lagrange

__all__ = ["Hyperelastic", "Material", "models", "vmap"]
__all__ = [
"Hyperelastic",
"Material",
"models",
"total_lagrange",
"updated_lagrange",
"vmap",
]
78 changes: 78 additions & 0 deletions src/felupe/constitution/jax/_total_lagrange.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
"""
This file is part of FElupe.

FElupe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

FElupe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FElupe. If not, see <http://www.gnu.org/licenses/>.
"""
from functools import wraps


def total_lagrange(material):
r"""Decorate a second Piola-Kirchhoff stress Total-Lagrange material formulation as
a first Piola-Kirchoff stress function.

Notes
-----
.. math::

\delta \psi = \boldsymbol{F} \boldsymbol{S} : \delta \boldsymbol{F}

Examples
--------
>>> import felupe as fem
>>> import felupe.constitution.jax as mat
>>> import jax.numpy as jnp
>>>
>>> @mat.total_lagrange
>>> def neo_hooke_total_lagrange(F, mu=1):
>>> C = F.T @ F
>>> dev = lambda C: C - jnp.trace(C) / 3 * jnp.eye(3)
>>> S = mu * dev(jnp.linalg.det(C)**(-1/3) * C) @ jnp.linalg.inv(C)
>>> return S
>>>
>>> umat = mat.Material(neo_hooke_total_lagrange, mu=1)

See Also
--------
felupe.constitution.jax.Hyperelastic : A hyperelastic material definition with a
given function for the strain energy density function per unit undeformed volume
with Automatic Differentiation provided by jax.
felupe.constitution.jax.Material : A material definition with a given function for
the partial derivative of the strain energy function w.r.t. the deformation
gradient tensor with Automatic Differentiation provided by jax.
"""
from jax import Array

@wraps(material)
def first_piola_kirchhoff_stress(F, *args, **kwargs):
# evaluate the second Piola-Kirchhoff stress
res = material(F, *args, **kwargs)

# check if the material formulation returns state variables and extract
# the second Piola-Kirchhoff stress tensor
if isinstance(res, Array):
S = res
statevars_new = None
else:
S, statevars_new = res

# first Piola-Kirchhoff stress tensor
P = F @ S

if statevars_new is None:
return P
else:
return P, statevars_new

return first_piola_kirchhoff_stress
81 changes: 81 additions & 0 deletions src/felupe/constitution/jax/_updated_lagrange.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
"""
This file is part of FElupe.

FElupe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

FElupe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FElupe. If not, see <http://www.gnu.org/licenses/>.
"""
from functools import wraps


def updated_lagrange(material):
r"""Decorate a Cauchy-stress Updated-Lagrange material formulation as a first Piola-
Kirchoff stress function.

Notes
-----
.. math::

\delta \psi = J \boldsymbol{\sigma} \boldsymbol{F}^{-T} : \delta \boldsymbol{F}

Examples
--------
>>> import felupe as fem
>>> import felupe.constitution.jax as mat
>>> import jax.numpy as jnp
>>>
>>> @fem.updated_lagrange
>>> def neo_hooke_updated_lagrange(F, mu=1):
>>> J = jnp.linalg.det(F)
>>> b = F @ F.T
>>> dev = lambda b: b - jnp.trace(b) / 3 * jnp.eye(3)
>>> τ = mu * dev(J**(-2/3) * b)
>>> return τ / J
>>>
>>> umat = mat.Material(neo_hooke_updated_lagrange, mu=1)

See Also
--------
felupe.constitution.jax.Hyperelastic : A hyperelastic material definition with a
given function for the strain energy density function per unit undeformed volume
with Automatic Differentiation provided by jax.
felupe.constitution.jax.Material : A material definition with a given function for
the partial derivative of the strain energy function w.r.t. the deformation
gradient tensor with Automatic Differentiation provided by jax.
"""
import jax.numpy as jnp
from jax import Array

@wraps(material)
def first_piola_kirchhoff_stress(F, *args, **kwargs):
# evaluate the Cauchy stress
res = material(F, *args, **kwargs)

# check if the material formulation returns state variables and extract
# the Cauchy stress tensor
if isinstance(res, Array):
σ = res
statevars_new = None
else:
σ, statevars_new = res

# first Piola-Kirchhoff stress tensor
J = jnp.linalg.det(F)
P = J * σ @ jnp.linalg.inv(F).T

if statevars_new is None:
return P
else:
return P, statevars_new

return first_piola_kirchhoff_stress
9 changes: 9 additions & 0 deletions src/felupe/constitution/jax/models/hyperelastic/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ._mooney_rivlin import mooney_rivlin
from ._third_order_deformation import third_order_deformation
from ._yeoh import yeoh

__all__ = [
"mooney_rivlin",
"third_order_deformation",
"yeoh",
]
31 changes: 31 additions & 0 deletions src/felupe/constitution/jax/models/hyperelastic/_mooney_rivlin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
"""
This file is part of FElupe.

FElupe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

FElupe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FElupe. If not, see <http://www.gnu.org/licenses/>.
"""
from functools import wraps

from ....tensortrax.models.hyperelastic import mooney_rivlin as mooney_rivlin_docstring


@wraps(mooney_rivlin_docstring)
def mooney_rivlin(C, C10, C01):
from jax.numpy import trace
from jax.numpy.linalg import det

J3 = det(C) ** (-1 / 3)
I1 = J3 * trace(C)
I2 = (I1**2 - J3**2 * trace(C @ C)) / 2
return C10 * (I1 - 3) + C01 * (I2 - 3)
Loading
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载