Hello,
I wish to simulate some deformable object with some air-chamber.
My input is a tetrahedral mesh. Starting from some surface mesh, it is first converted to volumetric mesh with tetgen, then to xdmf with meshio.
When loading the mesh, I can mark the boundaries of the air chamber, and use the measure ds_ac = Measure('ds', subdomain_data=boundaries)(1)
Till now, I use the pressure as parameter to inflate the system, I can express the force as pressure multiplied by normal.
Now, the problem is that the system is not behaving well when the pressure reaches some value, I suspect bistability is causing the solver to fail, so I want to switch to another parameter, namely the quantity of air in the air chamber, then use gas law pV=nRT.
My problem is that I had no idea how to express the volume V in the formulation. I know the function assemble
could do an integration, however no domain is representing the hole as it is not meshed.
Let me give you an MWE of what I’m doing now (for simplicity I generate a simple 2D mesh here, and there is just one iteration, but in practice it will be 3D and I loop with increasing pressures)
from dolfin import *
import numpy as np
from mshr import *
# Optimization options for the form compiler
parameters["form_compiler"]["cpp_optimize"] = True
ffc_options = {"optimize": True, "eliminate_zeros": True, "precompute_basis_const": True, "precompute_ip_const": True}
# Create mesh and define function space
box = Rectangle(Point(0.0, 0.0), Point(1.0,0.1))
subboxes = [Rectangle(Point(0.1*i-0.01, 0.04), Point(0.1*i+0.01,0.06)) for i in range(1,10)]
domain=box
for i in range(0,9):
domain=domain-subboxes[i]
mesh=generate_mesh(domain, 100)
V = VectorFunctionSpace(mesh, "Lagrange", 2)
N = FacetNormal(mesh)
left = CompiledSubDomain("near(x[0], side)", side = 0.)
c = Expression(("0.0", "0.0"),degree=2)
bcl = DirichletBC(V, c, left)
bcs = [bcl]
# Define functions
du = TrialFunction(V) # Incremental displacement
v = TestFunction(V) # Test function
u = Function(V) # Displacement from previous iteration
class myBubbles(SubDomain):
def inside(self,x,on_boundary):
return on_boundary and \
not(near(x[0],0.0)) and not(near(x[0],1.0)) and \
x[1]>0.01 and x[1]<0.09
# Kinematics
d = u.geometric_dimension()
I = Identity(d) # Identity tensor
# Elasticity parameters
E, nu = 100.0, 0.27
mu, lmbda = Constant(E/(2*(1 + nu))), Constant(E*nu/((1 + nu)*(1 - 2*nu)))
filex = XDMFFile('MWEresults.xdmf');
filex.parameters.update(
{
"functions_share_mesh": True, "rewrite_function_mesh": False, "flush_output": True
})
u.rename("displacement","");
p=0.01 ##Here is the pressure, I would like to change for n (number of air molecules)
#computation of energy
F = I + grad(u)
C = F.T*F
Finv=inv(F)
Ic = tr(C)
J = det(F)
n = J*Finv.T*N
# Stored strain energy density (compressible neo-Hookean model)
psi = (mu/2)*(Ic - 3) - mu*ln(J) + (lmbda/2)*(ln(J))**2
pr=Constant((p))
## Here I'd like to change pr expression
## First compute volume of the bubbles
## V_bubbles = ...
## Then express pr=n/V*Constant(R*T)
boundaries = MeshFunction("size_t", mesh,mesh.topology().dim()-1, 0)
boundaries.set_all(0)
bubbles_bound=myBubbles()
bubbles_bound.mark(boundaries, 1)
ds_region = Measure('ds', subdomain_data=boundaries)
Pi = psi*dx - dot(u,-pr*n)*ds_region(1)
# Compute first variation of Pi (directional derivative about u in the direction of v)
F = derivative(Pi, u, v)
Fmat = derivative(psi, u, v)
# Compute Jacobian of F
J = derivative(F, u, du)
# Solve variational problem
solve(F == 0, u, bcs, J=J,
form_compiler_parameters=ffc_options,
solver_parameters={
"newton_solver":{\
"relaxation_parameter":1.0, "relative_tolerance":1e-6 ,
"maximum_iterations":100, 'linear_solver': 'mumps'
} })
filex.write(u, p);