NiHu  2.0
helmholtz_3d_nearly_singular_integrals.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-2019 Peter Fiala <fiala@hit.bme.hu>
4 // Copyright (C) 2012-2019 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 
21 
22 #ifndef HELMHOLTZ_3D_NEARLY_SINGULAR_INTEGRALS_HPP_INCLUDED
23 #define HELMHOLTZ_3D_NEARLY_SINGULAR_INTEGRALS_HPP_INCLUDED
24 
25 #include "field_type_helpers.hpp"
26 #include "helmholtz_kernel.hpp"
27 #include "laplace_kernel.hpp"
29 #include "nearly_singular_collocational.hpp"
30 #include "nearly_singular_collocational_telles.hpp"
31 #include "quadrature_store_helper.hpp"
32 
33 #include "../core/nearly_singular_planar_constant_collocation_shortcut.hpp"
34 
35 
36 namespace NiHu
37 {
38 
47 {
48 public:
49  template <class elem_t, class wavenumber_t>
50  static std::complex<double> eval(
51  elem_t const &elem,
52  typename elem_t::x_t const &x0,
53  wavenumber_t const &k)
54  {
55  typedef typename elem_t::domain_t quadrature_domain_t;
56  enum { quadrature_order = 14 };
58  typedef typename elem_t::x_t x_t;
59 
61  laplace_3d_SLP_kernel kstatic;
62 
63  double res_static = laplace_3d_SLP_collocation_constant_plane_nearly_singular::eval(elem, x0);
64 
65  std::complex<double> res_dynamic = 0.0;
66 
67  for (auto it = quadrature_t::quadrature.begin(); it != quadrature_t::quadrature.end(); ++it)
68  {
69  auto const &xi = it->get_xi();
70  double w = it->get_w();
71 
72  x_t y = elem.get_x(xi);
73  double jac = elem.get_normal(xi).norm();
74 
75  res_dynamic += (
76  ktotal(x0, y) - kstatic(x0, y)
77  ) * w * jac;
78  }
79 
80  return res_static + res_dynamic;
81  }
82 };
83 
84 
90 {
91 public:
92  template <class elem_t, class wavenumber_t>
93  static std::complex<double> eval(
94  elem_t const &elem,
95  typename elem_t::x_t const &x0,
96  wavenumber_t const &k)
97  {
98  typedef typename elem_t::domain_t quadrature_domain_t;
99  enum { quadrature_order = 14 };
101  typedef typename elem_t::x_t x_t;
102 
104  laplace_3d_DLP_kernel kstatic;
105 
106  double res_static = laplace_3d_DLP_collocation_constant_plane_nearly_singular::eval(elem, x0);
107 
108  std::complex<double> res_dynamic = 0.0;
109 
110  x_t ny = elem.get_normal().normalized();
111 
112  for (auto it = quadrature_t::quadrature.begin(); it != quadrature_t::quadrature.end(); ++it)
113  {
114  auto const &xi = it->get_xi();
115  double w = it->get_w();
116 
117  x_t y = elem.get_x(xi);
118  double jac = elem.get_normal(xi).norm();
119 
120  res_dynamic += (
121  ktotal(x0, y, ny) - kstatic(x0, y, ny)
122  ) * w * jac;
123  }
124 
125  return res_static + res_dynamic;
126  }
127 };
128 
136 {
137 public:
138  template <class elem_t, class wavenumber_t>
139  static std::complex<double> eval(
140  elem_t const &elem,
141  typename elem_t::x_t const &x0,
142  typename elem_t::x_t const &nx,
143  wavenumber_t const &k)
144  {
145  typedef typename elem_t::domain_t quadrature_domain_t;
146  enum { quadrature_order = 14 };
148  typedef typename elem_t::x_t x_t;
149 
151  laplace_3d_DLPt_kernel kstatic;
152 
153  double res_static = laplace_3d_DLPt_collocation_constant_plane_nearly_singular::eval(elem, x0, nx);
154 
155  std::complex<double> res_dynamic = 0.0;
156 
157  for (auto it = quadrature_t::quadrature.begin(); it != quadrature_t::quadrature.end(); ++it)
158  {
159  auto const &xi = it->get_xi();
160  double w = it->get_w();
161 
162  x_t y = elem.get_x(xi);
163  double jac = elem.get_normal(xi).norm();
164 
165  res_dynamic += (
166  ktotal(x0, y, nx) - kstatic(x0, y, nx)
167  ) * w * jac;
168  }
169 
170  return res_static + res_dynamic;
171  }
172 };
173 
174 
181 {
182 public:
183  template <class elem_t, class wavenumber_t>
184  static std::complex<double> eval(
185  elem_t const &elem,
186  typename elem_t::x_t const &x0,
187  typename elem_t::x_t const &nx,
188  wavenumber_t const &k)
189  {
190  typedef typename elem_t::domain_t quadrature_domain_t;
191  enum { quadrature_order = 14 };
193  typedef typename elem_t::x_t x_t;
194 
196  laplace_3d_HSP_kernel kstatic;
197 
198  double res_static = laplace_3d_HSP_collocation_constant_plane_nearly_singular::eval(elem, x0, nx);
199 
200  std::complex<double> res_dynamic = 0.0;
201  x_t ny = elem.get_normal().normalized();
202 
203  for (auto it = quadrature_t::quadrature.begin(); it != quadrature_t::quadrature.end(); ++it)
204  {
205  auto const &xi = it->get_xi();
206  double w = it->get_w();
207 
208  x_t y = elem.get_x(xi);
209  double jac = elem.get_normal(xi).norm();
210 
211  res_dynamic += (
212  ktotal(x0, y, nx, ny) - kstatic(x0, y, nx, ny)
213  ) * w * jac;
214  }
215 
216  return res_static + res_dynamic;
217  }
218 };
219 
223 template <class TestField, class TrialField, class WaveNumber>
225  helmholtz_3d_SLP_kernel<WaveNumber>, TestField, TrialField,
226  typename std::enable_if<
227  is_collocational<TestField, TrialField>::value &&
228  is_constant_tria<TrialField>::value
229  >::type
230 >
231 {
233 public:
234  static bool needed(
235  kernel_base<kernel_t> const &kernel,
236  field_base<TestField> const &test_field,
237  field_base<TrialField> const &trial_field
238  )
239  {
240  double const limit = 1.5;
241 
242  // distance between element centres
243  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
244  double R = trial_field.get_elem().get_linear_size_estimate();
245  return d/R < limit;
246  }
247 
248  template <class result_t>
249  static result_t &eval(
250  result_t &result,
251  kernel_base<kernel_t> const &kernel,
252  field_base<TestField> const &test_field,
253  field_base<TrialField> const &trial_field
254  )
255  {
256  result(0) = helmholtz_3d_SLP_collocation_constant_plane_nearly_singular::eval(
257  trial_field.get_elem(),
258  test_field.get_elem().get_center(),
259  kernel.derived().get_wave_number());
260  return result;
261  }
262 };
263 
264 
268 template <class TestField, class TrialField, class WaveNumber>
270  helmholtz_3d_SLP_kernel<WaveNumber>, TestField, TrialField,
271  typename std::enable_if<
272  is_collocational<TestField, TrialField>::value &&
273  !is_constant_tria<TrialField>::value
274  >::type
275 >
276 {
278  typedef typename kernel_t::test_input_t test_input_t;
279  typedef TestField test_field_t;
280  typedef typename test_field_t::nset_t test_nset_t;
281  static unsigned const num_test_nodes = test_nset_t::num_nodes;
282 
283 public:
284  static bool needed(
285  kernel_base<kernel_t> const &kernel,
286  field_base<TestField> const &test_field,
287  field_base<TrialField> const &trial_field
288  )
289  {
290  double const limit = 1.5;
291 
292  // distance between element centres
293  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
294  double R = trial_field.get_elem().get_linear_size_estimate();
295 
296  return d/R < limit;
297  }
298 
299  template <class result_t>
300  static result_t &eval(
301  result_t &result,
302  kernel_base<kernel_t> const &kernel,
303  field_base<TestField> const &test_field,
304  field_base<TrialField> const &trial_field
305  )
306  {
308  nsc_t nsc(trial_field, kernel);
309 
310  for (unsigned i = 0; i < num_test_nodes; ++i)
311  {
312  test_input_t tsti(test_field.get_elem(), test_nset_t::corner_at(i));
313  nsc.integrate(result.row(i), tsti);
314  }
315 
316  return result;
317  }
318 };
319 
320 
321 template <class TestField, class TrialField, class WaveNumber>
323  helmholtz_3d_DLP_kernel<WaveNumber>, TestField, TrialField,
324  typename std::enable_if<
325  is_collocational<TestField, TrialField>::value &&
326  is_constant_tria<TrialField>::value
327  >::type
328 >
329 {
331 public:
332  static bool needed(
333  kernel_base<kernel_t> const &kernel,
334  field_base<TestField> const &test_field,
335  field_base<TrialField> const &trial_field
336  )
337  {
338  double const limit = 1.5;
339 
340  // distance between element centres
341  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
342  double R = trial_field.get_elem().get_linear_size_estimate();
343 
344  return d/R < limit;
345  }
346 
347  template <class result_t>
348  static result_t &eval(
349  result_t &result,
350  kernel_base<kernel_t> const &kernel,
351  field_base<TestField> const &test_field,
352  field_base<TrialField> const &trial_field
353  )
354  {
355  result(0) = helmholtz_3d_DLP_collocation_constant_plane_nearly_singular::eval(
356  trial_field.get_elem(),
357  test_field.get_elem().get_center(),
358  kernel.derived().get_wave_number());
359  return result;
360  }
361 };
362 
363 
364 template <class TestField, class TrialField, class WaveNumber>
366  helmholtz_3d_DLP_kernel<WaveNumber>, TestField, TrialField,
367  typename std::enable_if<
368  is_collocational<TestField, TrialField>::value &&
369  !is_constant_tria<TrialField>::value
370  >::type
371 >
372 {
374  typedef typename kernel_t::test_input_t test_input_t;
375  typedef TestField test_field_t;
376  typedef typename test_field_t::nset_t test_nset_t;
377  static unsigned const num_test_nodes = test_nset_t::num_nodes;
378 
379 public:
380  static bool needed(
381  kernel_base<kernel_t> const &kernel,
382  field_base<TestField> const &test_field,
383  field_base<TrialField> const &trial_field
384  )
385  {
386  double const limit = 1.5;
387 
388  // distance between element centres
389  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
390  double R = trial_field.get_elem().get_linear_size_estimate();
391 
392  return d/R < limit;
393  }
394 
395  template <class result_t>
396  static result_t &eval(
397  result_t &result,
398  kernel_base<kernel_t> const &kernel,
399  field_base<TestField> const &test_field,
400  field_base<TrialField> const &trial_field
401  )
402  {
403  // Note: order limited for dunavant trias
404  // typedef nearly_singular_collocational_telles<TrialField, kernel_t, 30> nsc_t;
406  nsc_t nsc(trial_field, kernel);
407 
408  for (unsigned i = 0; i < num_test_nodes; ++i)
409  {
410  test_input_t tsti(test_field.get_elem(), test_nset_t::corner_at(i));
411  nsc.integrate(result.row(i), tsti);
412  }
413 
414  return result;
415  }
416 };
417 
418 
419 
420 
421 template <class TestField, class TrialField, class WaveNumber>
423  helmholtz_3d_DLPt_kernel<WaveNumber>, TestField, TrialField,
424  typename std::enable_if<
425  is_collocational<TestField, TrialField>::value &&
426  is_constant_tria<TrialField>::value
427  >::type
428 >
429 {
431 public:
432  static bool needed(
433  kernel_base<kernel_t> const &kernel,
434  field_base<TestField> const &test_field,
435  field_base<TrialField> const &trial_field
436  )
437  {
438  double const limit = 1.5;
439 
440  // distance between element centres
441  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
442  double R = trial_field.get_elem().get_linear_size_estimate();
443  return d/R < limit;
444  }
445 
446  template <class result_t>
447  static result_t &eval(
448  result_t &result,
449  kernel_base<kernel_t> const &kernel,
450  field_base<TestField> const &test_field,
451  field_base<TrialField> const &trial_field
452  )
453  {
454  result(0) = helmholtz_3d_DLPt_collocation_constant_plane_nearly_singular::eval(
455  trial_field.get_elem(),
456  test_field.get_elem().get_center(),
457  test_field.get_elem().get_normal().normalized(),
458  kernel.derived().get_wave_number());
459  return result;
460  }
461 };
462 
463 
468 template <class TestField, class TrialField, class WaveNumber>
470  helmholtz_3d_DLPt_kernel<WaveNumber>, TestField, TrialField,
471  typename std::enable_if<
472  is_collocational<TestField, TrialField>::value &&
473  !is_constant_tria<TrialField>::value
474  >::type
475 >
476 {
478  typedef typename kernel_t::test_input_t test_input_t;
479  typedef TestField test_field_t;
480  typedef typename test_field_t::nset_t test_nset_t;
481  static unsigned const num_test_nodes = test_nset_t::num_nodes;
482 
483 public:
484  static bool needed(
485  kernel_base<kernel_t> const &kernel,
486  field_base<TestField> const &test_field,
487  field_base<TrialField> const &trial_field
488  )
489  {
490  double const limit = 1.5;
491 
492  // distance between element centres
493  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
494  double R = trial_field.get_elem().get_linear_size_estimate();
495  return d/R < limit;
496  }
497 
498  template <class result_t>
499  static result_t &eval(
500  result_t &result,
501  kernel_base<kernel_t> const &kernel,
502  field_base<TestField> const &test_field,
503  field_base<TrialField> const &trial_field
504  )
505  {
507  nsc_t nsc(trial_field, kernel);
508 
509  for (unsigned i = 0; i < num_test_nodes; ++i)
510  {
511  test_input_t tsti(test_field.get_elem(), test_nset_t::corner_at(i));
512  nsc.integrate(result.row(i), tsti);
513  }
514 
515  return result;
516  }
517 };
518 
519 
520 
521 
522 
523 
524 template <class TestField, class TrialField, class WaveNumber>
526  helmholtz_3d_HSP_kernel<WaveNumber>, TestField, TrialField,
527  typename std::enable_if<
528  is_collocational<TestField, TrialField>::value &&
529  is_constant_tria<TrialField>::value
530  >::type
531 >
532 {
534 public:
535  static bool needed(
536  kernel_base<kernel_t> const &kernel,
537  field_base<TestField> const &test_field,
538  field_base<TrialField> const &trial_field
539  )
540  {
541  double const limit = 1.5;
542 
543  // distance between element centres
544  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
545  double R = trial_field.get_elem().get_linear_size_estimate();
546  return d/R < limit;
547  }
548 
549  template <class result_t>
550  static result_t &eval(
551  result_t &result,
552  kernel_base<kernel_t> const &kernel,
553  field_base<TestField> const &test_field,
554  field_base<TrialField> const &trial_field
555  )
556  {
557  result(0) = helmholtz_3d_HSP_collocation_constant_plane_nearly_singular::eval(
558  trial_field.get_elem(),
559  test_field.get_elem().get_center(),
560  test_field.get_elem().get_normal().normalized(),
561  kernel.derived().get_wave_number());
562  return result;
563  }
564 };
565 
566 
567 template <class TestField, class TrialField, class WaveNumber>
569  helmholtz_3d_HSP_kernel<WaveNumber>, TestField, TrialField,
570  typename std::enable_if<
571  is_collocational<TestField, TrialField>::value &&
572  !is_constant_tria<TrialField>::value
573  >::type
574 >
575 {
577  typedef typename kernel_t::test_input_t test_input_t;
578  typedef TestField test_field_t;
579  typedef typename test_field_t::nset_t test_nset_t;
580  static unsigned const num_test_nodes = test_nset_t::num_nodes;
581 
582 public:
583  static bool needed(
584  kernel_base<kernel_t> const &kernel,
585  field_base<TestField> const &test_field,
586  field_base<TrialField> const &trial_field
587  )
588  {
589  double const limit = 1.5;
590 
591  // distance between element centres
592  double d = (test_field.get_elem().get_center() - trial_field.get_elem().get_center()).norm();
593  double R = trial_field.get_elem().get_linear_size_estimate();
594  return d/R < limit;
595  }
596 
597  template <class result_t>
598  static result_t &eval(
599  result_t &result,
600  kernel_base<kernel_t> const &kernel,
601  field_base<TestField> const &test_field,
602  field_base<TrialField> const &trial_field
603  )
604  {
606  nsc_t nsc(trial_field, kernel);
607 
608  for (unsigned i = 0; i < num_test_nodes; ++i)
609  {
610  test_input_t tsti(test_field.get_elem(), test_nset_t::corner_at(i));
611  nsc.integrate(result.row(i), tsti);
612  }
613 
614  return result;
615  }
616 };
617 
618 
619 template <class Elem, class WaveNumber>
621 {
622 public:
623  typedef Elem elem_t;
625  typedef typename kernel_t::test_input_t test_input_t;
626  typedef typename kernel_t::result_t res_t;
627 
628  static res_t eval(
629  test_input_t const &test_input,
630  elem_t const &elem,
631  kernel_base<kernel_t> const &kernel)
632  {
633  return helmholtz_3d_SLP_collocation_constant_plane_nearly_singular::eval(
634  elem,
635  test_input.get_x(),
636  kernel.derived().get_wave_number());
637  }
638 };
639 
640 template <class Elem, class WaveNumber>
642 {
643 public:
644  typedef Elem elem_t;
646  typedef typename kernel_t::test_input_t test_input_t;
647  typedef typename kernel_t::result_t res_t;
648 
649  static res_t eval(
650  test_input_t const &test_input,
651  elem_t const &elem,
652  kernel_base<kernel_t> const &kernel)
653  {
654  return helmholtz_3d_DLP_collocation_constant_plane_nearly_singular::eval(
655  elem,
656  test_input.get_x(),
657  kernel.derived().get_wave_number());
658  }
659 };
660 
661 
662 template <class Elem, class WaveNumber>
664 {
665 public:
666  typedef Elem elem_t;
668  typedef typename kernel_t::test_input_t test_input_t;
669  typedef typename kernel_t::result_t res_t;
670 
671  static res_t eval(
672  test_input_t const &test_input,
673  elem_t const &elem,
674  kernel_base<kernel_t> const &kernel)
675  {
676  return helmholtz_3d_DLPt_collocation_constant_plane_nearly_singular::eval(
677  elem,
678  test_input.get_x(),
679  test_input.get_unit_normal(),
680  kernel.derived().get_wave_number());
681  }
682 };
683 
684 
685 template <class Elem, class WaveNumber>
687 {
688 public:
689  typedef Elem elem_t;
691  typedef typename kernel_t::test_input_t test_input_t;
692  typedef typename kernel_t::result_t res_t;
693 
694  static res_t eval(
695  test_input_t const &test_input,
696  elem_t const &elem,
697  kernel_base<kernel_t> const &kernel)
698  {
699  return helmholtz_3d_HSP_collocation_constant_plane_nearly_singular::eval(
700  elem,
701  test_input.get_x(),
702  test_input.get_unit_normal(),
703  kernel.derived().get_wave_number());
704  }
705 };
706 
707 } // end of namespace NiHu
708 
709 #endif /* HELMHOLTZ_3D_NEARLY_SINGULAR_INTEGRALS_HPP_INCLUDED */
NiHu::nearly_singular_collocational
Definition: nearly_singular_collocational.hpp:22
NiHu::volume_element
class describing a volume element that has no normal vector
Definition: element.hpp:455
laplace_kernel.hpp
implementation of kernels of the Laplace equation
NiHu::laplace_3d_HSP_collocation_constant_plane_nearly_singular::eval
static double eval(elem_t const &elem, typename elem_t::x_t const &x0_in, typename elem_t::x_t const &nx_in)
Definition: laplace_3d_nearly_singular_integrals.hpp:320
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::regular_quad_store
store-wrapper of a statically stored quadrature
Definition: quadrature_store_helper.hpp:13
NiHu::kernel_base< kernel_t >
NiHu::nearly_singular_integral
Definition: nearly_singular_integral.hpp:27
NiHu::helmholtz_3d_SLP_collocation_constant_plane_nearly_singular
Nearly singular collocational integral of the 3D Helmholtz SLP kernel over planes.
Definition: helmholtz_3d_nearly_singular_integrals.hpp:46
NiHu::nearly_singular_planar_constant_collocation_shortcut
Definition: nearly_singular_planar_constant_collocation_shortcut.hpp:8
NiHu::nearly_singular_collocational_telles
Definition: nearly_singular_collocational_telles.hpp:116
NiHu::field_base::get_elem
const elem_t & get_elem() const
return underlying element
Definition: field.hpp:149
NiHu::field_base
CRTP base class of all fields.
Definition: field.hpp:111
NiHu::volume_element::domain_t
typename base_t::domain_t domain_t
the domain type
Definition: element.hpp:637
NiHu::helmholtz_3d_DLPt_collocation_constant_plane_nearly_singular
nearly singular collocational integral of the 3D Helmholtz DLPt kernel over planes
Definition: helmholtz_3d_nearly_singular_integrals.hpp:135
NiHu::normal_derivative_kernel
Normal derivative of a distance dependent kernel.
Definition: normal_derivative_kernel.hpp:26
helmholtz_kernel.hpp
Kernels of the Helmholtz equation .
NiHu::helmholtz_3d_HSP_collocation_constant_plane_nearly_singular
nearly singular collocational integral of the 3D Helmholtz HSP kernel over planes The singular static...
Definition: helmholtz_3d_nearly_singular_integrals.hpp:180
laplace_3d_nearly_singular_integrals.hpp
Nearly singular integrals for the Laplace kernels.
NiHu::helmholtz_3d_DLP_collocation_constant_plane_nearly_singular
nearly singular collocational integral of the 3D Helmholtz DLP kernel over planes The singular static...
Definition: helmholtz_3d_nearly_singular_integrals.hpp:89