Hi
I have been successfully running a nonlinear mixed vector field problem (simple uni-axial tension of a rod) using a non-homogeneous Dirichlet boundary condition incrementally applied as a vector, i.e [ u_x, u_y, u_z] = [ t*1.0, 0.0, 0.0 ] at the right end of the rod (the left end is clamped):
msh = mesh.create_box(MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]), np.array([L, H, H])], [20, 1, 1],
mesh.CellType.hexahedron)
P1 = ufl.VectorElement("CG", msh.ufl_cell(), 2, dim=3) # Lagrange family, 2nd order
P2 = ufl.VectorElement("CG", msh.ufl_cell(), 1, dim=3) # Lagrange family, 1st order
VY = fem.FunctionSpace(msh, ufl.MixedElement([P1, P2]))
v, yf = ufl.TestFunctions(VY) # test functions
uwf = fem.Function(VY) # current displacement and change of director
u, wf = ufl.split(uwf)
def right(x):
return np.isclose(x[0], L)
class incremented_displacement_expression:
def __init__(self):
self.t = 0.0
def eval(self, x):
# linearly incremented displacement
return np.stack((np.full(x.shape[1], self.t * 1.0), np.zeros(x.shape[1]), np.zeros(x.shape[1])))
V0, u_dofs = VY.sub(0).collapse()
incremented_displacement_expr = incremented_displacement_expression()
incremented_displacement_expr.t = 0
incremented_displacement = fem.Function(V0)
incremented_displacement.interpolate(incremented_displacement_expr.eval)
right_u_dofs = fem.locate_dofs_geometrical((VY.sub(0),V0), right)
bc2 = fem.dirichletbc(incremented_displacement, right_u_dofs, VY.sub(0))
skipping some not relevant lines
for n in range(1, 10):
# update the inhomogeneous displacement boundary condition
incremented_displacement_expr.t = n
incremented_displacement.interpolate(incremented_displacement_expr.eval)
# solve the equation system
num_its, converged = solver.solve(uwf)
I realized now that the actual problem only prescribes the u_x component but u_y and u_z are both kept free, i.e. I only need to apply the Dirichlet BC component-wise for u_x.
I am following the example showing vector component-wise https://jorgensd.github.io/dolfinx-tutorial/chapter3/component_bc.html but wanted to stick to geometrical DOF localization and I also had to transfer the example code into the mixed environment. I got it running without errors but I don’t get a converged solution anymore, although the load (the non-homogeneous Dirichlet BC) has effectively not changed:
class incremented_x_displacement_expression:
def __init__(self):
self.t = 0.0
def eval(self, x):
# linearly incremented displacement
return np.full(x.shape[1], self.t * 1.0)
V0, u_dofs = VY.sub(0).collapse()
V0x, u_x_dofs = V0.sub(0).collapse()
incremented_x_displacement_expr = incremented_x_displacement_expression()
incremented_x_displacement_expr.t = 0
incremented_x_displacement = fem.Function(V0x)
incremented_x_displacement.interpolate(incremented_x_displacement_expr.eval)
right_ux_dofs = fem.locate_dofs_geometrical((V0.sub(0),V0x), right)
bc2 = fem.dirichletbc(incremented_x_displacement, right_ux_dofs, V0.sub(0))
skipping some not relevant lines
for n in range(1, 10):
# update the inhomogeneous displacement boundary condition
incremented_x_displacement_expr.t = n
incremented_x_displacement.interpolate(incremented_x_displacement_expr.eval)
# solve the equation system
num_its, converged = solver.solve(uwf)
Please advise. Many thanks in advance.