I have two cylinders which are not supposed to interact with each other (yet). I apply a pressure at the right face of both cylinders. Why do they curve like this instead of going straight?
If I remove the second cylinder it looks like this (as expected)
If I move them further away from each other this effect increases as well as the elongation only in x direction
It does not matter where I put the 2nd cylinder, the direction in which it gets deformed is always the same. Here I put the 2nd cylinder on the z axis and still the first one is deformed in negative y and negative z direction.
This is my code to reproduce this:
import numpy as np # type: ignore
from ufl import sym, grad, Identity, tr, inner, Measure, TestFunction, TrialFunction # type: ignore
from mpi4py import MPI # type: ignore
from dolfinx import fem, io, mesh
from dolfinx.fem.petsc import assemble_vector, assemble_matrix, create_vector, apply_lifting, set_bc
from dolfinx.fem import locate_dofs_geometrical, DirichletBC
from petsc4py import PETSc # type: ignore
import matplotlib.pyplot as plt # type: ignore
import gmsh
pressure_value = 8.0
E = 10 # Young's modulus
radius = 1
radius_2 = 1
length = 10
gmsh.initialize()
gmsh.option.setNumber("General.Terminal", 0)
gdim = 3
# add first cylinder
gmsh.model.add("cylinder")
cylinder_tag = gmsh.model.occ.addCylinder(0, 0, 0, length, 0, 0, radius)
gmsh.model.occ.synchronize()
gmsh.model.addPhysicalGroup(gdim, [cylinder_tag], 0)
surfaces = gmsh.model.getBoundary([(3, cylinder_tag)], oriented=False, recursive=False)
right_face_tag = surfaces[1][1]
gms.model.addPhysicalGroup(gdim - 1, [right_face_tag], 1)
gmsh.model.setPhysicalName(gdim - 1, 1, "Right")
left_face_tag = surfaces[0][1]
gmsh.model.addPhysicalGroup(gdim - 1, [left_face_tag], 2)
gmsh.model.setPhysicalName(gdim - 1, 2, "Left")
lateral_surface_tags = [surf[1] for surf in surfaces[2:]]
gmsh.model.addPhysicalGroup(gdim - 1, lateral_surface_tags, 3)
gmsh.model.setPhysicalName(gdim - 1, 3, "Lateral")
# add second cylinder
second_cylinder_tag = gmsh.model.occ.addCylinder(0, 0,20*radius, length, 0, 0, radius_2)
gmsh.model.occ.synchronize()
gmsh.model.addPhysicalGroup(gdim, [second_cylinder_tag], 1)
surfaces = gmsh.model.getBoundary([(3, second_cylinder_tag)], oriented=False, recursive=False)
second_right_face_tag = surfaces[1][1]
gmsh.model.addPhysicalGroup(gdim - 1, [second_right_face_tag], 4)
gmsh.model.setPhysicalName(gdim - 1, 4, "secondRight")
second_left_face_tag = surfaces[0][1]
gmsh.model.addPhysicalGroup(gdim - 1, [second_left_face_tag], 5)
gmsh.model.setPhysicalName(gdim - 1, 5, "secondLeft")
second_lateral_surface_tags = [surf[1] for surf in surfaces[2:]]
gmsh.model.addPhysicalGroup(gdim - 1, second_lateral_surface_tags, 6)
gmsh.model.setPhysicalName(gdim - 1, 6, "secondLateral")
gmsh.model.mesh.generate(gdim)
domain, _, facets = io.gmshio.model_to_mesh(gmsh.model, MPI.COMM_WORLD, 0, gdim=gdim)
gmsh.finalize()
shape = (gdim,)
# Define the function space
V = fem.functionspace(domain, ("P", 2, shape))
u = TrialFunction(V)
v = TestFunction(V)
u_h = fem.Function(V, name="Displacement")
# Define strain and stress tensors
def epsilon(u):
return sym(grad(u))
def sigma(u):
return E * epsilon(u)
pressure_force = fem.Constant(domain, np.array([pressure_value, 0, 0]))
dx = Measure("dx", domain=domain) # Volume measure
ds = Measure("ds", domain=domain, subdomain_data=facets) # Surface measure for boundaries
right_face = 1
right_face_second = 4
# Define the boundary conditions
def left(x):
return np.isclose(x[0], 0)
left_dofs = locate_dofs_geometrical(V, left)
bcs = [
fem.dirichletbc(np.zeros(3,), left_dofs, V) # keep the left face fixed
]
# Define the weak form
a = (inner(sigma(u), epsilon(v)) * dx)
L = inner(pressure_force, v) * (ds(right_face) + ds(right_face_second))
# in case of a single cylinder:
# L = inner(pressure_force, v) * ds(right_face)
bilinear_form = fem.form(a)
linear_form = fem.form(L)
A = assemble_matrix(bilinear_form, bcs=bcs)
A.assemble()
b = create_vector(linear_form)
solver = PETSc.KSP().create(domain.comm)
solver.setOperators(A)
solver.setType(PETSc.KSP.Type.PREONLY)
solver.getPC().setType(PETSc.PC.Type.LU)
problem = fem.petsc.LinearProblem(
a, L, u=u_h, bcs=bcs,
petsc_options={"ksp_type": "preonly", "pc_type": "lu"}
)
vtk = io.VTKFile(domain.comm, "results/dynamic/dynamic_cylinder.pvd", "w")
# Update the right hand side reusing the initial vector
with b.localForm() as loc_b:
loc_b.set(0)
assemble_vector(b, linear_form)
# Apply Dirichlet boundary condition to the vector
apply_lifting(b, [bilinear_form], [bcs])
b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
set_bc(b, bcs)
# Solve linear problem
solver.solve(b, u_h.x.petsc_vec)
u_h.x.scatter_forward()
vtk.write_function(u_h)
vtk.close()