45. H(div)-conforming Stokes#
[Master thesis Lehrenfeld 2010, Lehrenfeld+Schöberl, 2016]
Discretize velocity \(u\) in \(H(\operatorname{div})\), with Raviart-Thomas or BDM elements. This allows to use pressure space \(Q_h = \operatorname{div} V_h\). This the discrete velocity is exactly divergence free.
Since RT/BDM elements have only continuous normal components, they cannot be used directly for the viscosity term. So we use HDG for gluing together also the tangential components.
from ngsolve import *
from ngsolve.webgui import Draw
from netgen.occ import *
shape = Rectangle(2,0.41).Circle(0.2,0.2,0.05).Reverse().Face()
shape.edges.name="wall"
shape.edges.Min(X).name="inlet"
shape.edges.Max(X).name="outlet"
mesh = Mesh(OCCGeometry(shape, dim=2).GenerateMesh(maxh=0.07)).Curve(3)
Draw (mesh);
order=4
VT = HDiv(mesh, order=order, dirichlet="wall|cyl|inlet")
VF = TangentialFacetFESpace(mesh, order=order, dirichlet="wall|cyl|inlet")
Q = L2(mesh, order=order-1)
V = VT*VF*Q
u, uhat, p = V.TrialFunction()
v, vhat, q = V.TestFunction()
n = specialcf.normal(mesh.dim)
h = specialcf.mesh_size
dS = dx(element_boundary=True)
nu = 1e-3
def tang(vec):
return vec - (vec*n)*n
# Thesis Christoph Lehrenfeld, page 71
a = BilinearForm (V)
a += nu*InnerProduct(Grad(u), Grad(v)) * dx
a += nu*InnerProduct(Grad(u)*n, tang(vhat-v)) * dS
a += nu*InnerProduct(Grad(v)*n, tang(uhat-u)) * dS
a += nu*4*order**2/h * InnerProduct(tang(vhat-v), tang(uhat-u)) * dS
a += div(u)*q*dx + div(v)*p*dx
a.Assemble();
f = LinearForm(V).Assemble()
invstokes = a.mat.Inverse(V.FreeDofs())
gfu = GridFunction(V)
uin = CoefficientFunction((1.5*4*y*(0.41-y)/(0.41*0.41),0))
gfu.components[0].Set(uin, definedon=mesh.Boundaries("inlet"))
res = f.vec - a.mat*gfu.vec
gfu.vec.data += invstokes * res
Draw (gfu.components[0], mesh, "vel") # velocity
Draw (gfu.components[2], mesh, "pressure") # pressure
Draw (div(gfu.components[0]), mesh, "divvel"); # div velocity