[Tutorial] Easy and fast assembly of bilinear forms for hyperelastic solids #839
Replies: 4 comments 12 replies
-
I'll have to update the docstring and the code because for a compressible Neo-Hookean material the volumetric term is associated to lambda and not the bulk modulus. |
Beta Was this translation helpful? Give feedback.
-
This technique also enables faster evaluations of hyperelastic forms using automatic differentiation (just as an idea using casADi...). No explicit gradients and hessians are evaluated by AD; only jacobian - vector products ( Material definition with Automatic Differentiationimport casadi as ca
class NeoHooke:
def __init__(self, mu, bulk):
F = ca.SX.sym("F", 3, 3)
dF = ca.SX.sym("dF", 3, 3)
DF = ca.SX.sym("DF", 3, 3)
C = ca.transpose(F) @ F
J = ca.det(F)
W = mu * (J**(-2/3) * ca.trace(C) - 3) + bulk * (J - 1)**2/2
dW = ca.jtimes( W, F, dF)
DdW = ca.jtimes(dW, F, DF)
self._gvp = ca.Function("g", [F, dF], [dW])
self._hvp = ca.Function("h", [F, dF, DF], [DdW])
def ravel(self, T):
return T.reshape(T.shape[0], -1, order="F")
def gradient_vector_product(self, F, dF):
n = F.shape[-2] * F.shape[-1]
gvp = self._gvp.map(n, "thread", 4)
return np.array(
gvp(self.ravel(F), self.ravel(dF))
).reshape(F.shape[-2:], order="F")
def hessian_vector_product(self, F, dF, DF):
n = F.shape[-2] * F.shape[-1]
hvp = self._hvp.map(n, "thread", 4)
return np.array(
hvp(self.ravel(F), self.ravel(dF), self.ravel(DF))
).reshape(F.shape[-2:], order="F") And here is the defintion of (bi-) linear forms with the above material class: umat = NeoHooke(mu=1.0, bulk=2.0)
def deformation_gradient(w):
dudX = grad(w["displacement"])
F = dudX + identity(dudX)
return F
@LinearForm(nthreads=4)
def L(v, w):
F = deformation_gradient(w)
return umat.gradient_vector_product(F, grad(v))
@BilinearForm(nthreads=4)
def a(u, v, w):
F = deformation_gradient(w)
return umat.hessian_vector_product(F, grad(v), grad(u)) |
Beta Was this translation helpful? Give feedback.
-
Here is a picture I plan to use: The mesh is rough so that test suite runs fast. |
Beta Was this translation helpful? Give feedback.
-
Hi,
as already mentioned in #703 I came across a solution how to drastically speed-up the assembly of bilinear forms for hyperelastic solids. The solution is to not explicitely calculate the deformation-dependent fourth-order elasticity tensor but instead formulate the problem in variational notation. Below follows an example - beside the speed-up this simplifies the analytic derivatives of the strain energy function. I really like that kind of coding 😎 👍🏻. In my opinion this is the way to go how to code hyperelastic forms in scikit-fem. Note that no fourth-order tensor is created inside the bilinear form. Please have a look at the following lines of theory + code and try it out for yourself:
Best regards,
Andreas
Edit: I've updated this post with the constitutive corrections from below (renamed
bulk
tolmbda
, usemul
helper) so that if one only reads the original post at least the theory and the copy-paste code-block is up to date.Beta Was this translation helpful? Give feedback.
All reactions