2D Helmholtz problem coupling FEM and BEM#
We want to solve the acoustic propagation of a plane wave in a heterogeneous medium. In order to do that, we distinguish a domain
Fig. 17 Domains for computation:
Fig. 18 Domains for computation:
We solve
with
We will use:

Fig. 19
We decompose the problem in a coupled system of two equations:
-
in the FEM part, the solution solves the following equation:
which gives the variational formulation
with
is the normal trace of on . -
in the BEM part, we solve
The scattered field verifies
with
the total field solution of the equation and the normal trace of on , and are the single and double layer boundary potentialsand
Since
, and taking the limit when goes to , we obtain the integral equationThe resulting variational formulation for the BEM part is then
By adding the variational formulations relatives to the two linked problems, we obtain the final variational formulation.
Finally, the solution is obtained directly from
The last step is to merge the FEM solution in

Fig. 20 Solution of the FEM-BEM problem.#
The code of this example follows:
#include "xlife++.h"
using namespace xlifepp;
using namespace std;
// find = eta(x)
Real find(const Point & M, Parameters & pa = defaultParameters)
{
Real res=1.;
if (std::max(std::abs(M[0]), std::abs(M[1])) < 0.5)
res=std::exp(-((M[0]*M[0]-0.25)*(M[1]*M[1]-0.25))/(2.*0.05));
return res;
}
Real eta2(const Point & M, Parameters & pa = defaultParameters)
{
Real tmp=find(M);
return tmp*tmp;
}
Complex g1(const Point& M, Parameters& pa = defaultParameters)
{
Real k=real(pa("k"));
Point d(1., 0.);
return exp(i_*(k*dot(M, d)));
}
int main(int argc, char** argv)
{
init(argc, argv, _lang=en); // mandatory initialization of xlifepp
verboseLevel(10);
Real k=10.;
// meshing
Real hsize=(2*pi_/k)/15.;
SquareGeo sp(_center=Point(0., 0.), _length=1., _hsteps=hsize, _domain_name="Omega", _side_names="Gamma");
Mesh m1=Mesh(sp, _shape=triangle, _generator=gmsh);
Domain omega = m1.domain("Omega");
Domain gamma = m1.domain("Gamma");
theCout << "Mesh size = " << hsize << eol;
theCout << "Number of Triangles = " << m1.nbOfElements() << eol;
// defining parameter and kernel
Parameters pars;
pars << Parameter(k, "k");
Kernel G=Helmholtz2dKernel(pars);
Function finc(g1, pars);
// defining space, unknown and test function
Space V1(_domain=omega, _interpolation=P1, _name="V1", _notOptimizeNumbering);
Space V0(_domain=gamma, _interpolation=P1, _name="V0", _notOptimizeNumbering);
Unknown u1(V1, _name="u1"); TestFunction v1(u1, _name="v1");
Unknown l0(V0, _name="l0"); TestFunction lt0(l0, _name="lt0");
theCout << "Nb dofs BEM= " << V0.nbDofs() << " Nb dofs FEM= " << V1.nbDofs() << eol;
// defining bilinear and linear form
IntegrationMethods ims(_method=Duffy, _order=15, _bound=0., _quad=defaultQuadrature, _order=12, _bound=1.,
_quad=defaultQuadrature, _order=10, _bound=2., _quad=defaultQuadrature, _order=8);
BilinearForm blf=intg(omega, grad(u1)|grad(v1))-k*k*intg(omega, eta2*u1*v1) - intg(gamma, l0*v1) + 0.5*intg(gamma, u1*lt0)
- intg(gamma, gamma, u1*ndotgrad_y(G)*lt0, _method=ims) + intg(gamma, gamma, l0*G*lt0, _method=ims);
LinearForm lf=intg(gamma, finc*lt0);
// computing FEM/BEM matrix and right hand side vector
TermMatrix lhs(blf, _name="lhs");
TermVector rhs(lf);
// solving linear system using direct method
TermVector sol=directSolve(lhs, rhs);
// Representing the solution FEM and BEM
SquareGeo Sint(_center=Point(0., 0.), _length=1, _hsteps=hsize, _domain_name="S_int");
SquareGeo Sext(_center=Point(0., 0.), _length=3, _hsteps=1.5*hsize, _domain_name="S_ext");
Mesh mrep(Sext+Sint, _shhape=triangle, _generator=gmsh);
Domain S_ext=mrep.domain("S_ext"), S_int=mrep.domain("S_int");
Domain S=merge(S_ext, S_int, "S");
Space Vrep(_domain=S, _interpolation=P1, _name="Vrep", _notOptimizeNumbering);
Unknown ur(Vrep, _name="ur");
Function Find(find, pars);
TermVector findex(ur, S, Find);
saveToFile("findex", findex, _format=vtu); // Representing eta
TermVector Uint=interpolate(ur, S_int, sol(u1)); // FEM solution (total field)
saveToFile("Uint", Uint, _format=vtu);
// Representing of the BEM part
IntegrationMethods imr(_quad=GaussLegendre, _order=20, _bound=1., _quad=GaussLegendre, _order=10, _bound=2.,
_quad=GaussLegendre, _order=5);
TermVector Uext = - integralRepresentation(ur, S_ext, intg(gamma, G*sol(l0), _method=imr))
+ integralRepresentation(ur, S_ext, intg(gamma, ndotgrad_y(G)*sol(u1), _method=imr));
TermVector Uinc(ur, S_ext, finc);
saveToFile("Uinc", Uinc, _format=vtu); // Incident field
saveToFile("Uext", Uext, _format=vtu); // scattered field in exterior domain
TermVector Uext_t = Uext + Uinc;
saveToFile("Uext_t", Uext_t, _format=vtu); // Total field in exterior domain
TermVector U=merge(Uint, Uext_t); // Merged FEM and BEM solutions
saveToFile("U", U, _format=vtu);
theCout << "Program finished" << eol;
return 0;
}