Hello, I wish to implement create_slip_constraint from dolfinx_mpc on the generalized plane strain case. The left and bottom edges are allowed to slide tangentially but not normally.
I am stuck in the part dolfinx.fem.petsc.assemble_matrix_block implementation with mpc. A guidance will be quite helpful. Here is my code below.
import gmsh
from mpi4py import MPI
from petsc4py import PETSc
import ufl
from dolfinx import fem, io, plot
import dolfinx.fem.petsc
from dolfinx.cpp.la.petsc import get_local_vectors
from scifem import create_real_functionspace
from dolfinx_mpc.utils import (create_point_to_point_constraint, determine_closest_block, rigid_motions_nullspace, facet_normal_approximation)
from dolfinx_mpc import LinearProblem, MultiPointConstraint
hsize = 0.2
Re = 11.0
Ri = 9.0
gmsh.initialize()
gmsh.option.setNumber("General.Terminal", 0) # to disable meshing info
gdim = 2
model_rank = 0
gmsh.model.add("Model")
geom = gmsh.model.geo
center = geom.add_point(0, 0, 0)
p1 = geom.add_point(Ri, 0, 0)
p2 = geom.add_point(Re, 0, 0)
p3 = geom.add_point(0, Re, 0)
p4 = geom.add_point(0, Ri, 0)
x_radius = geom.add_line(p1, p2)
outer_circ = geom.add_circle_arc(p2, center, p3)
y_radius = geom.add_line(p3, p4)
inner_circ = geom.add_circle_arc(p4, center, p1)
boundary = geom.add_curve_loop([x_radius, outer_circ, y_radius, inner_circ])
surf = geom.add_plane_surface([boundary])
geom.synchronize()
gmsh.option.setNumber("Mesh.CharacteristicLengthMin", hsize)
gmsh.option.setNumber("Mesh.CharacteristicLengthMax", hsize)
gmsh.model.addPhysicalGroup(gdim, [surf], 1)
gmsh.model.addPhysicalGroup(gdim - 1, [x_radius], 1, name="bottom")
gmsh.model.addPhysicalGroup(gdim - 1, [y_radius], 2, name="left")
gmsh.model.addPhysicalGroup(gdim - 1, [outer_circ], 3, name="outer")
gmsh.model.mesh.generate(gdim)
domain, _, facets = io.gmshio.model_to_mesh(
gmsh.model, MPI.COMM_WORLD, model_rank, gdim=gdim
)
gmsh.finalize()
def eps(v, ezz):
return ufl.sym(
ufl.as_tensor(
[
[v[0].dx(0), v[0].dx(1), 0],
[v[1].dx(0), v[1].dx(1), 0],
[0, 0, ezz],
]
)
)
E = fem.Constant(domain, 1e5)
nu = fem.Constant(domain, 0.3)
mu = E / 2 / (1 + nu)
lmbda = E * nu / (1 + nu) / (1 - 2 * nu)
def sigma(v, ezz):
return lmbda * ufl.tr(eps(v, ezz)) * ufl.Identity(3) + 2.0 * mu * eps(v, ezz)
def eps(v, ezz):
return ufl.sym(
ufl.as_tensor(
[
[v[0].dx(0), v[0].dx(1), 0],
[v[1].dx(0), v[1].dx(1), 0],
[0, 0, ezz],
]
)
)
E = fem.Constant(domain, 1e5)
nu = fem.Constant(domain, 0.3)
mu = E / 2 / (1 + nu)
lmbda = E * nu / (1 + nu) / (1 - 2 * nu)
def sigma(v, ezz):
return lmbda * ufl.tr(eps(v, ezz)) * ufl.Identity(3) + 2.0 * mu * eps(v, ezz)
# Define Function Space
degree = 2
V = fem.functionspace(domain, ("P",degree, (gdim,)))
R = create_real_functionspace(domain)
W = MixedFunctionSpace(V, R)
# Define Variational Problem
du, dezz = TrialFunctions(W)
u_, ezz_ = TestFunctions(W)
#u = fem.Function(V, name = "Displacement")
a_form = inner(sigma(du, dezz), eps(u_, ezz_)) * dx
T = fem.Constant(domain, 1000000.0)
#Self-weight on the surface
n = FacetNormal(domain)
ds = Measure("ds", domain=domain, subdomain_data=facet_markers)
dx = Measure("dx", domain=domain, subdomain_data=cell_markers)
dS = Measure("dS", domain=domain, subdomain_data=facet_markers)
L_form = dot(T*n,u_) * ds(3)
a_blocked_compiled = fem.form(extract_blocks(a_form))
L_blocked_compiled = fem.form(extract_blocks(L_form))
# Get the facet markers for boundary edges (ps1 and ps2)
mpc = MultiPointConstraint(V)
for tag in [1, 2]: # ps1 and ps2
normal_vec = create_normal_approximation(V, facet_markers, tag)
mpc.create_slip_constraint(V, (facet_markers, tag), normal_vec)
mpc.finalize()
a_blocked_compiled = fem.form(ufl.extract_blocks(a_form))
L_blocked_compiled = fem.form(ufl.extract_blocks(L_form))
after this part I am stuck and need your guidance.
A = dolfinx.fem.petsc.assemble_matrix_block(a_blocked_compiled, bcs=bcs)
A.assemble()
b = dolfinx.fem.petsc.assemble_vector_block(
L_blocked_compiled, a_blocked_compiled, bcs=bcs
)
ksp = PETSc.KSP().create(domain.comm)
ksp.setOperators(A)
ksp.setType("preonly")
pc = ksp.getPC()
pc.setType("lu")
pc.setFactorSolverType("mumps")
# solve system
xh = dolfinx.fem.petsc.create_vector_block(L_blocked_compiled)
ksp.solve(b, xh)
xh.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
maps = [(Wi.dofmap.index_map, Wi.dofmap.index_map_bs) for Wi in W.ufl_sub_spaces()]
u = fem.Function(V, name="Displacement")
x_local = get_local_vectors(xh, maps)
u.x.array[: len(x_local[0])] = x_local[0]
u.x.scatter_forward()
ezz = x_local[1][0]