This page was generated from unit-3.6-surfacehdg/surfacehdg.ipynb.

3.6 Scalar PDE on surfaces (with HDG)

We are solving the scalar linear transport problem

tuεΔΓu+divΓ(wu)=0 on Γ,

where Γ is a closed oriented surface in R3.

[1]:
from ngsolve import *
from ngsolve.webgui import Draw

Mesh of (only) the surface:

We consider the unit sphere (only surface mesh!)

[2]:
from netgen.occ import *
sphere = Sphere((0,0,0),1).faces[0]
sphere.name = "sphere"
geo = OCCGeometry(sphere)
mesh = Mesh(geo.GenerateMesh(maxh=0.5))
Draw(mesh)
[2]:
BaseWebGuiScene
[3]:
order = 4
if order > 0:
    mesh.Curve(order)
Draw(mesh)
[3]:
BaseWebGuiScene

Tangential velocity field:

[4]:
t = Parameter(0.)
b = CoefficientFunction((y,-x,0))
Draw (b, mesh, "b")
eps = 5e-5

some local quantities

normal, tangential, co-normal and mesh size

[5]:
n = specialcf.normal(mesh.dim)
h = specialcf.mesh_size
local_tang = specialcf.tangential(mesh.dim)
con = Cross(n,local_tang) #co-normal pointing outside of a surface element
bn = InnerProduct(b,con)

Discretization

Surface FESpaces:

[6]:
fesl2 = SurfaceL2(mesh, order=order)
fesedge = FacetSurface(mesh, order=order)

fes = fesl2*fesedge
u,uE = fes.TrialFunction()
v,vE = fes.TestFunction()

surface gradients, co-normal derivatives and jumps:

[7]:
gradu = u.Trace().Deriv()
gradv = v.Trace().Deriv()
jumpu = u - uE
jumpv = v - vE
dudn = InnerProduct(gradu,con)
dvdn = InnerProduct(gradv,con)

Diffusion formulation (Hybrid Interior Penalty on Surface):

TTuvTTnu(vv^)TTnu(uu^)+αp2hFF(uu^)(vv^)
[8]:
a = BilinearForm(fes)
# diffusion

dr = ds(element_boundary=True)

alpha = 10*(order+1)**2
a += eps*gradu * gradv * ds
a += - eps*dudn * jumpv * dr
a += - eps*dvdn * jumpu * dr
a += eps*alpha/h * jumpu * jumpv * dr

Convection formulation (Hybrid Upwinding):

TTuwv+TT(wn)uhybupwv+TTout(wn)(u^u)v^

with

uhybupw={uif wn(outflow),u^else(inflow).

outflow

inflow

elementupwind

facetupwind

[9]:
a = BilinearForm(fes)
# convection (surface version of Egger+Schöberl formulation):
a += - u * InnerProduct(b,gradv) * ds
a += IfPos(bn, bn*u, bn*uE) * v * dr + IfPos(bn, bn, 0) * (uE - u) * vE * dr
a.Assemble()
[9]:
<ngsolve.comp.BilinearForm at 0x7f95ba36dc30>

Mass matrix:

[10]:
m = BilinearForm(fes)
m += u*v*ds
m.Assemble()
[10]:
<ngsolve.comp.BilinearForm at 0x7f95b9938430>

M-matrix for implicit Euler

[11]:
dt = 0.02

mstar = m.mat.CreateMatrix()
mstar.AsVector().data = m.mat.AsVector() + dt * a.mat.AsVector()
mstarinv = mstar.Inverse()

from math import pi
T = 8*pi

Time stepping

Visualization of solution (Deformation in normal direction)

[12]:
gfu = GridFunction(fes)
gfu.components[0].Set(1.5*exp(-20*(x*x+(y-1)**2+(z)**2)),definedon=mesh.Boundaries("sphere"))

The time loop

[13]:
sceneun = Draw (gfu.components[0]*n, mesh, "un", deformation = True, autoscale=False)
t.Set(0)
for i in range(int(T/dt)):
    gfu.vec.data = mstarinv @ m.mat * gfu.vec
    sceneun.Redraw()
    t.Set(t.Get()+dt)

Remark:

  • We can apply static condensation as in the volume