# 2.14 Coupling of FEM with plane waves¶

In this tutorial we define global basis functions via Python. As an example, we choose out-going plane waves in a wave-guide.

[1]:

from ngsolve import *
from netgen.occ import *
from ngsolve.webgui import Draw

[2]:

r1 = Rectangle(1,1).Face()
r1.edges.Min(Y).name = "dir"
r1.edges.Max(Y).name = "dir"
r1.edges.Min(X).name = "dir"
r1.edges.Max(X).name = "coupling"
r1.faces.name = "fem"
circ = Circle((0.4,0.7),0.02).Face()
circ.faces.name = "femsource"

circ2 = Circle((0.4,0.3),0.05).Face()
circ2.faces.name = "femobstacle"

r2 = MoveTo(1,0).Rectangle(3,1).Face()
r2.edges.Min(Y).name = "dir"
r2.edges.Max(Y).name = "dir"
r2.faces.name = "waves"
shape = Glue([r1-circ-circ2, circ,circ2,r2])


The left side is discretized by finite elements. On the right side we use (propagating and evanescent) plane waves. On the interface both fields are coupled by a ultra-weak variational formulation.

[3]:

Draw (shape);

[4]:

geo = OCCGeometry(shape, dim=2)
mesh = Mesh(geo.GenerateMesh(maxh=0.2)).Curve(3)
Draw (mesh);


## outgoing plane waves:¶

$\sin (k_{y,j} y) e^{i k_{x,j} x}$

with \begin{eqnarray*} k_{y,j} & = & j \pi \\ k_{x,j} & = & \sqrt{\omega^2 - k_{y,j}^2} \end{eqnarray*}

Define them as multidimensional CoefficientFunction:

[5]:

omega = 3.5*pi * (1+0j)

ky = [j*pi for j in range(1,5)]
kx = [sqrt(omega**2-kyi**2) for kyi in ky]
k = zip(ky,kx)
shapes = CF(tuple(sin(kyi*y)*exp(1j*kxi*x) for kyi,kxi in k))
dshapesx = shapes.Diff(x)

[6]:

Draw (shapes[2], mesh, animate_complex=True );

[7]:

from ngsolve.comp import GlobalSpace

fesfem = H1(mesh, order=4, definedon="fem.*", dirichlet="dir", complex=True)
profile=sin(pi*y)
feswaves = GlobalSpace (mesh, definedon="waves", basis = shapes)
fes = fesfem*feswaves

[8]:

fes.ndof, fesfem.ndof, feswaves.ndof

[8]:

(3685, 3681, 4)


Bilinear-form:

$\int_{\Omega_{FEM}} \nabla u \nabla v - \omega^2 \varepsilon u v dx + \int_{\gamma_{coupling}} - u \partial_n v_w - v \partial_n u_w + u_w \partial_n v_w$
[9]:

u,v = fes.TnT()
(uf,uw), (vf,vw) = fes.TnT()
uwdx = uw.Operator("dn")
vwdx = vw.Operator("dn")

epsilon = mesh.MaterialCF( { "obstacle" : 10 }, 1)

a = BilinearForm(fes)
a += (-uf*vwdx-vf*uwdx+uw.Trace()*vwdx)*ds("coupling")
a.Assemble()

f = LinearForm(1*vf*dx("femsource")).Assemble()

[10]:

gfu = GridFunction(fes)
gfu.vec.data = a.mat.Inverse(fes.FreeDofs()) * f.vec

gfu2 = mesh.MaterialCF( { "fem.*" : gfu.components[0], "waves" : gfu.components[1] })
Draw (gfu2, mesh, animate_complex=True );

[ ]:



[ ]: