Perfectly matched layers in NGSolve

6.2. Perfectly matched layers in NGSolve#

In NGSolve PMLs are implemented as additional mesh transformation. First a PML object is generated.

from ngsolve import *
from ngsolve.webgui import Draw

pml_cart = pml.Cartesian((0,0),(0.5,0.5),3j)

pml.Cartesian((xmin, ymin), (xmax,ymax),alpha) generates a cartesian PML with a complex scaling outside of the rectangle \(\Omega_{\mathrm {int}}\) defined by xmin,ymin,xmax,ymax with complex coordinate stretching 1+alpha.

Calling the mapping yields the complex scaled point:

pml_cart(1,0), pml_cart(3,1)
( (1,1.5)
    (0,0),
  (3,7.5)
  (1,1.5))

The PML class also offers the scaling and its Jacobian and determinant as a CoefficientFunction

mesh = Mesh(unit_square.GenerateMesh(maxh=0.1))
Draw(pml_cart.PML_CF.real,mesh,vectors=True)
Draw(pml_cart.PML_CF.imag,mesh,vectors=True)

Draw(pml_cart.Det_CF.real,mesh)
Draw(pml_cart.Det_CF.imag,mesh)

Draw(pml_cart.Jac_CF.real,mesh)
Draw(pml_cart.Jac_CF.imag,mesh)
BaseWebGuiScene

To set a PML to a mesh one may use Mesh.SetPML(PML,domain)

mesh.SetPML(pml_cart,'.*')

Assembling a matrix will now integrate over the “complex” mesh:

fes = H1(mesh, complex = True)

u,v = fes.TnT()

bfm = BilinearForm(u*v*dx).Assemble()

print(bfm.mat[0,0])
(0.0008333333333333365+0.0012500000000000048j)

Different types of PMLs#

There exist different types of scalings e.g., PML.Radial, PML.HalfSpace, PML.BrickRadial

pml_rad = pml.Radial((0,0),0.2)

Draw(pml_rad.PML_CF.imag,mesh,order=5)
BaseWebGuiScene
pml_half = pml.HalfSpace((0.5,0),(2,1))

Draw(pml_half.PML_CF.imag,mesh,order=5)
BaseWebGuiScene
pml_brickrad = pml.BrickRadial((0.2,0.2),(0.4,0.8),(0.3,0.3))

Draw(pml_brickrad.PML_CF.imag,mesh,order=5)
BaseWebGuiScene

Combining PMLs#

PMLs can be combined using +:

sumpml = pml.HalfSpace((0.5,0),(1,0))+pml.HalfSpace((0,0.5),(0.5,1))

Draw(sumpml.PML_CF.imag,mesh,order=5)
BaseWebGuiScene

This can e.g., be used to create a cartesian scaling with different strength in each direction

cart_pml_ani = pml.HalfSpace((0.5,0),(1,0))+pml.HalfSpace((0,0.5),(0,1),5j)

Draw(cart_pml_ani.PML_CF.imag,mesh,order=5)
BaseWebGuiScene

PMLs can also be tensorized using CompoundPML

pml3d = pml.Compound(sumpml,pml.Cartesian((0.2),(0.7)))
mesh = Mesh(unit_cube.GenerateMesh(maxh=0.1))
Draw(pml3d.PML_CF.imag,mesh)
BaseWebGuiScene