H(\operatorname{div})-conforming HDG methods for Stokes

\(\newcommand{\opdiv}{\operatorname{div}}\)

4. H(\(\operatorname{div}\))-conforming HDG methods for Stokes#

  • Want to use \(H(\opdiv)\)-conforming finite elements for velocity

  • Since \(Q_h = \opdiv V_h\), we obtain exact divergence-free velocities

  • use HDG to discretize viscosity term

  • Since \(u_h \in {\mathcal BDM_k}\) is normally continuous, HDG is needed only for the tangential component

  • Facet variable \(\hat u\) lives in the tangential space on the facet

\[ a(u,\hat u; v, \hat v) = \sum_T \int_T \nabla u \nabla v - \int_{\partial T} \frac{\partial u}{\partial n} (v-\widehat{v})_t - \int_{\partial T} \frac{\partial v}{\partial n} (u-\widehat{u})_t + \int_{\partial T} \frac{\alpha p^2}{h} (u-\widehat{u})_t (v-\widehat{v})_t \]
\[ b(u, q) = \int \opdiv \, u \, q \]
from netgen.geom2d import SplineGeometry
from ngsolve import *
from ngsolve.webgui import Draw
geo = SplineGeometry()
geo.AddRectangle( (0, 0), (2, 0.41), bcs = ("wall", "outlet", "wall", "inlet"))
geo.AddCircle ( (0.2, 0.2), r=0.05, leftdomain=0, rightdomain=1, bc="cyl")
mesh = Mesh( geo.GenerateMesh(maxh=0.08))
mesh.Curve(5);
Draw (mesh)
BaseWebGuiScene
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*order/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 = CF( (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, vectors={"grid_size":30})  # velocity
Draw (gfu.components[2], mesh); # pressure