question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mixed formulation for Incompressible Hyperelasticity

See original GitHub issue

Following #439 and inputs from ex18, I started working yesterday on a mixed formulation for incompressible hyperelasticity using the Taylor-Hood elements. The idea is to work on imposing Dirichlet BC’s later today and then test a simple uniaxial tension later in the week. This should be fairly self contained. This is what I have so far. Please let me know whenever you get time to take a look. No rush from my end

from numpy import einsum, linalg as nla, zeros, zeros_like, concatenate, abs as npabs, split as npsplit
from scipy.sparse import bmat
from sympy import Symbol, simplify, lambdify, diff, sqrt
from skfem.helpers import grad, transpose
from typing import List, Optional
from numba import jit, prange
from skfem import *

@jit(cache=True, nopython=True, nogil=True, parallel=True)
def vdet(A):
    detA = zeros_like(A[0, 0])
    detA = A[0, 0] * (A[1, 1] * A[2, 2] -
                    A[1, 2] * A[2, 1]) -\
        A[0, 1] * (A[1, 0] * A[2, 2] -
                    A[1, 2] * A[2, 0]) +\
        A[0, 2] * (A[1, 0] * A[2, 1] -
                    A[1, 1] * A[2, 0])
    return detA

@jit(cache=True, nopython=True, nogil=True, parallel=True)
def vinv(A):
    invA = zeros_like(A)
    detA = vdet(A)
    invA[0, 0] = (-A[1, 2] * A[2, 1] +
                A[1, 1] * A[2, 2]) / detA
    invA[1, 0] = (A[1, 2] * A[2, 0] -
                A[1, 0] * A[2, 2]) / detA
    invA[2, 0] = (-A[1, 1] * A[2, 0] +
                A[1, 0] * A[2, 1]) / detA
    invA[0, 1] = (A[0, 2] * A[2, 1] -
                A[0, 1] * A[2, 2]) / detA
    invA[1, 1] = (-A[0, 2] * A[2, 0] +
                A[0, 0] * A[2, 2]) / detA
    invA[2, 1] = (A[0, 1] * A[2, 0] -
                A[0, 0] * A[2, 1]) / detA
    invA[0, 2] = (-A[0, 2] * A[1, 1] +
                A[0, 1] * A[1, 2]) / detA
    invA[1, 2] = (A[0, 2] * A[1, 0] -
                A[0, 0] * A[1, 2]) / detA
    invA[2, 2] = (-A[0, 1] * A[1, 0] +
                A[0, 0] * A[1, 1]) / detA
    return invA, detA


def F1(w):
    u = w["w"][0]
    p = w["w"][1]
    # print(w["w"][0])
    F = zeros_like(grad(u))
    for i in prange(3):
        F[i,i] += 1.
    F += grad(u)
    Finv, J = vinv(F)
    return p * J * transpose(Finv) + mu * F

def F2(w):
    u = w["w"][0]
    p = w["w"][1]
    F = zeros_like(grad(u))
    for i in prange(3):
        F[i,i] += 1.
    F += grad(u)
    J = vdet(F)
    Js = Jstar(p)
    return J-(Js + (p + mu/Js - lmbda*(Js - 1))*dJst_dp(p))

def A11(w):
    u = w["w"][0]
    p = w["w"][1]
    F = zeros_like(grad(u))
    eye = zeros_like(grad(u))
    for i in prange(3):
        F[i,i] += 1.
        eye[i,i] += 1.
    F += grad(u)
    Finv, J = vinv(F)
    L = p*J*einsum("lk...,ji...->ijkl...",Finv, Finv) - p * J * einsum("jk...,li...->ijkl...", Finv, Finv) + mu * einsum("ik...,jl...->ijkl...", eye, eye)
    return L

def A12(w):
    u = w["w"][0]
    p = w["w"][1]
    F = zeros_like(grad(u))
    for i in prange(3):
        F[i,i] += 1.
    F += grad(u)
    Finv, J = vinv(F)
    return J * transpose(Finv)

def A21(w):
    u = w["w"][0]
    p = w["w"][1]
    F = zeros_like(grad(u))
    for i in prange(3):
        F[i,i] += 1.
    F += grad(u)
    Finv, J = vinv(F)
    return J * transpose(Finv)

def A22(w):
    u = w["w"][0]
    p = w["w"][1]
    # F = zeros_like(grad(u))
    # for i in prange(3):
    #     F[i,i] += 1.
    # F += grad(u)
    # Finv, J = vinv(F)
    Js = Jstar(p)
    dJdp = dJst_dp(p)
    d2Jdp2 = d2Jst_dp2(p)

    L = -2.*dJdp - p * d2Jdp2 + mu/Js**2 * dJdp**2 - mu/Js*d2Jdp2 + lmbda * (Js - 1.) * d2Jdp2 + lmbda * dJdp**2
    return L
    

mesh = MeshTet()
uelem = ElementVectorH1(ElementTetP2())
pelem = ElementTetP1()
elems = {
    "u": uelem,
    "p": pelem
}
basis = {
    field: InteriorBasis(mesh, e, intorder=3)
    for field, e in elems.items()
}

