Bembel
SingleLayerOperator.hpp
1 // This file is part of Bembel, the higher order C++ boundary element library.
2 //
3 // Copyright (C) 2022 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_HOMOGENISEDLAPLACE_SINGLELAYEROPERATOR_HPP_
13 #define BEMBEL_SRC_HOMOGENISEDLAPLACE_SINGLELAYEROPERATOR_HPP_
14 
15 namespace Bembel {
16 // forward declaration of class HomogenisedLaplaceSingleLayerOperator
17 // in order to define traits
18 class HomogenisedLaplaceSingleLayerOperator;
19 
23 template<>
25  typedef Eigen::VectorXd EigenType;
26  typedef Eigen::VectorXd::Scalar Scalar;
27  enum {
28  OperatorOrder = -1,
29  Form = DifferentialForm::Discontinuous,
30  NumberOfFMMComponents = 1
31  };
32 };
33 
40  HomogenisedLaplaceSingleLayerOperator> {
41  // implementation of the kernel evaluation, which may be based on the
42  // information available from the superSpace
43  public:
49  this->deg = getDegree(HomogenisedLaplaceSingleLayerOperator::precision);
50  this->cs = getCoefficients(
51  HomogenisedLaplaceSingleLayerOperator::precision);
52  }
53 
54  template<class T>
55  void evaluateIntegrand_impl(const T &super_space, const SurfacePoint &p1,
56  const SurfacePoint &p2,
57  Eigen::Matrix<
59  >::Scalar, Eigen::Dynamic, Eigen::Dynamic> *intval) const {
60  auto polynomial_degree = super_space.get_polynomial_degree();
61  auto polynomial_degree_plus_one_squared = (polynomial_degree + 1)
62  * (polynomial_degree + 1);
63 
64  // get evaluation points on unit square
65  auto s = p1.segment < 2 > (0);
66  auto t = p2.segment < 2 > (0);
67 
68  // get quadrature weights
69  auto ws = p1(2);
70  auto wt = p2(2);
71 
72  // get points on geometry and tangential derivatives
73  auto x_f = p1.segment < 3 > (3);
74  auto x_f_dx = p1.segment < 3 > (6);
75  auto x_f_dy = p1.segment < 3 > (9);
76  auto y_f = p2.segment < 3 > (3);
77  auto y_f_dx = p2.segment < 3 > (6);
78  auto y_f_dy = p2.segment < 3 > (9);
79 
80  // compute surface measures from tangential derivatives
81  auto x_kappa = x_f_dx.cross(x_f_dy).norm();
82  auto y_kappa = y_f_dx.cross(y_f_dy).norm();
83 
84  // integrand without basis functions
85  auto integrand = evaluateKernel(x_f, y_f) * x_kappa * y_kappa * ws * wt;
86 
87  // multiply basis functions with integrand and add to intval, this is an
88  // efficient implementation of
89  // (*intval) += super_space.basisInteraction(s, t)
90  // * evaluateKernel(x_f, y_f) * x_kappa * y_kappa * ws * wt;
91  super_space.addScaledBasisInteraction(intval, integrand, s, t);
92 
93  return;
94  }
95 
96  Eigen::Matrix<double, 1, 1> evaluateFMMInterpolation_impl(
97  const SurfacePoint &p1, const SurfacePoint &p2) const {
98  // get evaluation points on unit square
99  auto s = p1.segment < 2 > (0);
100  auto t = p2.segment < 2 > (0);
101 
102  // get points on geometry and tangential derivatives
103  auto x_f = p1.segment < 3 > (3);
104  auto x_f_dx = p1.segment < 3 > (6);
105  auto x_f_dy = p1.segment < 3 > (9);
106  auto y_f = p2.segment < 3 > (3);
107  auto y_f_dx = p2.segment < 3 > (6);
108  auto y_f_dy = p2.segment < 3 > (9);
109 
110  // compute surface measures from tangential derivatives
111  auto x_kappa = x_f_dx.cross(x_f_dy).norm();
112  auto y_kappa = y_f_dx.cross(y_f_dy).norm();
113 
114  // interpolation
115  Eigen::Matrix<double, 1, 1> intval;
116  intval(0) = evaluateKernel(x_f, y_f) * x_kappa * y_kappa;
117 
118  return intval;
119  }
120 
124  double evaluateKernel(const Eigen::Vector3d &x,
125  const Eigen::Vector3d &y) const {
126  return k_mod(x - y)
127  + evaluate_solid_sphericals(x - y, this->cs, this->deg, false);
128  }
129 
133  static void setPrecision(double p) {
134  HomogenisedLaplaceSingleLayerOperator::precision = p;
135  }
136 
140  static double getPrecision() {
141  return HomogenisedLaplaceSingleLayerOperator::precision;
142  }
143 
144  private:
146  unsigned int deg;
148  Eigen::VectorXd cs;
150  static double precision;
151 };
152 
153 double HomogenisedLaplaceSingleLayerOperator::precision = 0;
154 
155 } // namespace Bembel
156 
157 #endif // BEMBEL_SRC_HOMOGENISEDLAPLACE_SINGLELAYEROPERATOR_HPP_
This class implements the specification of the integration for the single layer operator for the homo...
double evaluateKernel(const Eigen::Vector3d &x, const Eigen::Vector3d &y) const
Fundamental solution of the Homogenised Laplace problem.
static double getPrecision()
returns the precision of the periodicity of the kernel
HomogenisedLaplaceSingleLayerOperator()
Constructs an object initialising the coefficients and the degree via the static variable precision.
static void setPrecision(double p)
sets the precision of the periodicity of the kernel
Eigen::Matrix< double, 12, 1 > SurfacePoint
typedef of SurfacePoint
Routines for the evalutation of pointwise errors.
Definition: AnsatzSpace.hpp:14
Eigen::VectorXd getCoefficients(double precision)
Calculates the coefficients for the solid harmonics expansion of the periodic kernel .
unsigned int getDegree(double precision)
Returns the degree of the sphericals expansion given a precision. Can be extended,...
double evaluate_solid_sphericals(Eigen::Vector3d x, Eigen::VectorXd cs, unsigned int deg, bool grad)
Evaluates the series for real coefficients cs if grad is false, and for real coefficients cs if gra...
Definition: Sphericals.hpp:128
double k_mod(Eigen::Vector3d in)
Returns the modified kernel .
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...