Hello everybody. I am trying to simulate fluid flow around an object using the incompressible Stokes flow equations. I want to define a free-slip boundary condition around an "obstacle" with a curved surface in the middle of the domain, and to do that I'm trying to use the Nitsche method. Here is a paper describing the Nitsche method (the relevant material is on pages 5-6). And here somebody actually implemented the Nitsche method in FEniCS, but I am unable to run it with my current version (2016.2). I tried to structure my own program using this person's implementation.
So here's the problem. I am trying to benchmark my program using an analytical solution, but my simulation results are nowhere close. In fact, the simulation results seem to better match the case where a no-slip boundary condition is applied around the "obstacle" in the middle of the domain. I am unable to figure out where the discrepancy is coming from. Does anybody have experience with fluid mechanics who can help me out?
I'll post my code below, but here are some relevant details:
The domain under consideration is pretty simple. It's just a 10 x 10 square with a circular hole in the center, and the radius of the hole is 1. I want to apply a free-slip boundary condition around this hole so that the velocity normal to the surface is zero.
I'm using Taylor-Hood elements, so the problem is defined in a mixed function space with quadratic interpolation for velocity and linear interpolation for pressure.
For Dirichlet boundary conditions, I have imposed free slip on the top and bottom edges of the domain. On the left and right edges, I have set the velocity as Constant((1,0))
.
And here is the full code:
# import Python modules
from __future__ import division
from fenics import *
# suppress FEniCS output to screen
set_log_active(False)
# load mesh
mesh = Mesh()
hdf5 = HDF5File(mpi_comm_world(),"mesh/cylinder.h5","r")
hdf5.read(mesh,"mesh",False)
hdf5.close()
# define function spaces
P1 = FiniteElement("CG", mesh.ufl_cell(), 1) # first order scalar finite element
P2 = VectorElement("CG", mesh.ufl_cell(), 2) # second order vector finite element
V = FunctionSpace(mesh, MixedElement([P2,P1])) # mixed finite element
# classes for domain edge boundaries
class left_edge(SubDomain):
def inside(self, x, on_boundary): return near(x[0],0) and on_boundary
class right_edge(SubDomain):
def inside(self, x, on_boundary): return near(x[0],10) and on_boundary
class bottom_edge(SubDomain):
def inside(self, x, on_boundary): return near(x[1],0) and on_boundary
class top_edge(SubDomain):
def inside(self, x, on_boundary): return near(x[1],10) and on_boundary
class hole_edge(SubDomain):
def inside(self, x, on_boundary): return ((x[0]-5)**2+(x[1]-5)**2 <= 1.1) and on_boundary
left = left_edge()
right = right_edge()
bottom = bottom_edge()
top = top_edge()
hole = hole_edge()
# mark boundaries as "ds"
boundaries = FacetFunction("size_t",mesh,0)
left.mark(boundaries, 1)
right.mark(boundaries, 2)
bottom.mark(boundaries, 3)
top.mark(boundaries, 4)
hole.mark(boundaries, 5)
ds = Measure("ds",subdomain_data=boundaries)
# Dirichlet BC's
free_slip_top = DirichletBC(V.sub(0).sub(1), Constant(0), top)
free_slip_bottom = DirichletBC(V.sub(0).sub(1), Constant(0), bottom)
flow_left = DirichletBC(V.sub(0), Constant((1,0)), left)
flow_right = DirichletBC(V.sub(0), Constant((1,0)), right)
BC = [free_slip_top, free_slip_bottom, flow_left, flow_right]
# symmetric gradient operator
def D(x):
return sym(nabla_grad(x))
# linear viscosity
eta = Constant(1)
# stress
def sig(x,y):
return 2*eta*D(x) - y*Identity(2)
# trial and test functions for velocity and pressure
u, p = TrialFunctions(V) # trial functions in (P2, P1) space
v, q = TestFunctions(V) # test functions in (P2, P1) space
# loading terms
f = Constant((0, 0))
g = Constant(0)
# penalty terms
h = CellSize(mesh)
beta = Constant(10)
# variational form
n = FacetNormal(mesh) # normal vector
t = dot(sig(u,p),n) # traction
s = dot(sig(v,q),n) # traction
# stokes flow main terms
a = (2*eta*inner(D(v),D(u)) - p*div(v) + q*div(u))*dx
L = inner(f,v)*dx
# nitsche terms
a += (
- inner(dot(t,n),dot(v,n))
- inner(dot(s,n),dot(u,n))
+ beta/h*inner(dot(u,n),dot(v,n))
)*ds(5)
L += -inner(g,inner(s,n))*ds(5)
# solve the variational form
w = Function(V)
solve(a==L, w, BC)
u, p = w.split(deepcopy=True)
# store data
hdf5 = HDF5File(mpi_comm_world(),"output/data.h5","w")
hdf5.write(mesh,"mesh")
hdf5.write(u,"velocity")
hdf5.write(p,"pressure")
hdf5.close()
Thank you in advance.