NiHu  2.0
helmholtz_2d_singular_double_integrals.hpp
1 // This file is a part of NiHu, a C++ BEM template library.
2 //
3 // Copyright (C) 2012-2018 Peter Fiala <fiala@hit.bme.hu>
4 // Copyright (C) 2012-2018 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 
22 #ifndef NIHU_HELMHOLTZ_2D_SINGULAR_DOUBLE_INTEGRALS_HPP_INCLUDED
23 #define NIHU_HELMHOLTZ_2D_SINGULAR_DOUBLE_INTEGRALS_HPP_INCLUDED
24 
25 #include <boost/math/constants/constants.hpp>
26 
27 #include "helmholtz_kernel.hpp"
28 #include "field_type_helpers.hpp"
29 #include "lib_element.hpp"
31 #include "normal_derivative_singular_integrals.hpp"
32 #include "../core/match_types.hpp"
33 #include "../core/singular_integral_shortcut.hpp"
34 #include "../util/math_functions.hpp"
35 
36 namespace NiHu
37 {
38 
50 template <class TestField, class TrialField, size_t order>
52 {
53  typedef TestField test_field_t;
54  typedef TrialField trial_field_t;
55 
56  typedef typename test_field_t::nset_t test_shape_t;
57  typedef typename trial_field_t::nset_t trial_shape_t;
58 
59  static size_t const nTest = test_shape_t::num_nodes;
60  static size_t const nTrial = trial_shape_t::num_nodes;
61 
62  typedef Eigen::Matrix<std::complex<double>, nTest, nTrial> result_t;
63 
64  typedef typename trial_field_t::elem_t elem_t;
65  typedef typename elem_t::domain_t domain_t;
66 
67  typedef typename domain_t::xi_t xi_t;
68  typedef typename elem_t::x_t x_t;
69 
71 
72 public:
77  template <class wave_number_t>
78  static result_t eval(elem_t const &elem, wave_number_t const &k)
79  {
80  using namespace boost::math::double_constants;
81 
82 #ifdef NIHU_PRINT_DEBUG
83  static bool printed = false;
84  if (!printed) {
85  std::cout << "Using helmholtz_2d_SLP_galerkin_face_general" << std::endl;
86  printed = true;
87  }
88 #endif
90  kernel_t kernel(k);
91 
92  result_t I = result_t::Zero();
93 
94  // loop over u
95  for (auto itu = quadrature_t::quadrature.begin(); itu != quadrature_t::quadrature.end(); ++itu) {
96  xi_t u = itu->get_xi();
97  double wu = itu->get_w();
98 
99  result_t NNt0 = test_shape_t::template eval_shape<0>(u) *
100  trial_shape_t::template eval_shape<0>(u).transpose();
101  double J0 = elem.get_dx(u).norm();
102 
103  // loop over v
104  for (auto itv = quadrature_t::quadrature.begin(); itv != quadrature_t::quadrature.end(); ++itv) {
105  double v = (itv->get_xi()(0) + 1.) / 2.;
106  double wv = itv->get_w() / 2.;
107 
108  xi_t xi, eta;
109 
110  // loop over domains (0) upper triangle, (1) lower triangle
111  for (int d = 0; d < 2; ++d) {
112  if (d == 0) {
113  xi(0) = u(0) + (+1. - u(0)) * v;
114  eta(0) = u(0) + (-1. - u(0)) * v;
115  }
116  else {
117  xi(0) = u(0) + (-1. - u(0)) * v;
118  eta(0) = u(0) + (+1. - u(0)) * v;
119  }
120 
121  std::complex<double> G = kernel(elem.get_x(xi), elem.get_x(eta));
122  double Jxi = elem.get_dx(xi).norm();
123  double Jeta = elem.get_dx(eta).norm();
124  auto Nxi = test_shape_t::template eval_shape<0>(xi);
125  auto Neta = trial_shape_t::template eval_shape<0>(eta);
126 
127  // evaluate integrand
128  result_t F = G * Jxi * Jeta * (Nxi * Neta.transpose());
129 
130  // evaluate integrand's singular part
131  double G0 = -std::log(2. * v * J0) / two_pi;
132  result_t F0 = G0 * J0 * J0 * NNt0;
133 
134  // integrate difference numerically
135  I += (F - F0) * (2. * (1. - v)) * wu * wv;
136  } // loop over domains
137  } // loop over v
138 
139  // compensate with analytical inner integral of the regular part
140  I += 2. * (1.5 - std::log(2. * J0)) / two_pi * J0 * J0 * NNt0 * wu;
141  } // loop over u
142 
143  return I;
144  } // function eval
145 }; // class helmholtz_2d_SLP_galerkin_face_general
146 
147 
154 template <unsigned expansion_length>
156 {
157 public:
163  template <class wavenumber_t>
164  static std::complex<double> eval(double R, wavenumber_t const &k)
165  {
166 #ifdef NIHU_PRINT_DEBUG
167  static bool printed = false;
168  if (!printed) {
169  std::cout << "Using helmholtz_2d_SLP_galerkin_face_constant_line" << std::endl;
170  printed = true;
171  }
172 #endif
173 
174  using namespace boost::math::double_constants;
175  using namespace std::complex_literals;
176 
177  wavenumber_t kR = k * R;
178  wavenumber_t logkR = std::log(kR);
179 
180  auto I = 1. - 2.i/pi * (logkR - 1.5 + euler);
181 
182  wavenumber_t q = -kR * kR;
183  wavenumber_t pow = 1.;
184  double Cn = 0.;
185 
186  for (unsigned n = 1; n <= expansion_length; ++n) {
187  unsigned d = (n+1) * (2*n+1);
188  double Fn = 1./d;
189  wavenumber_t Gn = logkR/d - (4*n + 3)/2./(d*d);
190  pow *= q/(n*n);
191  Cn += 1./n;
192  I += (Fn-(2.i/pi)*(Gn+(euler - Cn)*Fn)) * pow;
193  }
194 
195  return I * (R*R) * -1.0i;
196  } // end of function eval
197 }; // end of class helmholtz_2d_SLP_galerkin_face_constant_line
198 
199 
210 template <class TestField, class TrialField, size_t order>
212 {
213  typedef TestField test_field_t;
214  typedef TrialField trial_field_t;
215 
216  typedef typename test_field_t::nset_t test_shape_t;
217  typedef typename trial_field_t::nset_t trial_shape_t;
218 
219  static size_t const nTest = test_shape_t::num_nodes;
220  static size_t const nTrial = trial_shape_t::num_nodes;
221 
222  typedef Eigen::Matrix<std::complex<double>, nTest, nTrial> result_t;
223 
224  typedef typename trial_field_t::elem_t elem_t;
225  typedef typename elem_t::domain_t domain_t;
226 
227  typedef typename domain_t::xi_t xi_t;
228  typedef typename elem_t::x_t x_t;
229 
231 
232 public:
238  template <class wave_number_t>
239  static result_t eval(elem_t const &elem, wave_number_t const &k)
240  {
241 #ifdef NIHU_PRINT_DEBUG
242  static bool printed = false;
243  if (!printed) {
244  std::cout << "Using helmholtz_2d_DLP_galerkin_face_general" << std::endl;
245  printed = true;
246  }
247 #endif
248 
249  using namespace boost::math::double_constants;
250 
252  kernel_t kernel(k);
253 
254  result_t I = result_t::Zero();
255 
256  // loop over v
257  for (auto itv = quadrature_t::quadrature.begin(); itv != quadrature_t::quadrature.end(); ++itv) {
258  xi_t v = itv->get_xi();
259  v(0) = (v(0) + 1.) / 2.;
260  double wv = itv->get_w() / 2.;
261 
262  // loop over u
263  for (auto itu = quadrature_t::quadrature.begin(); itu != quadrature_t::quadrature.end(); ++itu) {
264  xi_t u = itu->get_xi();
265  double wu = itu->get_w();
266 
267  // loop over domains
268  for (int d = 0; d < 2; ++d) {
269  xi_t xi, eta;
270 
271  if (d == 0) {
272  xi(0) = u(0) + (+1. - u(0)) * v(0);
273  eta(0) = u(0) + (-1. - u(0)) * v(0);
274  }
275  else {
276  xi(0) = u(0) + (-1. - u(0)) * v(0);
277  eta(0) = u(0) + (+1. - u(0)) * v(0);
278  }
279 
280  double Jxi = elem.get_normal(xi).norm();
281  std::complex<double> G = kernel(elem.get_x(xi), elem.get_x(eta), elem.get_normal(eta));
282 
283  auto Nxi = test_shape_t::template eval_shape<0>(xi);
284  auto Neta = trial_shape_t::template eval_shape<0>(eta);
285 
286  // evaluate integrand (Jeta is incorporated in the Kernel with the normal)
287  result_t F = G * (Jxi * 2 * (1. - v(0))) * (Nxi * Neta.transpose());
288 
289  I += F * wv * wu;
290  } // loop over domains
291  } // loop over u
292  } // loop over v
293  return I;
294  } // end fo function eval
295 }; // class helmholtz_2d_DLP_galerkin_face_general
296 
297 
308 template <class TestField, class TrialField, size_t order>
310 {
311  typedef TestField test_field_t;
312  typedef TrialField trial_field_t;
313 
314  typedef typename test_field_t::nset_t test_shape_t;
315  typedef typename trial_field_t::nset_t trial_shape_t;
316 
317  static size_t const nTest = test_shape_t::num_nodes;
318  static size_t const nTrial = trial_shape_t::num_nodes;
319 
320  typedef Eigen::Matrix<std::complex<double>, nTest, nTrial> result_t;
321 
322  typedef typename trial_field_t::elem_t elem_t;
323  typedef typename elem_t::domain_t domain_t;
324 
325  typedef typename domain_t::xi_t xi_t;
326  typedef typename elem_t::x_t x_t;
327 
329 
330 public:
336  template <class wave_number_t>
337  static result_t eval(elem_t const &elem, wave_number_t const &k)
338  {
339 #ifdef NIHU_PRINT_DEBUG
340  static bool printed = false;
341  if (!printed) {
342  std::cout << "Using helmholtz_2d_DLPt_galerkin_face_general" << std::endl;
343  printed = true;
344  }
345 #endif
346 
347  using namespace boost::math::double_constants;
348 
350  kernel_t kernel(k);
351 
352  result_t I = result_t::Zero();
353 
354  // loop over v
355  for (auto itv = quadrature_t::quadrature.begin(); itv != quadrature_t::quadrature.end(); ++itv) {
356  xi_t v = itv->get_xi();
357  v(0) = (v(0) + 1.) / 2.;
358  double wv = itv->get_w() / 2.;
359 
360  // loop over u
361  for (auto itu = quadrature_t::quadrature.begin(); itu != quadrature_t::quadrature.end(); ++itu) {
362  xi_t u = itu->get_xi();
363  double wu = itu->get_w();
364 
365  // loop over domains
366  for (int d = 0; d < 2; ++d) {
367  xi_t xi, eta;
368 
369  if (d == 0) {
370  xi(0) = u(0) + (+1. - u(0)) * v(0);
371  eta(0) = u(0) + (-1. - u(0)) * v(0);
372  }
373  else {
374  xi(0) = u(0) + (-1. - u(0)) * v(0);
375  eta(0) = u(0) + (+1. - u(0)) * v(0);
376  }
377 
378  double Jeta = elem.get_normal(eta).norm();
379  std::complex<double> G = kernel(elem.get_x(xi), elem.get_x(eta), elem.get_normal(xi));
380 
381  auto Nxi = test_shape_t::template eval_shape<0>(xi);
382  auto Neta = trial_shape_t::template eval_shape<0>(eta);
383 
384  // evaluate integrand (Jeta is incorporated in the Kernel with the normal)
385  result_t F = G * (Jeta * 2 * (1. - v(0))) * (Nxi * Neta.transpose());
386 
387  I += F * wv * wu;
388  } // loop over domains
389  } // loop over u
390  } // loop over v
391  return I;
392  } // end fo function eval
393 }; // class helmholtz_2d_DLPt_galerkin_face_general
394 
395 
407 template <class TestField, class TrialField, size_t order>
409 {
410  typedef TestField test_field_t;
411  typedef TrialField trial_field_t;
412 
413  typedef typename test_field_t::nset_t test_shape_t;
414  typedef typename trial_field_t::nset_t trial_shape_t;
415 
416  static size_t const nTest = test_shape_t::num_nodes;
417  static size_t const nTrial = trial_shape_t::num_nodes;
418 
419  typedef Eigen::Matrix<std::complex<double>, nTest, nTrial> result_t;
420 
421  typedef typename trial_field_t::elem_t elem_t;
422  typedef typename elem_t::domain_t domain_t;
423 
424  typedef typename domain_t::xi_t xi_t;
425  typedef typename elem_t::x_t x_t;
426 
428 
429  static result_t F2(xi_t const &u)
430  {
431  using namespace boost::math::double_constants;
432  return test_shape_t::template eval_shape<0>(u)
433  * trial_shape_t::template eval_shape<0>(u).transpose() / (2.0 * two_pi);
434  }
435 
436 public:
440  template <class wave_number_t>
441  static result_t eval(elem_t const &elem, wave_number_t const &k)
442  {
443 #ifdef NIHU_PRINT_DEBUG
444  static bool printed = false;
445  if (!printed) {
446  std::cout << "Using helmholtz_2d_HSP_galerkin_face_general" << std::endl;
447  printed = true;
448  }
449 #endif
450 
451  using namespace boost::math::double_constants;
452 
454  kernel_t kernel(k);
455 
456  result_t I = result_t::Zero();
457 
458  // loop over v
459  for (auto it = quadrature_t::quadrature.begin(); it != quadrature_t::quadrature.end(); ++it) {
460  xi_t v = it->get_xi();
461  v(0) = (v(0) + 1.) / 2.;
462  double wv = it->get_w() / 2.;
463 
464  // loop over u
465  for (auto jt = quadrature_t::quadrature.begin(); jt != quadrature_t::quadrature.end(); ++jt) {
466  xi_t u = jt->get_xi();
467  double wu = jt->get_w();
468 
469  // loop over domains
470  for (int d = 0; d < 2; ++d) {
471  xi_t xi, eta;
472 
473  if (d == 0) {
474  xi(0) = u(0) + (+1. - u(0)) * v(0);
475  eta(0) = u(0) + (-1. - u(0)) * v(0);
476  }
477  else {
478  xi(0) = u(0) + (-1. - u(0)) * v(0);
479  eta(0) = u(0) + (+1. - u(0)) * v(0);
480  }
481 
482  x_t x = elem.get_x(xi);
483  x_t y = elem.get_x(eta);
484  x_t Jeta = elem.get_normal(eta);
485  x_t Jxi = elem.get_normal(xi);
486  std::complex<double> G = kernel(x, y, Jxi, Jeta);
487 
488  auto Nxi = test_shape_t::template eval_shape<0>(xi);
489  auto Neta = trial_shape_t::template eval_shape<0>(eta);
490 
491  // evaluate integrand
492  result_t F = G * 2. * (1. - v(0)) * (Nxi * Neta.transpose());
493 
494  I += F * wv * wu;
495  } // loop over domains
496 
497  I -= 2.0 * F2(u) / (v(0) * v(0)) * wv * wu;
498  } // loop over u
499 
500  I += 2.0 * (F2(xi_t(1.)) + F2(xi_t(-1.0))) / v(0) * wv;
501  } // loop over v
502 
503  for (auto jt = quadrature_t::quadrature.begin(); jt != quadrature_t::quadrature.end(); ++jt) {
504  xi_t u = jt->get_xi();
505  double wu = jt->get_w();
506  I -= 2.0 * F2(u) * wu;
507  }
508 
509  I -= 2.0 * (F2(xi_t(1.0)) * std::log(2.0 * elem.get_dx(xi_t(1.0)).norm())
510  + F2(xi_t(-1.0)) * std::log(2.0 * elem.get_dx(xi_t(-1.0)).norm()));
511 
512  return I;
513  } // end fo function eval
514 }; // class helmholtz_2d_HSP_galerkin_face_general
515 
516 
528 template <class TestField, class TrialField, size_t order>
530 {
531  typedef TestField test_field_t;
532  typedef TrialField trial_field_t;
533 
534  typedef typename test_field_t::nset_t test_shape_t;
535  typedef typename test_shape_t::shape_t test_N_t;
536  typedef typename trial_field_t::nset_t trial_shape_t;
537  typedef typename trial_shape_t::shape_t trial_N_t;
538 
539  static size_t const nTest = test_shape_t::num_nodes;
540  static size_t const nTrial = trial_shape_t::num_nodes;
541 
542  typedef Eigen::Matrix<std::complex<double> , nTest, nTrial> result_t;
543 
544  typedef typename trial_field_t::elem_t trial_elem_t;
545  typedef typename test_field_t::elem_t test_elem_t;
546 
547  typedef typename trial_elem_t::domain_t domain_t;
548  typedef typename domain_t::xi_t xi_t;
549  typedef typename trial_elem_t::x_t x_t;
550 
552 
553 public:
559  template<class wave_number_t>
560  static result_t eval(
561  test_elem_t const &test_elem,
562  trial_elem_t const &trial_elem,
563  wave_number_t const &k)
564  {
565 #ifdef NIHU_PRINT_DEBUG
566  static bool printed = false;
567  if (!printed) {
568  std::cout << "Using helmholtz_2d_HSP_galerkin_edge_general" << std::endl;
569  printed = true;
570  }
571 #endif
572  using namespace boost::math::double_constants;
573 
575  kernel_t kernel(k);
576 
577  result_t I = result_t::Zero();
578 
579  int singular_domain;
580  if (test_elem.get_nodes()(test_elem_t::num_nodes - 1) == trial_elem.get_nodes()(0))
581  singular_domain = 1;
582  else if (test_elem.get_nodes()(0) == trial_elem.get_nodes()(trial_elem_t::num_nodes - 1))
583  singular_domain = 0;
584  else throw std::logic_error("Invalid singular case detected");
585 
586  // loop over two subdomains
587  for (int d = 0; d < 2; ++d) {
588  xi_t xi0, eta0;
589  if (d == 0) {
590  xi0 << -1;
591  eta0 << +1;
592  }
593  else {
594  xi0 << +1;
595  eta0 << -1;
596  }
597 
598  bool singular = singular_domain == d;
599 
600  x_t ax0, ay0, Jx0, Jy0;
601  test_N_t Nx0;
602  trial_N_t Ny0;
603 
604  // prepare quantities needed to compute F1(u)
605  if (singular) {
606  ax0 = test_elem.get_dx(xi0);
607  ay0 = trial_elem.get_dx(eta0);
608  Jx0 = test_elem.get_normal(xi0);
609  Jy0 = trial_elem.get_normal(eta0);
610  Nx0 = test_shape_t::template eval_shape<0>(xi0);
611  Ny0 = trial_shape_t::template eval_shape<0>(eta0);
612  }
613 
614  // loop over u
615  for (auto itu = quadrature_t::quadrature.begin(); itu != quadrature_t::quadrature.end(); ++itu) {
616  xi_t u = itu->get_xi();
617  double wu = itu->get_w();
618 
619  // s and F1 are only computed if singular
620  double s;
621  result_t F1;
622 
623  if (singular) {
624  x_t svec = ay0 * (u - eta0)(0) - ax0 * (u - xi0)(0);
625  s = svec.norm();
626  x_t es = svec.normalized();
627  F1 = (Jx0.dot(Jy0) - 2 * es.dot(Jx0) * es.dot(Jy0)) / pi / s / s *
628  (Nx0 * Ny0.transpose());
629  }
630 
631  // loop over v
632  for (auto itv = quadrature_t::quadrature.begin(); itv != quadrature_t::quadrature.end(); ++itv) {
633  xi_t v = itv->get_xi();
634  // transform v to (0,1) from (-1,1)
635  v(0) = (v(0) + 1.) / 2.;
636  double wv = itv->get_w() / 2.;
637 
638  // compute intrinsic variables
639  xi_t xi = xi0 + (u - xi0) * v;
640  xi_t eta = eta0 + (u - eta0) * v;
641 
642  // compute kernel value
643  x_t x = test_elem.get_x(xi);
644  x_t y = trial_elem.get_x(eta);
645  x_t Jxi = test_elem.get_normal(xi);
646  x_t Jeta = trial_elem.get_normal(eta);
647  std::complex<double> G = kernel(x, y, Jxi, Jeta);
648 
649  test_N_t Nxi = test_shape_t::template eval_shape<0>(xi);
650  trial_N_t Neta = trial_shape_t::template eval_shape<0>(eta);
651 
652  // evaluate integrand
653  result_t F = G * 2. * v(0) * (Nxi * Neta.transpose());
654 
655  I += F * wv * wu;
656 
657  if (singular)
658  // subtract singular part
659  I -= F1 / v(0) * wv * wu;
660  } // loop over v
661 
662  if (singular)
663  // add analytic (inner) integral of singular part
664  I += F1 * std::log(s) * wu;
665 
666  } // loop over u
667  } // loop over domains
668 
669  return I;
670  } // function eval
671 }; // class helmholtz_2d_HSP_galerkin_edge_general
672 
673 
678 template <class WaveNumber, class TestField, class TrialField>
680  helmholtz_2d_SLP_kernel<WaveNumber>, TestField, TrialField, match::match_1d_type,
681  typename std::enable_if<
682  std::is_same<typename get_formalism<TestField, TrialField>::type, formalism::general>::value &&
683  !(is_constant_line<TrialField>::value && is_constant_line<TestField>::value)
684  >::type
685 >
686 {
687 public:
695  template <class result_t>
696  static result_t &eval(
697  result_t &result,
699  field_base<TestField> const &,
700  field_base<TrialField> const &trial_field,
701  element_match const &)
702  {
704  trial_field.get_elem(), kernel.derived().get_wave_number());
705  return result;
706  }
707 };
708 
709 
713 template <class WaveNumber, class TestField, class TrialField>
715  helmholtz_2d_SLP_kernel<WaveNumber>, TestField, TrialField, match::match_1d_type,
716  typename std::enable_if<
717  std::is_same<typename get_formalism<TestField, TrialField>::type, formalism::general>::value &&
718  is_constant_line<TrialField>::value &&
719  is_constant_line<TestField>::value
720  >::type
721 >
722 {
723 public:
731  template <class result_t>
732  static result_t &eval(
733  result_t &result,
735  field_base<TestField> const &,
736  field_base<TrialField> const &trial_field,
737  element_match const &)
738  {
739  auto const &elem = trial_field.get_elem();
740  double R = (elem.get_coords().col(1) - elem.get_coords().col(0)).norm()/2.;
742  R, kernel.derived().get_wave_number());
743 
744  return result;
745  }
746 };
747 
748 
753 template <class TestField, class TrialField, class WaveNumber>
755  helmholtz_2d_DLP_kernel<WaveNumber>, TestField, TrialField, match::match_1d_type,
756  typename std::enable_if<
757  std::is_same<typename get_formalism<TestField, TrialField>::type, formalism::general>::value &&
758  !std::is_same<typename TrialField::elem_t::lset_t, line_1_shape_set>::value
759  >::type
760 >
761 {
762 public:
770  template <class result_t>
771  static result_t &eval(
772  result_t &result,
774  field_base<TestField> const &test_field,
775  field_base<TrialField> const &trial_field,
776  element_match const &)
777  {
779  test_field.get_elem(), kernel.derived().get_wave_number());
780  return result;
781  }
782 };
783 
784 
789 template <class TestField, class TrialField, class WaveNumber>
791  helmholtz_2d_DLPt_kernel<WaveNumber>, TestField, TrialField, match::match_1d_type,
792  typename std::enable_if<
793  std::is_same<typename get_formalism<TestField, TrialField>::type, formalism::general>::value &&
794  !std::is_same<typename TrialField::elem_t::lset_t, line_1_shape_set>::value
795  >::type
796 >
797 {
798 public:
806  template <class result_t>
807  static result_t &eval(
808  result_t &result,
810  field_base<TestField> const &test_field,
811  field_base<TrialField> const &trial_field,
812  element_match const &)
813  {
815  test_field.get_elem(), kernel.derived().get_wave_number());
816  return result;
817  }
818 };
819 
820 
825 template <class TestField, class TrialField, class WaveNumber>
827  helmholtz_2d_HSP_kernel<WaveNumber>, TestField, TrialField, match::match_1d_type,
828  typename std::enable_if<
829  std::is_same<typename get_formalism<TestField, TrialField>::type, formalism::general>::value
830  >::type
831 >
832 {
833 public:
841  template <class result_t>
842  static result_t &eval(
843  result_t &result,
845  field_base<TestField> const &test_field,
846  field_base<TrialField> const &trial_field,
847  element_match const &)
848  {
850  test_field.get_elem(), kernel.derived().get_wave_number());
851  return result;
852  }
853 };
854 
855 
859 template <class TestField, class TrialField, class WaveNumber>
861  helmholtz_2d_HSP_kernel<WaveNumber>, TestField, TrialField, match::match_0d_type,
862  typename std::enable_if<
863  std::is_same<typename get_formalism<TestField, TrialField>::type, formalism::general>::value
864  >::type
865 >
866 {
867 public:
875  template <class result_t>
876  static result_t &eval(
877  result_t &result,
879  field_base<TestField> const &test_field,
880  field_base<TrialField> const &trial_field,
881  element_match const &)
882  {
884  test_field.get_elem(),
885  trial_field.get_elem(),
886  kernel.derived().get_wave_number());
887  return result;
888  }
889 };
890 } // end of namespace NiHu
891 
892 
893 #endif // NIHU_HELMHOLTZ_2D_SINGULAR_DOUBLE_INTEGRALS_HPP_INCLUDED
NiHu::helmholtz_2d_HSP_galerkin_edge_general
Edge match double integral of the HSP kernel over curved elements with general shape sets.
Definition: helmholtz_2d_singular_double_integrals.hpp:529
NiHu::singular_integral_shortcut< helmholtz_2d_DLP_kernel< WaveNumber >, TestField, TrialField, match::match_1d_type, typename std::enable_if< std::is_same< typename get_formalism< TestField, TrialField >::type, formalism::general >::value &&!std::is_same< typename TrialField::elem_t::lset_t, line_1_shape_set >::value >::type >::eval
static result_t & eval(result_t &result, kernel_base< helmholtz_2d_DLP_kernel< WaveNumber > > const &kernel, field_base< TestField > const &test_field, field_base< TrialField > const &trial_field, element_match const &)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:771
NiHu::singular_integral_shortcut< helmholtz_2d_DLPt_kernel< WaveNumber >, TestField, TrialField, match::match_1d_type, typename std::enable_if< std::is_same< typename get_formalism< TestField, TrialField >::type, formalism::general >::value &&!std::is_same< typename TrialField::elem_t::lset_t, line_1_shape_set >::value >::type >::eval
static result_t & eval(result_t &result, kernel_base< helmholtz_2d_DLPt_kernel< WaveNumber > > const &kernel, field_base< TestField > const &test_field, field_base< TrialField > const &trial_field, element_match const &)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:807
NiHu::helmholtz_2d_HSP_galerkin_face_general
Face match double integral of the HSP kernel.
Definition: helmholtz_2d_singular_double_integrals.hpp:408
NiHu::singular_integral_shortcut< helmholtz_2d_SLP_kernel< WaveNumber >, TestField, TrialField, match::match_1d_type, typename std::enable_if< std::is_same< typename get_formalism< TestField, TrialField >::type, formalism::general >::value &&is_constant_line< TrialField >::value &&is_constant_line< TestField >::value >::type >::eval
static result_t & eval(result_t &result, kernel_base< helmholtz_2d_SLP_kernel< WaveNumber > > const &kernel, field_base< TestField > const &, field_base< TrialField > const &trial_field, element_match const &)
evaluate singular integral
Definition: helmholtz_2d_singular_double_integrals.hpp:732
NiHu::helmholtz_2d_SLP_galerkin_face_constant_line
Face match double integral of the SLP kernel over a line element with constant shape function.
Definition: helmholtz_2d_singular_double_integrals.hpp:155
NiHu::singular_integral_shortcut< helmholtz_2d_SLP_kernel< WaveNumber >, TestField, TrialField, match::match_1d_type, typename std::enable_if< std::is_same< typename get_formalism< TestField, TrialField >::type, formalism::general >::value &&!(is_constant_line< TrialField >::value &&is_constant_line< TestField >::value) >::type >::eval
static result_t & eval(result_t &result, kernel_base< helmholtz_2d_SLP_kernel< WaveNumber > > const &kernel, field_base< TestField > const &, field_base< TrialField > const &trial_field, element_match const &)
evaluate singular integral
Definition: helmholtz_2d_singular_double_integrals.hpp:696
NiHu::volume_element::x_t
element_traits::location_value_type< Derived, 0 >::type x_t
type of the element's physical location variable
Definition: element.hpp:220
NiHu::helmholtz_2d_DLPt_galerkin_face_general
Face match double integral of the DLPt kernel.
Definition: helmholtz_2d_singular_double_integrals.hpp:309
NiHu::regular_quad_store
store-wrapper of a statically stored quadrature
Definition: quadrature_store_helper.hpp:13
NiHu::exponential_covariance_kernel
Definition: covariance_kernel.hpp:42
NiHu::helmholtz_2d_SLP_galerkin_face_general
Face match double integral of the SLP kernel over a curved element with general shape set.
Definition: helmholtz_2d_singular_double_integrals.hpp:51
NiHu::match::match_0d_type
std::integral_constant< int, 0 > match_0d_type
two elements are adjacent with a 0d (vertex) match
Definition: match_types.hpp:38
NiHu::kernel_base
CRTP base class of all BEM kernels.
Definition: kernel.hpp:133
NiHu::helmholtz_2d_HSP_galerkin_edge_general::eval
static result_t eval(test_elem_t const &test_elem, trial_elem_t const &trial_elem, wave_number_t const &k)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:560
NiHu::element_match
class describing the adjacency (match) state of two elements
Definition: element_match.hpp:39
NiHu::helmholtz_2d_HSP_galerkin_face_general::eval
static result_t eval(elem_t const &elem, wave_number_t const &k)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:441
NiHu::singular_integral_shortcut
a shortcut for the user to define customised singular integral methods
Definition: double_integral.hpp:709
NiHu::match::match_1d_type
std::integral_constant< int, 1 > match_1d_type
two elements are adjacent with a 1d (line) match
Definition: match_types.hpp:40
NiHu::field_base::get_elem
const elem_t & get_elem() const
return underlying element
Definition: field.hpp:149
NiHu::singular_integral_shortcut< helmholtz_2d_HSP_kernel< WaveNumber >, TestField, TrialField, match::match_0d_type, typename std::enable_if< std::is_same< typename get_formalism< TestField, TrialField >::type, formalism::general >::value >::type >::eval
static result_t & eval(result_t &result, kernel_base< helmholtz_2d_HSP_kernel< WaveNumber > > const &kernel, field_base< TestField > const &test_field, field_base< TrialField > const &trial_field, element_match const &)
evaluate singular integral
Definition: helmholtz_2d_singular_double_integrals.hpp:876
NiHu::field_base
CRTP base class of all fields.
Definition: field.hpp:111
NiHu::helmholtz_2d_SLP_galerkin_face_constant_line::eval
static std::complex< double > eval(double R, wavenumber_t const &k)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:164
laplace_2d_singular_double_integrals.hpp
Analytical expressions for the singular integrals of 2D Laplace kernels.
NiHu::volume_element::domain_t
typename base_t::domain_t domain_t
the domain type
Definition: element.hpp:637
NiHu::singular_integral_shortcut< helmholtz_2d_HSP_kernel< WaveNumber >, TestField, TrialField, match::match_1d_type, typename std::enable_if< std::is_same< typename get_formalism< TestField, TrialField >::type, formalism::general >::value >::type >::eval
static result_t & eval(result_t &result, kernel_base< helmholtz_2d_HSP_kernel< WaveNumber > > const &kernel, field_base< TestField > const &test_field, field_base< TrialField > const &trial_field, element_match const &)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:842
NiHu::normal_derivative_kernel
Normal derivative of a distance dependent kernel.
Definition: normal_derivative_kernel.hpp:26
lib_element.hpp
helmholtz_kernel.hpp
Kernels of the Helmholtz equation .
NiHu::helmholtz_2d_DLP_galerkin_face_general::eval
static result_t eval(elem_t const &elem, wave_number_t const &k)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:239
NiHu::helmholtz_2d_DLP_galerkin_face_general
Face match double integral of the DLP kernel.
Definition: helmholtz_2d_singular_double_integrals.hpp:211
NiHu::helmholtz_2d_DLPt_galerkin_face_general::eval
static result_t eval(elem_t const &elem, wave_number_t const &k)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:337
NiHu::helmholtz_2d_SLP_galerkin_face_general::eval
static result_t eval(elem_t const &elem, wave_number_t const &k)
Evaluate the integral.
Definition: helmholtz_2d_singular_double_integrals.hpp:78
NiHu::regular_quad_store::quadrature
static const gaussian_quadrature< domain_t > quadrature
the stored static quadrature member
Definition: quadrature_store_helper.hpp:16