from ngsolve import *
from netgen.occ import *
from ngsolve.krylovspace import CG, GMRes
from ngsolve.webgui import Draw
from ngsolve.bem import *
keys: homogeneous Laplace bvp with mixed conditions, Calderon projector, Dirichlet data, Neumann data
Laplace with Mixed Conditions#
We consider an interior boundary value problem with mixed boundary conditions like this:
\( \left\{ \begin{array}{r rcl r} & \Delta u &=& 0 &\mathrm{in}\; \Omega\,,\\ \textnormal{Dirichlet condition} & \gamma_0 u &=& m & \mathrm{on}\; \Gamma_0\,,\\ \textnormal{Neumann condition} & \gamma_1 u &=& j & \mathrm{on}\; \Gamma_1\,. \end{array} \right. \quad\quad\quad\) |
|
The following representation formula for the solution \(u\) holds:
Define the geometry and the mesh:
topsphere = Sphere((0,0,0), 1) * Box((-1,-1,0),(1,1,1))
botsphere = Sphere((0,0,0), 1) - Box((-1,-1,0),(1,1,1))
topsphere.faces.name = "neumann"
botsphere.faces.name = "dirichlet"
shape = Fuse( [topsphere,botsphere] )
order = 3
mesh = Mesh(OCCGeometry(shape).GenerateMesh(maxh=0.25)).Curve(order)
Draw (mesh);
Define the finite element product space \(H^{\frac12}(\Gamma)\times H^{-\frac12}(\Gamma)\) with \(H^{\frac12}(\Gamma)\) conforming elements for the Dirichlet and \(H^{-\frac12}(\Gamma)\) for the Neumann trace.
# use L2 conform elements for the Neumann trace, label all dofs where Neumann data is given:
fesL2 = SurfaceL2(mesh, order=order-1, dirichlet="neumann")
# use H1 conform elements for the Dirichlet trace, label all dofs where Dirichlet data is given:
fesH1 = H1(mesh, order=order, dirichlet="dirichlet", definedon=mesh.Boundaries(".*"))
fes = fesH1 * fesL2
fes.ndof
uH1,uL2 = fes.TrialFunction()
vH1,vL2 = fes.TestFunction()
print ("ndofL2 = ", fesL2.ndof, "ndofH1 = ", fesH1.ndof, "ndof fes =", fes.ndof)
ndofL2 = 2736 ndofH1 = 2116 ndof fes = 4852
Compute and set the Dirichlet and the Neumann data:
uexa = CF(x)
mj = GridFunction(fes)
mjexa = GridFunction(fes)
mjexa.components[0].Interpolate(uexa, definedon=mesh.Boundaries(".*"))
mj.components[0].Set( mjexa.components[0], definedon=mesh.Boundaries("dirichlet")) # given Dirichlet data m
n = specialcf.normal(3)
gradn_uexa = CF((uexa.Diff(x), uexa.Diff(y), uexa.Diff(z))) * n
mjexa.components[1].Interpolate(gradn_uexa, definedon=mesh.Boundaries(".*"))
mj.components[1].Set( mjexa.components[1], definedon=mesh.Boundaries("neumann")) # given Neumann data j
Draw(mj.components[0], mesh, draw_vol=False);
Boundary Integral Equation
The Calderon projector relates the Dirichlet and the Neumann traces of the solution \(u\), i.e.,
and we use it to solve for the Dirchlet trace on \(\Gamma_1\) and the Neumann trace on \(\Gamma_0\).
Compute boundary integral operators \(\mathrm{V}, \mathrm{K}, \mathrm{D}\) and the mass matrix \(\mathrm{M}\):
eps = 1e-6
intorder = 2 * order + 6
with TaskManager():
V = LaplaceSL( uL2*ds ) * vL2*ds
K = LaplaceDL( uH1*ds ) * vL2*ds
D = LaplaceSL( curl(uH1)*ds ) * curl(vH1)*ds
M = BilinearForm( uH1 * vL2 * ds(bonus_intorder=3)).Assemble()
Insert all given data in the Dirichlet-to-Neumann map and compute the right hand side vector:
with TaskManager():
rhs = ((0.5 * ( M.mat + M.mat.T) + ( K.mat - K.mat.T) - V.mat - D.mat) * mj.vec).Evaluate()
lhs = V.mat - K.mat + K.mat.T + D.mat
Solve for the missing trace data:
with TaskManager():
pre = BilinearForm( (uH1 * vH1 + uL2 * vL2) * ds(bonus_intorder=3) ).Assemble().mat.Inverse(freedofs=fes.FreeDofs())
sol = GMRes(A=lhs, b=rhs, pre=pre, tol=1e-8, maxsteps=500, printrates=False)
Have a look at the Neumann data on \(\Gamma_0\) and compute the error:
gf = GridFunction(fes)
gf.vec[:] = sol
gfj = gf.components[1]
print ("Neumann error =", sqrt(Integrate(Norm(gfj + mj.components[1] - mjexa.components[1])**2, mesh.Boundaries(".*"), BND)))
Draw (gfj, mesh.Boundaries("dirichlet"));
Neumann error = 0.00030086008584905217
Have a look at the Dirichlet data on \(\Gamma_1\) and compute the error:
gfm = gf.components[0]
print ("Dirichlet error =", sqrt(Integrate(Norm(gfm + mj.components[0] - mjexa.components[0])**2, mesh.Boundaries(".*"), BND)))
Draw (gfm, mesh.Boundaries("neumann"));
Dirichlet error = 7.886510364731268e-06
Evaluation of the Solution
screen = WorkPlane(Axes((0,0,0), Z, X)).RectangleC(0.5,0.5).Face()
screen.faces.name="screen"
mesh_screen = Mesh(OCCGeometry(screen).GenerateMesh(maxh=0.1)).Curve(1)
fes_screen = H1(mesh_screen, order=13)
gf_screen = GridFunction(fes_screen)
SLPotential = LaplaceSL(uL2*ds(bonus_intorder=intorder))
DLPotential = LaplaceDL(uH1*ds(bonus_intorder=intorder))
repformula = SLPotential(gf) - DLPotential(gf) + SLPotential(mj) - DLPotential(mj)
with TaskManager():
gf_screen.Set(repformula, definedon=mesh_screen.Boundaries("screen"), dual=False)
Draw(gf_screen)
BaseWebGuiScene
