Material property as a field #497
Replies: 4 comments 12 replies
-
Hi, do your material properties also change with the deformation? |
Beta Was this translation helpful? Give feedback.
-
Here's the example of the README, modified to linear-elasticity and with a spatial-dependent young's modulus. import felupe as fem
# create a hexahedron-region on a cube
mesh = fem.Cube(n=6)
region = fem.RegionHexahedron(mesh)
# add a field container (with a vector-valued displacement field)
field = fem.FieldContainer([fem.Field(region, dim=3)])
boundaries, loadcase = fem.dof.uniaxial(field, move=1, clamped=True)
# example: interpolate (initial) X-coordinates from mesh-points to quadrature points
X, Y, Z = fem.Field(region, dim=3, values=mesh.points).interpolate()
# the X-coordinate is now available for every quadrature point and for every cell
print(X.shape) # (8, 125)
# field-dependent young's modulus
E = 1 + X
# define the constitutive material behaviour
# and create a linear-elastic solid body
umat = fem.LinearElastic(E=E, nu=0.3)
solid = fem.SolidBody(umat, field)
# prepare a step with substeps
step = fem.Step(items=[solid], boundaries=boundaries)
# add the step to a job, evaluate
fem.Job(steps=[step]).evaluate()
# visualize the results
view = fem.View(field)
view.plot("Displacement", component=None).show() Hope that helps! |
Beta Was this translation helpful? Give feedback.
-
And here is an example for nonlinear elasticity (isotropic hyperelasticity): import felupe as fem
# create a hexahedron-region on a cube
mesh = fem.Cube(n=6)
region = fem.RegionHexahedron(mesh)
# add a field container (with a vector-valued displacement field)
field = fem.FieldContainer([fem.Field(region, dim=3)])
boundaries, loadcase = fem.dof.uniaxial(field, clamped=True)
# interpolate (initial) coordinates from mesh-points to quadrature points
X, Y, Z = fem.Field(region, dim=3, values=mesh.points).interpolate()
# define the constitutive material behaviour (with a spatial-dependent shear modulus)
# and create an isotropic-hyperelastic solid body
umat = fem.NeoHooke(mu=1 + X)
solid = fem.SolidBodyNearlyIncompressible(umat, field, bulk=5000)
# prepare a step with substeps
step = fem.Step(
items=[solid],
boundaries=boundaries,
ramp={boundaries["move"]: fem.math.linsteps([0, 1], num=5)},
)
# add the step to a job, evaluate
job = fem.Job(steps=[step])
job.evaluate()
# visualize the results
view = fem.View(field)
view.plot("Displacement", component=None).show() |
Beta Was this translation helpful? Give feedback.
-
Hi @abhiawasthi1993, sorry for the super-late reply. I don't know if you're still interested in this topic. Here's a quick example where a material parameter is defined by a field and the strain energy density function of a hyperelastic solid is defined by matadi. However, I'm still not sure how to create the Jacobian (using automatic differentiation) w.r.t. the material parameter(s). I think this depends on the quantity you would like to fit, I could imagine the maximum principal log. strains or the displacement vectors. Anyway, an additional field would be required for this quantity such that the Jacobian can be extracted from the list of import felupe as fem
import numpy as np
import matadi as mat
import matadi.math as mm
mesh = fem.Rectangle(n=3)
region = fem.RegionQuad(mesh)
# a mixed-field container with displacements and material parameter field
field = fem.FieldContainer(
fields=[fem.FieldPlaneStrain(region, dim=2), fem.Field(region, dim=1)]
)
def fun(x, K=5):
# unpack input variables
F, C10, ζ = x[:3]
C = F.T @ F
J = mm.det(F)
I1 = mm.trace(C) * J ** (-2 / 3)
# strain energy density function
ψ = C10 * (I1 - 3) + K * (J - 1) ** 2 / 2
# update of state variables (not used)
ζ_new = ζ
return [mm.gradient(ψ, F), mm.gradient(ψ, C10), ζ_new]
# symbolic variables, including (required - but not used) state variables
F = mat.Variable("F", 3, 3)
C10 = mat.Variable("C10")
ζ = mat.Variable("ζ")
umat = mat.MaterialTensor([F, C10, ζ], fun, statevars=1)
solid = fem.SolidBody(umat=umat, field=field)
boundaries, loadcase = fem.dof.uniaxial(field, clamped=True)
# prescribed values for the material parameters by a boundary condition
entire_model = np.ones(field[-1].region.mesh.npoints, dtype=bool)
boundaries["C10"] = fem.Boundary(field[-1], mask=entire_model)
boundaries["C10"].update(value=0.5 + np.random.rand(field[-1].region.mesh.npoints) / 10)
move = fem.math.linsteps([0, 1], num=5)
ramp = {boundaries["move"]: move}
step = fem.Step(items=[solid], ramp=ramp, boundaries=boundaries)
job = fem.Job(steps=[step]).evaluate()
ax = solid.imshow("Principal Values of Logarithmic Strain") |
Beta Was this translation helpful? Give feedback.
-
I would like to model an inhomogeneous material where the material property value would be a spatially varying field instead of a constant value throughout (current implementation). Any leads on this would be much appreciated.
Beta Was this translation helpful? Give feedback.
All reactions