du = zeros(basis["u"].N)
dp = zeros(basis["p"].N)
stretch_ = 1.5

dofs = {
    "left":basis["u"].get_dofs(lambda x: x[0] < 1.e-6),
    "bottom":basis["u"].get_dofs(lambda x: x[1] < 1.e-6),
    "back":basis["u"].get_dofs(lambda x: x[2] < 1.e-6),
    "front":basis["u"].get_dofs(lambda x: x[2] > 1. - 1.e-6)
}
# print(dofs)
du[dofs["left"].nodal["u^1"]] = 0.
du[dofs["bottom"].nodal["u^2"]] = 0.
du[dofs["back"].nodal["u^3"]] = 0.
du[dofs["front"].nodal["u^3"]] = stretch_

I = basis["u"].complement_dofs(dofs)
# material parameters
mu, lmbda = 1., 1.e3

p = Symbol("p", real=True)
Jst = (lmbda + p + sqrt((lmbda+p)**2 + 4*lmbda*mu ))/(2*lmbda)
dJst_dp = lambdify(p, simplify(Jst.diff(p)), "numpy")
d2Jst_dp2 = lambdify(p, simplify(Jst.diff(p,2)), "numpy")
Jstar = lambdify(p, simplify(Jst), "numpy")
w = (
    basis["u"].interpolate(du),
    basis["p"].interpolate(dp)
)

@LinearForm
def a1(v, w):
    return einsum("ij...,ij...",F1(w), grad(v))

@LinearForm
def a2(v, w):
    return F2(w) * v

@BilinearForm
def b11(u, v, w):
    return einsum("ijkl...,ij...,kl...",A11(w), grad(u), grad(v))

@BilinearForm
def b12(u, v, w):
    return einsum("ij...,ij...",A12(w), grad(v)) * u

@BilinearForm
def b21(u, v, w):
    return einsum("ij...,ij...",A21(w), grad(v)) * u

@BilinearForm
def b22(u, v, w):
    return A22(w) * u * v

for itr in range(100):
    w = (
        basis["u"].interpolate(du),
        basis["p"].interpolate(dp)
    )

    K11 = asm(b11, basis["u"], basis["u"], w=w)
    K12 = asm(b12, basis["p"], basis["u"], w=w)
    K21 = asm(b21, basis["p"], basis["u"], w=w)
    K22 = asm(b22, basis["p"], basis["p"], w=w)
    f = concatenate((
        asm(a1, basis["u"], w=w),
        asm(a2, basis["p"], w=w)
    ))
    K = bmat(
        [[K11, K12],
         [K21.T, K22]], "csr"
    )
    uvp = solve(*condense(K, -f, I=I), use_umfpack=True)
    delu, delp = npsplit(uvp, [K11.shape[0]])
    du += delu
    dp += delp
    normu = nla.norm(delu)
    normp = nla.norm(delp)
    print(f"{itr+1}, norm_du: {normu}, norm_dp: {normp}")
    if normu < 1.e-6 and normp < 1.e-6:
        break

import meshio
from vedo import show as vShow, Mesh as vMesh
meshio.xdmf.write(
    "mixedFEM.xdmf",
    meshio.Mesh(mesh.p.T, {"tetra":mesh.t.T},point_data={"u":du[basis["u"].nodal_dofs].T})
)

Once I work through the details, and it happens to be of interest to you I’d be glad to contribute it as an (advanced) example.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:26 (26 by maintainers)

github_iconTop GitHub Comments

1reaction
kinnalacommented, Aug 15, 2020

but forgot to check if it indeed returns all the pressure dofs which is what I need in this case.

I see, right now find_dofs (etc.) are targeted more towards finding boundary DOF’s than interior DOF’s although the key all may suggest something else. I still haven’t quite figured out how to design a proper interface for finding and handling DOF’s.

1reaction
kinnalacommented, Aug 15, 2020

So maybe it was something related to the DOF’s after all? I changed

    uvp = solve(*condense(K, -f, I=I), use_umfpack=True)

to

    uvp = solve(*condense(K, -f, D=dofs), use_umfpack=True)

and now I get inco Edit: Forgot to mention that the above uses ElementTetMini but I now verified that I get the same correct result with ElementTetP2.

Read more comments on GitHub >

github_iconTop Results From Across the Web

A mixed finite element formulation for compressible finite ...
Abstract. A mixed finite element formulation for compressible finite hyperelasticity, possibly with strongly deformation dependent stiffening ...
Read more >
Mixed Formulation
The mixed formulation is useful not only for linear elastic materials but also for elastoplastic materials, hyperelastic materials, and viscoelastic materials.
Read more >
A mixed finite element method for large deformation analysis ...
This paper discusses finite element formulations for large deformation analysis of incompressible hyperelastic materials.
Read more >
A linearized consistent mixed displacement-pressure ...
Abstract. We propose a novel mixed displacement-pressure formulation based on an energy functional that takes into account the relation ...
Read more >
Mixed Kirchhoff stress - displacement - pressure formulations ...
Keywords: Kirchhoff stress formulation, Incompressible hyperelasticity, Augmented Lagrangian preconditioning, Mixed finite element methods. 2000 ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found