NiHu  2.0
helmholtz_kernel.hpp
Go to the documentation of this file.
1 // This file is a part of NiHu, a C++ BEM template library.
2 //
3 // Copyright (C) 2012-2014 Peter Fiala <fiala@hit.bme.hu>
4 // Copyright (C) 2012-2014 Peter Rucz <rucz@hit.bme.hu>
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
25 #ifndef HELMHOLTZ_KERNEL_HPP_INCLUDED
26 #define HELMHOLTZ_KERNEL_HPP_INCLUDED
27 
28 #include <boost/math/constants/constants.hpp>
29 
30 #include <cmath>
31 
32 #include "../core/global_definitions.hpp"
33 #include "../core/gaussian_quadrature.hpp"
34 #include "../util/math_functions.hpp"
37 #include "wave_number_kernel.hpp"
38 
39 #include "laplace_kernel.hpp"
40 
41 namespace NiHu
42 {
43 template <class Space, class WaveNumber>
45 
47 namespace distance_dependent_kernel_traits_ns
48 {
49  template <class Space, class WaveNumber>
50  struct space<helmholtz_kernel<Space, WaveNumber> > : Space {};
51 
52  template <class Space, class WaveNumber>
53  struct result<helmholtz_kernel<Space, WaveNumber> >
54  {
55  typedef std::complex<typename Space::scalar_t> type;
56  };
57 
58  template <class Space, class WaveNumber>
59  struct quadrature_family<helmholtz_kernel<Space, WaveNumber> >
60  : gauss_family_tag {};
61 
62  template <class Space, class WaveNumber>
63  struct is_singular<helmholtz_kernel<Space, WaveNumber> > : std::true_type {};
64 
65  template <class Space, class WaveNumber>
66  struct singular_core<helmholtz_kernel<Space, WaveNumber> > {
68  };
69 
70  template <class Space, class WaveNumber>
71  struct singular_quadrature_order<helmholtz_kernel<Space, WaveNumber> >
72  : std::integral_constant<unsigned, 7> {};
73 
74  template <class Scalar, class WaveNumber>
75  struct far_field_behaviour<helmholtz_kernel<space_2d<Scalar>, WaveNumber> >
76  : asymptotic::log<1> {};
77 
78  template <class Scalar, class WaveNumber>
79  struct singularity_type<helmholtz_kernel<space_2d<Scalar>, WaveNumber> >
80  : asymptotic::log<1> {};
81 
82  template <class Scalar, class WaveNumber>
83  struct far_field_behaviour<helmholtz_kernel<space_3d<Scalar>, WaveNumber> >
84  : asymptotic::inverse<1> {};
85 
86  template <class Scalar, class WaveNumber>
87  struct singularity_type<helmholtz_kernel<space_3d<Scalar>, WaveNumber> >
88  : asymptotic::inverse<1> {};
89 } // distance_dependent_kernel_traits_ns
90 
91 
92 template <class scalar, class WaveNumber>
93 class helmholtz_kernel<space_2d<scalar>, WaveNumber>
94  : public wave_number_kernel<WaveNumber>
95  , public distance_dependent_kernel<helmholtz_kernel<space_2d<scalar>, WaveNumber> >
96 {
97 public:
100  >::type result_t;
101 
102 private:
103  void eval_impl(std::integral_constant<unsigned, 0>, scalar r, result_t *f) const
104  {
105  auto z = this->get_wave_number() * r;
106  auto H0 = bessel::H<0, 2>(std::complex<scalar>(z));
107  *f = std::complex<scalar>(0, -.25) * H0;
108  }
109 
110  void eval_impl(std::integral_constant<unsigned, 1>, scalar r, result_t *f) const
111  {
112  auto const &k = this->get_wave_number();
113  auto z = k * r;
114  auto H1 = bessel::H<1, 2>(std::complex<scalar>(z));
115  *f = std::complex<scalar>(0, .25) * this->get_wave_number() * H1;
116  }
117 
118  void eval_impl(std::integral_constant<unsigned, 2>, scalar r, result_t *f) const
119  {
120  auto const &k = this->get_wave_number();
121  auto z = k * r;
122  auto H0 = bessel::H<0, 2>(std::complex<scalar>(z));
123  auto H1 = bessel::H<1, 2>(std::complex<scalar>(z));
124  auto H2 = bessel::H<2, 2>(std::complex<scalar>(z));
125  f[1] = std::complex<scalar>(0, .25) * k*k * (H1/z);
126  f[0] = std::complex<scalar>(0, -.25) * k*k * (.5 * H2 - .5 * H0 + H1/z);
127  }
128 
129  void eval_impl(std::integral_constant<unsigned, 3>, scalar r, result_t *f) const
130  {
131  f[0] = f[1] = result_t(0);
132  }
133 
134 public:
135  helmholtz_kernel(WaveNumber const &k)
137  {
138  }
139 
140  template <unsigned order>
141  void eval(scalar r, std::complex<scalar> *f) const
142  {
143  eval_impl(std::integral_constant<unsigned, order>(), r, f);
144  }
145 };
146 
147 
148 template <class scalar, class WaveNumber>
149 class helmholtz_kernel<space_3d<scalar>, WaveNumber>
150  : public wave_number_kernel<WaveNumber>
151  , public distance_dependent_kernel<helmholtz_kernel<space_3d<scalar>, WaveNumber> >
152 {
153 public:
156  >::type result_t;
157 
158 private:
159  void eval_impl(std::integral_constant<unsigned, 0>, scalar r, result_t *f) const
160  {
161  using namespace boost::math::double_constants;
162  auto kr = this->get_wave_number() * r;
163  auto ikr = result_t(0,1) * kr;
164  f[0] = std::exp(-ikr) / r / (4. * pi);
165  }
166 
167 
168  void eval_impl(std::integral_constant<unsigned, 1>, scalar r, result_t *f) const
169  {
170  using boost::math::double_constants::pi;
171  auto kr = this->get_wave_number() * r;
172  auto ikr = result_t(0,1) * kr;
173  f[0] = std::exp(-ikr) / (r*r) / (4. * pi) * (-ikr - 1.);
174  }
175 
176 
177  void eval_impl(std::integral_constant<unsigned, 2>, scalar r, result_t *f) const
178  {
179  using boost::math::double_constants::pi;
180  auto ikr = result_t(0,1) * (this->get_wave_number() * r);
181  auto g = std::exp(-ikr) / (r*r*r) / (4. * pi);
182  f[1] = -g * (1. + ikr);
183  f[0] = g * (3. + ikr * (3. + ikr));
184  }
185 
186 
187  void eval_impl(std::integral_constant<unsigned, 3>, scalar r, result_t *f) const
188  {
189  using boost::math::double_constants::pi;
190  auto ikr = result_t(0,1) * (this->get_wave_number() * r);
191  auto g = std::exp(-ikr)/(r*r*r*r) / (4. * pi);
192  f[1] = g * (3. + ikr * (3. + ikr));
193  f[0] = -g * (15. + ikr * (15 + ikr * (6 + ikr)));
194  }
195 
196 public:
197  helmholtz_kernel(WaveNumber const &k)
199  {
200  }
201 
202  template <unsigned order>
203  void eval(scalar r, result_t *f) const
204  {
205  this->eval_impl(std::integral_constant<unsigned, order>(), r, f);
206  }
207 };
208 
210 namespace kernel_traits_ns
211 {
212  template <class Scalar, class WaveNumber>
214  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 0, 0>
215  > : asymptotic::log<1> {};
216 
217  template <class Scalar, class WaveNumber>
219  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 0, 0>
220  > : asymptotic::log<1> {};
221 
223  template <class Scalar, class WaveNumber>
225  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 0, 1>
226  > : asymptotic::inverse<1> {};
227 
229  template <class Scalar, class WaveNumber>
231  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 0, 1>
232  > : asymptotic::inverse<1> {};
233 
235  template <class Scalar, class WaveNumber>
237  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 1, 0>
238  > : asymptotic::inverse<1> {};
239 
241  template <class Scalar, class WaveNumber>
243  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 1, 0>
244  > : asymptotic::inverse<1> {};
245 
247  template <class Scalar, class WaveNumber>
249  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 1, 1>
250  > : asymptotic::inverse<2> {};
251 
253  template <class Scalar, class WaveNumber>
255  normal_derivative_kernel<helmholtz_kernel<space_2d<Scalar>, WaveNumber>, 1, 1>
256  > : asymptotic::inverse<2> {};
257 
258 }
259 
261 namespace kernel_traits_ns
262 {
263  template <class Scalar, class WaveNumber, int Nx, int Ny>
265  normal_derivative_kernel<helmholtz_kernel<space_3d<Scalar>, WaveNumber>, Nx, Ny>
266  > : asymptotic::inverse<1 + Nx + Ny> {};
267 
268  template <class Scalar, class WaveNumber, int Nx, int Ny>
270  normal_derivative_kernel<helmholtz_kernel<space_3d<Scalar>, WaveNumber>, Nx, Ny>
271  > : asymptotic::inverse<1 + Nx + Ny> {};
272 
273  // the normal derivative on the smooth boundary cancels the 1/r^2
274  // singularity of the kernel's derivative
275  template <class Scalar, class WaveNumber>
277  normal_derivative_kernel<helmholtz_kernel<space_3d<Scalar>, WaveNumber>, 0, 1>
278  > : asymptotic::inverse<1> {};
279 
280  // the normal derivative on the smooth boundary cancels the 1/r^2
281  // singularity of the kernel's derivative
282  template <class Scalar, class WaveNumber>
284  normal_derivative_kernel<helmholtz_kernel<space_3d<Scalar>, WaveNumber>, 1, 0>
285  > : asymptotic::inverse<1> {};
286 } // end of namespace kernel_traits_ns
287 
288 
289 
291 template <class WaveNumber>
294 template <class WaveNumber>
297 template <class WaveNumber>
300 template <class WaveNumber>
303 template <class WaveNumber>
306 template <class WaveNumber>
309 template <class WaveNumber>
312 template <class WaveNumber>
315 template <class WaveNumber>
317 
318 } // end of namespace NiHu
319 
320 #endif // HELMHOLTZ_KERNEL_HPP_INCLUDED
321 
NiHu::helmholtz_kernel
Definition: helmholtz_kernel.hpp:44
NiHu::distance_dependent_kernel_traits_ns::quadrature_family
Definition: distance_dependent_kernel.hpp:29
NiHu::kernel_traits_ns::singularity_type
return the kernel's singularity type
Definition: kernel.hpp:59
laplace_kernel.hpp
implementation of kernels of the Laplace equation
NiHu::asymptotic::log
logarithmic singularity with specified order
Definition: asymptotic_types.hpp:41
NiHu::scalar
metafunction returning the scalar type
Definition: matrix_traits.hpp:66
NiHu::distance_dependent_kernel_traits_ns::far_field_behaviour
Definition: distance_dependent_kernel.hpp:41
NiHu::distance_dependent_kernel_traits_ns::singular_core
Definition: distance_dependent_kernel.hpp:35
NiHu::space
class representing a coordinate space with a scalar and a dimension
Definition: space.hpp:36
NiHu::distance_dependent_kernel_traits_ns::result
Definition: distance_dependent_kernel.hpp:26
NiHu::distance_dependent_kernel_traits_ns::singular_quadrature_order
Definition: distance_dependent_kernel.hpp:38
NiHu::distance_dependent_kernel
Definition: distance_dependent_kernel.hpp:18
distance_dependent_kernel.hpp
Class NiHu::distance_dependent_kernel.
NiHu::laplace_kernel
Kernel of the Laplace equation in two and three dimensions.
Definition: laplace_kernel.hpp:45
NiHu::distance_dependent_kernel_traits_ns::is_singular
Definition: distance_dependent_kernel.hpp:32
NiHu::distance_dependent_kernel_traits_ns::space
Definition: distance_dependent_kernel.hpp:23
NiHu::kernel_traits_ns::far_field_behaviour
return the far field asymptotic behaviour of the kernel
Definition: kernel.hpp:51
normal_derivative_kernel.hpp
Class NiHu::normal_derivative_kernel.
NiHu::asymptotic::inverse
inverse singularity with specified order
Definition: asymptotic_types.hpp:50
NiHu::normal_derivative_kernel
Normal derivative of a distance dependent kernel.
Definition: normal_derivative_kernel.hpp:26
NiHu::wave_number_kernel
Definition: wave_number_kernel.hpp:8
NiHu::distance_dependent_kernel_traits_ns::singularity_type
Definition: distance_dependent_kernel.hpp:44
NiHu::gauss_family_tag
tag for the family of Gaussian quadratures
Definition: gaussian_quadrature.hpp:517