I have a unit square (constructed with Gmsh). I am solving a hyperelastic problem where the displacement of the domain is governed by a growth tensor growth tensor. I want to impose a zero displacement Dirichlet BC at the center of mass. However, the center of mass might not lie at a node if the mesh is not heavily refined. I want the zero Dirichlet BC to be imposed at a node that is closest to the center of mass. How do I achieve that? This is what I tried:
msh = meshio.read("square.msh") # Simple unit square mesh created in Gmsh
######################################################################################################################
triangle_mesh = create_mesh(msh, "triangle", True)
line_mesh = create_mesh(msh, "line", True)
meshio.write("mesh.xdmf", triangle_mesh)
meshio.write("mf.xdmf", line_mesh)
from dolfin import *
mesh = Mesh()
xdmf = XDMFFile(mesh.mpi_comm(),"mesh.xdmf")
xdmf.read(mesh)
mvc = MeshValueCollection("size_t", mesh, mesh.topology().dim())
with XDMFFile("mesh.xdmf") as infile:
infile.read(mvc, "name_to_read")
cf = cpp.mesh.MeshFunctionSizet(mesh, mvc)
xdmf.close()
mvc = MeshValueCollection("size_t", mesh, mesh.topology().dim()-1)
with XDMFFile("mf.xdmf") as infile:
infile.read(mvc, "name_to_read")
mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)
ds_custom = Measure("dS", domain=mesh, subdomain_data=mf) # Defining global boundary measure, for global surface measure, plug in "dS" instead of "ds", which is used for subdomain boundary measures
dx_custom = Measure("dx", domain=mesh, subdomain_data=cf)
########## Calculating center of mass #########
new_V = VectorFunctionSpace(mesh,"P",1)
new_R = VectorFunctionSpace(mesh,"R",0)
new_position = Function(new_V)
new_position.assign(Expression(["x[0]","x[1]","x[2]"], element=new_V.ufl_element()))
new_c = TestFunction(new_R)
new_bulk = assemble(Constant(1.0)*dx(domain=mesh))
new_centroid = assemble(dot(new_c,new_position)*dx)
new_f = new_centroid/new_bulk
new_f_np = new_f.get_local()
center = new_f_np
print(f"center of mass = {center}",flush=True)
################################################
V = VectorFunctionSpace(mesh, 'P', 1)
u = Function(V)
v = TestFunction(V)
######################## Defining function to impose DBC at center ##################
class Gamma(SubDomain):
def inside(self, x, on_boundary):
return near(center[0], 1e-16) and near(center[1], 1e-16) and near(center[2], 1e-16) # I have tried with different values for the tolerance level
####################################################################
r = 0.02
nu1 = 0.01
mu1 = 5.0
d = mesh.geometry().dim()
I = Identity(d) # Identity tensor
F = I + grad(u) # Deformation gradient
g_bact = as_tensor([[1.0+r,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]])
Fe = variable(F*inv(g_bact))
C = Fe.T*Fe
J = det(Fe)
M = cofac(F)
# Invariants of deformation tensors
Ic = tr(C)
psi = (mu1/2)*(Ic - 3) + ((nu1)*(mu1)/(1-2*nu1))*(J-1)**2 - mu1*(ln(J))
TT = det(g_bact)*diff(psi,Fe)*(inv(g_bact).T) # First Piola-Kirchoff stress
# Compute first variation of Pi (directional derivative about u in the direction of v)
Pi = inner(TT,grad(v))*dx_custom(5)
r_center = Constant((0.0,0.0,0.0))
bcs = DirichletBC(V, r_center, Gamma(), "pointwise")
# Solve variational problem
solve(Pi == 0, u , bcs,
solver_parameters={"newton_solver": {"relative_tolerance": 5e-8,
"absolute_tolerance": 5e-9,"maximum_iterations": 50}})
File('displacement.pvd')<<u
How do I get the Dirichlet BC be imposed at a node that is closest to the center of mass? Any suggestions would be extremely useful.
Thank you.