Bembel
 
Loading...
Searching...
No Matches
HypersingularOperator.hpp
1// This file is part of Bembel, the higher order C++ boundary element library.
2//
3// Copyright (C) 2024 see <http://www.bembel.eu>
4//
5// It was written as part of a cooperation of J. Doelz, H. Harbrecht, S. Kurz,
6// M. Multerer, S. Schoeps, and F. Wolf at Technische Universitaet Darmstadt,
7// Universitaet Basel, and Universita della Svizzera italiana, Lugano. This
8// source code is subject to the GNU General Public License version 3 and
9// provided WITHOUT ANY WARRANTY, see <http://www.bembel.eu> for further
10// information.
11//
12#ifndef BEMBEL_SRC_HELMHOLTZ_HYPERSINGULAROPERATOR_HPP_
13#define BEMBEL_SRC_HELMHOLTZ_HYPERSINGULAROPERATOR_HPP_
14
15namespace Bembel {
16// forward declaration of class HelmholtzHypersingularOperator in order to
17// define traits
18class HelmholtzHypersingularOperator;
19
20template <>
22 typedef Eigen::VectorXcd EigenType;
23 typedef Eigen::VectorXcd::Scalar Scalar;
24 enum {
25 OperatorOrder = 1,
26 Form = DifferentialForm::Continuous,
27 NumberOfFMMComponents = 3
28 };
29};
30
35 : public LinearOperatorBase<HelmholtzHypersingularOperator> {
36 // implementation of the kernel evaluation, which may be based on the
37 // information available from the superSpace
38 public:
40 template <class T>
41 void evaluateIntegrand_impl(const T &super_space, const SurfacePoint &p1,
42 const SurfacePoint &p2,
43 Eigen::MatrixXcd *intval) const {
44 auto polynomial_degree = super_space.get_polynomial_degree();
45 auto polynomial_degree_plus_one_squared =
46 (polynomial_degree + 1) * (polynomial_degree + 1);
47
48 // get evaluation points on unit square
49 Eigen::Vector2d s = p1.segment<2>(0);
50 Eigen::Vector2d t = p2.segment<2>(0);
51
52 // get quadrature weights
53 double ws = p1(2);
54 double wt = p2(2);
55
56 // get points on geometry and tangential derivatives
57 Eigen::Vector3d x_f = p1.segment<3>(3);
58 Eigen::Vector3d x_f_dx = p1.segment<3>(6);
59 Eigen::Vector3d x_f_dy = p1.segment<3>(9);
60 Eigen::Vector3d y_f = p2.segment<3>(3);
61 Eigen::Vector3d y_f_dx = p2.segment<3>(6);
62 Eigen::Vector3d y_f_dy = p2.segment<3>(9);
63
64 // compute surface measures from tangential derivatives
65 Eigen::Vector3d x_n = x_f_dx.cross(x_f_dy);
66 Eigen::Vector3d y_n = y_f_dx.cross(y_f_dy);
67
68 // compute h
69 double h =
70 1. / (1 << super_space.get_refinement_level()); // h = 1 ./ (2^M)
71
72 // evaluate kernel
73 std::complex<double> kernel = evaluateKernel(x_f, y_f);
74
75 // integrand without basis functions
76 std::complex<double> integrandScalar =
77 -kernel * x_n.dot(y_n) * wavenumber2_ * ws * wt;
78 std::complex<double> integrandCurl =
79 kernel * x_n.norm() * y_n.norm() * ws * wt / h / h;
80
81 // multiply basis functions with integrand and add to intval, this is an
82 // efficient implementation of
83 super_space.addScaledBasisInteraction(intval, integrandScalar, s, t);
84 super_space.addScaledSurfaceCurlInteraction(intval, integrandCurl, p1, p2);
85
86 return;
87 }
88
89 Eigen::Matrix<std::complex<double>, 3, 3> evaluateFMMInterpolation_impl(
90 const SurfacePoint &p1, const SurfacePoint &p2) const {
91 // get evaluation points on unit square
92 Eigen::Vector2d s = p1.segment<2>(0);
93 Eigen::Vector2d t = p2.segment<2>(0);
94
95 // get points on geometry and tangential derivatives
96 Eigen::Vector3d x_f = p1.segment<3>(3);
97 Eigen::Vector3d x_f_dx = p1.segment<3>(6);
98 Eigen::Vector3d x_f_dy = p1.segment<3>(9);
99 Eigen::Vector3d y_f = p2.segment<3>(3);
100 Eigen::Vector3d y_f_dx = p2.segment<3>(6);
101 Eigen::Vector3d y_f_dy = p2.segment<3>(9);
102
103 // compute surface measures from tangential derivatives
104 Eigen::Vector3d x_n = x_f_dx.cross(x_f_dy);
105 Eigen::Vector3d y_n = y_f_dx.cross(y_f_dy);
106
107 // evaluate kernel
108 std::complex<double> kernel = evaluateKernel(x_f, y_f);
109
110 // interpolation
111 Eigen::Matrix<std::complex<double>, 3, 3> intval;
112 intval.setZero();
113 intval(0, 0) = -kernel * wavenumber2_ * x_n.dot(y_n);
114 intval(1, 1) = kernel * x_f_dy.dot(y_f_dy);
115 intval(1, 2) = -kernel * x_f_dy.dot(y_f_dx);
116 intval(2, 1) = -kernel * x_f_dx.dot(y_f_dy);
117 intval(2, 2) = kernel * x_f_dx.dot(y_f_dx);
118
119 return intval;
120 }
121
125 std::complex<double> evaluateKernel(const Eigen::Vector3d &x,
126 const Eigen::Vector3d &y) const {
127 auto r = (x - y).norm();
128 return std::exp(-std::complex<double>(0., 1.) * wavenumber_ * r) / 4. /
129 BEMBEL_PI / r;
130 }
132 // setters
134 void set_wavenumber(std::complex<double> wavenumber) {
135 wavenumber_ = wavenumber;
136 wavenumber2_ = wavenumber_ * wavenumber_;
137 }
139 // getters
141 std::complex<double> get_wavenumber() { return wavenumber_; }
142
143 private:
144 std::complex<double> wavenumber_;
145 std::complex<double> wavenumber2_;
146};
147
153template <typename InterpolationPoints>
184
185} // namespace Bembel
186#endif // BEMBEL_SRC_HELMHOLTZ_HYPERSINGULAROPERATOR_HPP_
std::complex< double > evaluateKernel(const Eigen::Vector3d &x, const Eigen::Vector3d &y) const
Fundamental solution of Helmholtz problem.
Eigen::Matrix< double, 12, 1 > SurfacePoint
typedef of SurfacePoint
Eigen::MatrixXd moment2DComputer(const SuperSpace< LinOp > &super_space, const int cluster_level, const int cluster_refinements, const int number_of_points)
Computes a single 2D moment for the FMM by tensorisation of the 1D moments.
Routines for the evalutation of pointwise errors.
constexpr int getFunctionSpaceOutputDimension()
Computes 1D moment for FMM using derivatives of the basis functions. All calculations ar performed on...
Computes 1D moment for FMM. All calculations ar performed on [0,1].
Computes all 2D moment for the FMM by tensorisation of the 1D moments. Specialice this for your linea...
linear operator base class. this serves as a common interface for existing linear operators.
struct containing specifications on the linear operator has to be specialized or derived for any part...
The superspace manages local polynomial bases on each element of the mesh and provides an interface t...