Python API#
The BEM interface follows the usual NGSolve form language and mirrors the mathematical notation for boundary integral operators.
Imports#
from ngsolve import *
from ngsolve.bem import *
Boundary Spaces#
Common scalar trace spaces:
SurfaceL2: boundary density space, used for Neumann type traces,H1: volume space whose boundary trace is used for Dirichlet type traces,vector valued operators use spaces such as
VectorH1,HDivSurface, andHCurltraces,triangular and quadrilateral surface elements are supported.
Kernels and Layer Potentials#
Laplace kernel:
Helmholtz outgoing kernel:
Single layer potential:
Double layer potential:
This is the naming convention behind LaplaceSL, LaplaceDL, HelmholtzSL, and HelmholtzDL.
From Paper to Code#
A single layer bilinear form
is written as
V = LaplaceSL(u * ds) * v * ds
u * ds marks the source density on the boundary, LaplaceSL(...) applies the layer potential, and multiplication by v * ds tests the result on the boundary.
Laplace Operators#
Single layer operator:
V = LaplaceSL(u * ds) * v * ds
Double layer operator:
K = LaplaceDL(u_h1 * ds) * v * ds
Helmholtz Operators#
kappa = 4.0
V = HelmholtzSL(u * ds, kappa) * v * ds
K = HelmholtzDL(u * ds, kappa) * v * ds
C = HelmholtzCF(u * ds, kappa) * v * ds
HelmholtzSL: single layer operator,HelmholtzDL: double layer operator,HelmholtzCF: combined field operator for formulations such as Brakhage Werner.
Lamé#
Lamé single layer potential:
The matching NGSolve expression is the same single layer pattern, but with a vector valued density:
fes = VectorH1(mesh, order=order)
u, v = fes.TnT()
L = LameSL(u * ds, E=E, nu=nu) * v * ds
Maxwell#
The NGSolve syntax builds Maxwell blocks from HDivSurface and HCurl traces.
Maxwell layer potentials use the outgoing Helmholtz kernel explicitly. The Maxwell single layer reads as
Single layer potential:
SL = kappa * HelmholtzSL(uHDiv.Trace()*ds, kappa) + 1/ kappa * grad(HelmholtzSL(div(uHDiv.Trace())*ds, kappa))
Single layer operator matrix:
V1 = HelmholtzSL( uHDiv.Trace()*ds, kappa) * vHDiv.Trace() * ds
V2 = HelmholtzSL( div(uHDiv.Trace()) * ds, kappa) * div(vHDiv.Trace()) * ds
V = kappa * V1.mat - 1/kappa * V2.mat
The double layer potential and weak form reads as
Double layer potential:
DL = MaxwellDL(Cross(n, m.Trace()) * ds, kappa)
# or
DL = curl(HelmholtzSL(Cross(n,m.Trace()) * ds, kappa))
Double layer operator:
K = MaxwellDL(Cross(n, m.Trace()) * ds, kappa) * w.Trace() * ds
Available building blocks: LaplaceSL, LaplaceDL, HelmholtzSL, HelmholtzDL, HelmholtzCF, LameSL, and MaxwellDL.
Potential Evaluation#
A potential operator can be evaluated from a grid function density:
SL = LaplaceSL(u * ds)
potential = SL(gfu)
Evaluation on a target boundary region can use a local expansion (FMM evaluation):
potential_on_screen = SL(gfu, target_boundary)
Differentiated potentials use the operator interface:
grad_potential = grad(SL)(gfu)