NiHu  2.0
guiggiani_1992.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 
28 #ifndef GUIGGIANI_1992_HPP_INCLUDED
29 #define GUIGGIANI_1992_HPP_INCLUDED
30 
31 #include <boost/math/constants/constants.hpp>
32 
33 #include "line_quad_store.hpp"
34 #include "location_normal.hpp"
35 #include "weighted_input.hpp"
36 #include "../core/field.hpp"
37 #include "../core/kernel.hpp"
38 #include "../core/shapeset.hpp"
39 #include "../util/block_product.hpp"
40 #include "../util/store_pattern.hpp"
41 
42 #include <cmath>
43 #if NIHU_MEX_DEBUGGING
44 #include <mex.h>
45 #endif
46 
47 
48 namespace NiHu
49 {
50 
63 template <class singularity_type>
65 
67 typedef std::integral_constant<int, -2> _m2;
69 typedef std::integral_constant<int, -1> _m1;
71 typedef std::integral_constant<int, 0> _0;
73 typedef std::integral_constant<int, 1> _1;
75 typedef std::integral_constant<int, 2> _2;
76 
83 template <class TrialField, class Kernel, unsigned RadialOrder, unsigned TangentialOrder = RadialOrder, class Enable = void>
84 class guiggiani;
85 
86 
88 template <class TrialField, class Kernel, unsigned RadialOrder, unsigned TangentialOrder>
89 class guiggiani<TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if<
90  element_traits::is_surface_element<typename TrialField::elem_t>::value
91 >::type>
92 {
93 public:
95  enum {
96  radial_order = RadialOrder,
97  tangential_order = TangentialOrder
98  };
99 
101  typedef TrialField trial_field_t;
103  typedef typename trial_field_t::elem_t elem_t;
104 
106  typedef typename elem_t::domain_t domain_t;
108  typedef typename domain_t::xi_t xi_t;
110  typedef typename elem_t::scalar_t scalar_t;
112  typedef Eigen::Matrix<scalar_t, domain_t::dimension, domain_t::dimension> trans_t;
113 
115  typedef typename elem_t::x_t x_t;
116 
118  typedef typename trial_field_t::nset_t trial_nset_t;
120  typedef typename trial_nset_t::shape_t trial_n_shape_t;
121 
123  typedef Kernel kernel_t;
124 
129 
132 
137 
139  typedef typename semi_block_product_result_type<
140  typename singular_core_t::result_t, trial_n_shape_t
142 
144  typedef typename semi_block_product_result_type<
145  typename kernel_t::result_t, trial_n_shape_t
146  >::type total_result_t;
147 
149  enum {
152  };
153 
158  guiggiani(elem_t const &elem, kernel_base<kernel_t> const &kernel)
159  : m_elem(elem), m_kernel(kernel)
160  {
161  }
162 
163 private:
168  void compute_xi0(xi_t const &xi0, x_t const &normal)
169  {
170  // store the singular point and the unit normal vector
171  m_xi0 = xi0;
172  m_n0 = normal.normalized();
173 
174  // get the physical location and its gradient
175  m_x0 = m_elem.get_x(m_xi0);
176  typename elem_t::dx_return_type dx = m_elem.get_dx(m_xi0);
177 
178  scalar_t cosgamma = dx.col(shape_derivative_index::dXI).dot(dx.col(shape_derivative_index::dETA)) /
179  dx.col(shape_derivative_index::dXI).norm() / dx.col(shape_derivative_index::dETA).norm();
180  scalar_t u = dx.col(shape_derivative_index::dETA).norm() / dx.col(shape_derivative_index::dXI).norm();
181  m_T <<
182  1.0, cosgamma * u,
183  0.0, std::sqrt(1.0-cosgamma*cosgamma) * u;
184  // this scaling ensures that A is always equal to 1.0
185  // The transformation is Rong's improvement to Guiggiani
186  m_T *= dx.col(shape_derivative_index::dXI).norm();
187  m_Tinv = m_T.inverse();
188 
189  m_eta0 = m_T * m_xi0;
190 
191  scalar_t det_T = m_T.determinant();
192  if (std::isnan(det_T)) {
193  throw std::runtime_error(std::string("Error evaluating planar helper for Guiggiani integral (") +
194  "guiggiani_1992.hpp" + ", line:" + std::to_string(int(__LINE__)) + "): element #" + std::to_string(m_elem.get_id()[0]) + " is too distorted.");
195  }
196 
197  scalar_t sqrt_det_T = std::sqrt(std::abs(det_T)); // Linear size estimate
198 
199  m_Jvec_series[0] = m_elem.get_normal(m_xi0) / det_T;
200  m_N_series[0] = trial_nset_t::template eval_shape<0>(xi0);
201 
202  // geometrical parameters (planar helpers)
203  unsigned const N = domain_t::num_corners;
204  for (unsigned n = 0; n < N; ++n)
205  {
206  xi_t c1 = m_T * domain_t::get_corner(n); // corner
207  xi_t c2 = m_T * domain_t::get_corner((n + 1) % N); // next corner
208  xi_t l = xi_t::Zero();
209 
210  // Todo: add better check for heavily distorted element
211  // (Checking (c2 - c1).norm() does not seem to work Rong's improvement
212  if ((c2 - c1).norm() < 1e-2 * sqrt_det_T) {
213  throw std::runtime_error(std::string("Error evaluating planar helper for Guiggiani integral (") +
214  "guiggiani_1992.hpp" + ", line:" + std::to_string(int(__LINE__)) + "): element #" + std::to_string(m_elem.get_id()[0]) + " is too distorted.");
215  }
216 
217  l = (c2 - c1).normalized(); // side unit vector
218 
219  xi_t d1 = c1 - m_eta0; // vector to corners
220  xi_t d0 = d1 - l*d1.dot(l); // perpendicular to side
221 
222  m_theta_lim[n] = std::atan2(d1(1), d1(0)); // corner angle
223  m_theta0[n] = std::atan2(d0(1), d0(0)); // mid angle
224  m_ref_distance[n] = d0.norm(); // distance to side
225  }
226  }
227 
231  void compute_theta(scalar_t theta)
232  {
233  // contains cos theta sin theta in xi system
234  xi_t xi = m_Tinv.col(shape_derivative_index::dXI) * std::cos(theta)
235  + m_Tinv.col(shape_derivative_index::dETA) * std::sin(theta);
236 
237  typename elem_t::dx_return_type dx = m_elem.get_dx(m_xi0);
238 
239  m_rvec_series[0] = dx.col(shape_derivative_index::dXI) * xi(shape_derivative_index::dXI, 0)
241  if (laurent_order > 1) // compile_time IF
242  {
243  typename elem_t::ddx_return_type ddx = m_elem.get_ddx(m_xi0);
244 
245  m_rvec_series[1] = ddx.col(shape_derivative_index::dXIXI) * xi(shape_derivative_index::dXI, 0)*xi(shape_derivative_index::dXI, 0) / 2.0 +
248 
249  m_Jvec_series[1] = (
251  (
254  )
255  +
257  (
260  )
261  ) / m_T.determinant();
262 
263  auto dN = trial_nset_t::template eval_shape<1>(m_xi0);
264  m_N_series[1] = dN.col(shape_derivative_index::dXI)*xi(shape_derivative_index::dXI, 0)
266  }
267  }
268 
269 public:
276  template <class result_t>
277  void integrate(result_t &&I, xi_t const &xi0, x_t const &normal)
278  {
279  using namespace boost::math::double_constants;
280 
281 #if NIHU_MEX_DEBUGGING
282  static bool printed = false;
283  if (!printed)
284  {
285  mexPrintf("Computing integral with Guiggiani.\nRadial_order: %d\nTangential order: %d\n", RadialOrder, TangentialOrder);
286  printed = true;
287  }
288 #endif
289 
290  // compute the xi0-related quantities
291  compute_xi0(xi0, normal);
292 
293  // bind the kernel at the test input
294  test_input_t test_input(m_elem, m_xi0);
295  auto bound = m_kernel.bind(test_input);
296 
297  // iterate through triangles
298  unsigned const N = domain_t::num_corners;
299  for (unsigned n = 0; n < N; ++n)
300  {
301  // get angular integration limits
302  scalar_t t1 = m_theta_lim[n];
303  scalar_t t2 = m_theta_lim[(n + 1) % N];
304 
306  if (std::abs(t2-t1) < 1e-3)
307  continue;
308 
309  // we assume that the domain's corners are listed in positive order */
310  if (std::abs(t2 - t1) > pi)
311  t2 += two_pi;
312 
313  // theta integration
314  for (auto const &q_theta : line_quad_store<tangential_order>::quadrature)
315  {
316  // compute theta base point and weight
317  scalar_t xx = q_theta.get_xi()(0);
318  scalar_t theta = ((1.0 - xx) * t1 + (1.0 + xx) * t2) / 2.0;
319  scalar_t w_theta = q_theta.get_w() * (t2 - t1) / 2.0;
320 
321  // compute theta-related members
322  compute_theta(theta);
323  laurent_t::eval(*this);
324 
325  // reference domain's limit
326  scalar_t rho_lim = m_ref_distance[n] / std::cos(theta - m_theta0[n]);
327 
328  laurent_coeff_t toadd = m_Fcoeffs[0] * std::log(rho_lim);
329  if (laurent_order > 1) // compile_time IF
330  toadd -= m_Fcoeffs[1] / rho_lim;
331  toadd *= w_theta;
332 
333  I += toadd;
334 
335 /* this was for old Eigen versions (scalar casting)
336  for (int r = 0; r < I.rows(); ++r) // loop needed for scalar casting
337  for (int c = 0; c < I.cols(); ++c)
338  I(r,c) += toadd(r,c);
339 */
340 
341  // radial part of surface integration
342  for (auto const &q_rho : line_quad_store<radial_order>::quadrature)
343  {
344  // quadrature base point and weight
345  scalar_t rho = (1.0 + q_rho.get_xi()(0)) * rho_lim / 2.0;
346  scalar_t w_rho = q_rho.get_w() * rho_lim / 2.0;
347 
348  // compute location in original reference domain
349  xi_t eta(rho*std::cos(theta), rho*std::sin(theta));
350  xi_t xi = m_Tinv * eta + m_xi0;
351 
352  // evaluate G * N * J * rho
353  w_trial_input_t trial_input(m_elem, xi);
354  typename kernel_t::result_t GJrho =
355  bound(trial_input) * (trial_input.get_jacobian() / m_T.determinant() * rho);
356  typename trial_nset_t::shape_t N =
357  trial_nset_t::template eval_shape<0>(xi);
358  total_result_t F = semi_block_product(GJrho, N);
359 
360  // subtract the analytical singularity
361  laurent_coeff_t singular_part = m_Fcoeffs[0];
362  if (laurent_order > 1) // compile_time IF
363  singular_part += m_Fcoeffs[1] / rho;
364  singular_part /= rho;
365 
366  F -= singular_part;
367 /* this loop was needed for casting from Matrix<double> to Matrix<complex>
368  for (int r = 0; r < F.rows(); ++r)
369  for (int c = 0; c < F.cols(); ++c)
370  F(r,c) -= singular_part(r,c);
371 */
372 
373  // surface integral accumulation
374  I += w_theta * w_rho * F;
375  } // rho loop
376  } // theta loop
377  } // element sides
378  } // end of function integrate
379 
381  template <class T, T order>
382  x_t const &get_rvec_series(std::integral_constant<T, order>) const
383  {
384  static_assert((order-1)>=0, "Required distance Taylor coefficient too low");
385  static_assert((order-1) < laurent_order, "Required distance Taylor coefficient too high");
386  return m_rvec_series[order-1];
387  }
388 
390  template <class T, T order>
391  x_t const &get_Jvec_series(std::integral_constant<T, order>) const
392  {
393  static_assert(order < laurent_order, "Required Jacobian Taylor coefficient too high");
394  static_assert(order >= 0, "Required Jacobian Taylor coefficient too low");
395  return m_Jvec_series[order];
396  }
397 
399  template <class T, T order>
400  trial_n_shape_t const &get_shape_series(std::integral_constant<T, order>) const
401  {
402  static_assert(order < laurent_order, "Required shape set Taylor coefficient too high");
403  static_assert(order >= 0, "Required Jacobian Taylor coefficient too low");
404  return m_N_series[order];
405  }
406 
408  template <class T, T order>
409  laurent_coeff_t &get_laurent_coeff(std::integral_constant<T, order>)
410  {
411  static_assert(-(order+1) < laurent_order, "Required Laurent coefficient too high");
412  static_assert(-(order+1) >= 0, "Required Laurent coefficient too low");
413  return m_Fcoeffs[-(order+1)];
414  }
415 
417  template <class T, T order>
418  void set_laurent_coeff(std::integral_constant<T, order>, laurent_coeff_t const &v)
419  {
420  static_assert(-(order+1) < laurent_order, "Required Laurent coefficient too high");
421  static_assert(-(order+1) >= 0, "Required Laurent coefficient too low");
422  m_Fcoeffs[-(order+1)] = v;
423  }
424 
426  x_t const &get_n0(void) const
427  {
428  return m_n0;
429  }
430 
431  kernel_t const &get_kernel(void) const
432  {
433  return m_kernel.derived();
434  }
435 
436 private:
437  elem_t const &m_elem;
438  kernel_base<kernel_t> const &m_kernel;
440  xi_t m_xi0;
441  x_t m_x0;
442  x_t m_n0;
444  trans_t m_T;
445  trans_t m_Tinv;
446  xi_t m_eta0;
449  scalar_t m_theta_lim[domain_t::num_corners];
451  scalar_t m_theta0[domain_t::num_corners];
453  scalar_t m_ref_distance[domain_t::num_corners];
454 
455  x_t m_rvec_series[laurent_order];
456  x_t m_Jvec_series[laurent_order];
457  trial_n_shape_t m_N_series[laurent_order];
458  laurent_coeff_t m_Fcoeffs[laurent_order];
459 };
460 
461 
462 
468 template <class TrialField, class Kernel, unsigned RadialOrder, unsigned TangentialOrder>
469 class guiggiani<TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if<
470  !element_traits::is_surface_element<typename TrialField::elem_t>::value
471 >::type>
472 {
473 public:
475  enum {
476  radial_order = RadialOrder,
477  tangential_order = TangentialOrder
478  };
479 
481  typedef TrialField trial_field_t;
483  typedef typename trial_field_t::elem_t elem_t;
484 
486  typedef typename elem_t::domain_t domain_t;
488  typedef typename domain_t::xi_t xi_t;
490  typedef typename elem_t::scalar_t scalar_t;
492  typedef Eigen::Matrix<scalar_t, domain_t::dimension, domain_t::dimension> trans_t;
493 
495  typedef typename elem_t::x_t x_t;
496 
498  typedef typename trial_field_t::nset_t trial_nset_t;
500  typedef typename trial_nset_t::shape_t trial_n_shape_t;
501 
503  typedef Kernel kernel_t;
504 
509 
512 
517 
519  typedef typename semi_block_product_result_type<
520  typename singular_core_t::result_t, trial_n_shape_t
522 
524  typedef typename semi_block_product_result_type<
525  typename kernel_t::result_t, trial_n_shape_t
526  >::type total_result_t;
527 
529  enum {
532  };
533 
538  guiggiani(elem_t const &elem, kernel_base<kernel_t> const &kernel)
539  : m_elem(elem), m_kernel(kernel)
540  {
541  }
542 
543 private:
547  void compute_xi0(xi_t const &xi0)
548  {
549  m_xi0 = xi0;
550  m_x0 = m_elem.get_x(m_xi0);
551  typename elem_t::dx_return_type dx = m_elem.get_dx(m_xi0);
552 
553  scalar_t cosgamma = dx.col(shape_derivative_index::dXI).dot(dx.col(shape_derivative_index::dETA)) /
554  dx.col(shape_derivative_index::dXI).norm() / dx.col(shape_derivative_index::dETA).norm();
555  scalar_t u = dx.col(shape_derivative_index::dETA).norm() / dx.col(shape_derivative_index::dXI).norm();
556  m_T <<
557  1.0, cosgamma * u,
558  0.0, std::sqrt(1.0-cosgamma*cosgamma) * u;
559  // this scaling ensures that A is always equal to 1.0
560  m_T *= dx.col(shape_derivative_index::dXI).norm();
561  m_Tinv = m_T.inverse();
562 
563  m_eta0 = m_T * m_xi0;
564 
565  m_J_series[0] = m_elem.get_dx(m_xi0).determinant() / m_T.determinant();
566  m_N_series[0] = trial_nset_t::template eval_shape<0>(xi0);
567 
568  // geometrical parameters (planar helpers)
569  unsigned const N = domain_t::num_corners;
570  for (unsigned n = 0; n < N; ++n)
571  {
572  xi_t c1 = m_T * domain_t::get_corner(n); // corner
573  xi_t c2 = m_T * domain_t::get_corner((n + 1) % N); // next corner
574  xi_t l = (c2 - c1).normalized(); // side vector
575 
576  xi_t d1 = c1 - m_eta0; // vector to corners
577  xi_t d0 = d1 - l*d1.dot(l); // perpendicular to side
578 
579  m_theta_lim[n] = std::atan2(d1(1), d1(0)); // corner angle
580  m_theta0[n] = std::atan2(d0(1), d0(0)); // mid angle
581  m_ref_distance[n] = d0.norm(); // distance to side
582  }
583  }
584 
585  template <class Input1, class Input2>
586  typename Input1::Scalar detvectors(Eigen::DenseBase<Input1> const &v1, Eigen::DenseBase<Input2> const &v2)
587  {
588  return v1(0)*v2(1) - v1(1)*v2(0);
589  }
590 
594  void compute_theta(scalar_t theta)
595  {
596  // contains cos theta sin theta in xi system
597  xi_t xi = m_Tinv.col(shape_derivative_index::dXI) * std::cos(theta)
598  + m_Tinv.col(shape_derivative_index::dETA) * std::sin(theta);
599 
600  typename elem_t::dx_return_type dx = m_elem.get_dx(m_xi0);
601 
602  m_rvec_series[0] = dx.col(shape_derivative_index::dXI) * xi(shape_derivative_index::dXI, 0)
604  if (laurent_order > 1) // compile_time IF
605  {
606  typename elem_t::ddx_return_type ddx = m_elem.get_ddx(m_xi0);
607 
608  m_rvec_series[1] =
611  +
614  +
617 
618  m_J_series[1] = (
619  xi(0, 0) *
620  (
621  detvectors(ddx.col(shape_derivative_index::dXIXI), dx.col(shape_derivative_index::dETA)) +
622  detvectors(dx.col(shape_derivative_index::dXI), ddx.col(shape_derivative_index::dXIETA))
623  )
624  +
625  xi(1, 0) *
626  (
627  detvectors(ddx.col(shape_derivative_index::dETAXI), dx.col(shape_derivative_index::dETA))+
629  )
630  ) / m_T.determinant();
631 
632  auto dN = trial_nset_t::template eval_shape<1>(m_xi0);
633  m_N_series[1] = dN.col(shape_derivative_index::dXI)*xi(shape_derivative_index::dXI, 0)
635  }
636  }
637 
638 public:
645  template <class result_t>
646  void integrate(result_t &&I, xi_t const &xi0)
647  {
648  using namespace boost::math::double_constants;
649 
650 #if NIHU_MEX_DEBUGGING
651  static bool printed = false;
652  if (!printed)
653  {
654  mexPrintf("Computing integral with Guiggiani.\nRadial_order: %d\nTangential order: %d\n", RadialOrder, TangentialOrder);
655  printed = true;
656  }
657 #endif
658 
659  // compute the xi0-related quantities
660  compute_xi0(xi0);
661 
662  // bind the kernel at the test input
663  test_input_t test_input(m_elem, m_xi0);
664  auto bound = m_kernel.bind(test_input);
665 
666  // iterate through triangles
667  unsigned const N = domain_t::num_corners;
668  for (unsigned n = 0; n < N; ++n)
669  {
670  // get angular integration limits
671  scalar_t t1 = m_theta_lim[n];
672  scalar_t t2 = m_theta_lim[(n + 1) % N];
673 
674  // we assume that the domain's corners are listed in positive order
675  if (std::abs(t2 - t1) > pi)
676  t2 += two_pi;
677 
678  // theta integration
679  for (auto const &q_theta : line_quad_store<tangential_order>::quadrature)
680  {
681  // compute theta base point and weight
682  scalar_t xx = q_theta.get_xi()(0);
683  scalar_t theta = ((1.0 - xx) * t1 + (1.0 + xx) * t2) / 2.0;
684  scalar_t w_theta = q_theta.get_w() * (t2 - t1) / 2.0;
685 
686  // compute theta-related members
687  compute_theta(theta);
688  laurent_t::eval(*this);
689 
690  // reference domain's limit
691  scalar_t rho_lim = m_ref_distance[n] / std::cos(theta - m_theta0[n]);
692 
693  laurent_coeff_t toadd = m_Fcoeffs[0] * std::log(rho_lim);
694  if (laurent_order > 1) // compile_time IF
695  toadd -= m_Fcoeffs[1] / rho_lim;
696  toadd *= w_theta;
697 
698  for (int r = 0; r < I.rows(); ++r) // loop needed for scalar casting
699  for (int c = 0; c < I.cols(); ++c)
700  I(r,c) += toadd(r,c);
701 
702  // radial part of surface integration
703  for (auto const &q_rho : line_quad_store<radial_order>::quadrature)
704  {
705  // quadrature base point and weight
706  scalar_t rho = (1.0 + q_rho.get_xi()(0)) * rho_lim / 2.0;
707  scalar_t w_rho = q_rho.get_w() * rho_lim / 2.0;
708 
709  // compute location in original reference domain
710  xi_t eta(rho*std::cos(theta), rho*std::sin(theta));
711  xi_t xi = m_Tinv * eta + m_xi0;
712 
713  // evaluate G * N * J * rho
714  w_trial_input_t trial_input(m_elem, xi);
715  typename kernel_t::result_t GJrho =
716  bound(trial_input) * (trial_input.get_jacobian() / m_T.determinant() * rho);
717  typename trial_nset_t::shape_t N =
718  trial_nset_t::template eval_shape<0>(xi);
719  total_result_t F = semi_block_product(GJrho, N);
720 
721  // subtract the analytical singularity
722  laurent_coeff_t singular_part = m_Fcoeffs[0];
723  if (laurent_order > 1) // compile_time IF
724  singular_part += m_Fcoeffs[1] / rho;
725  singular_part /= rho;
726 
727  for (int r = 0; r < F.rows(); ++r) // loop needed for scalar casting
728  for (int c = 0; c < F.cols(); ++c)
729  F(r,c) -= singular_part(r,c);
730 
731  // surface integral accumulation
732  I += w_theta * w_rho * F;
733  } // rho loop
734  } // theta loop
735  } // element sides
736  }
737 
739  template <class T, T order>
740  x_t const &get_rvec_series(std::integral_constant<T, order>) const
741  {
742  static_assert((order-1)>=0, "Required distance Taylor coefficient too low");
743  static_assert((order-1) < laurent_order, "Required distance Taylor coefficient too high");
744  return m_rvec_series[order-1];
745  }
746 
748  template <class T, T order>
749  double get_J_series(std::integral_constant<T, order>) const
750  {
751  static_assert(order < laurent_order, "Required Jacobian Taylor coefficient too high");
752  static_assert(order >= 0, "Required Jacobian Taylor coefficient too low");
753  return m_J_series[order];
754  }
755 
757  template <class T, T order>
758  trial_n_shape_t const &get_shape_series(std::integral_constant<T, order>) const
759  {
760  static_assert(order < laurent_order, "Required shape set Taylor coefficient too high");
761  static_assert(order >= 0, "Required Jacobian Taylor coefficient too low");
762  return m_N_series[order];
763  }
764 
766  template <class T, T order>
767  laurent_coeff_t &get_laurent_coeff(std::integral_constant<T, order>)
768  {
769  static_assert(-(order+1) < laurent_order, "Required Laurent coefficient too high");
770  static_assert(-(order+1) >= 0, "Required Laurent coefficient too low");
771  return m_Fcoeffs[-(order+1)];
772  }
773 
775  template <class T, T order>
776  void set_laurent_coeff(std::integral_constant<T, order>, laurent_coeff_t const &v)
777  {
778  static_assert(-(order+1) < laurent_order, "Required Laurent coefficient too high");
779  static_assert(-(order+1) >= 0, "Required Laurent coefficient too low");
780  m_Fcoeffs[-(order+1)] = v;
781  }
782 
783 
784  kernel_t const &get_kernel(void) const
785  {
786  return m_kernel.derived();
787  }
788 
789 
790 private:
791  elem_t const &m_elem;
792  kernel_base<kernel_t> const &m_kernel;
794  xi_t m_xi0;
795  x_t m_x0;
797  trans_t m_T;
798  trans_t m_Tinv;
799  xi_t m_eta0;
802  scalar_t m_theta_lim[domain_t::num_corners];
804  scalar_t m_theta0[domain_t::num_corners];
806  scalar_t m_ref_distance[domain_t::num_corners];
807 
808  x_t m_rvec_series[laurent_order];
809  scalar_t m_J_series[laurent_order];
810  trial_n_shape_t m_N_series[laurent_order];
811  laurent_coeff_t m_Fcoeffs[laurent_order];
812 };
813 
814 }
815 
816 
817 
818 #endif // GUIGGIANI_1992_HPP_INCLUDED
819 
NiHu::polar_laurent_coeffs
definition of Laurent coefficients of singularities
Definition: guiggiani_1992.hpp:64
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::elem_t
trial_field_t::elem_t elem_t
the element type
Definition: guiggiani_1992.hpp:483
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_laurent_coeff
laurent_coeff_t & get_laurent_coeff(std::integral_constant< T, order >)
return a Laurent coefficient
Definition: guiggiani_1992.hpp:409
NiHu::shape_derivative_index::dETAETA
@ dETAETA
index of eta_eta in 2nd derivative matrix
Definition: shapeset.hpp:54
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_n_shape_t
trial_nset_t::shape_t trial_n_shape_t
the shape function vector type
Definition: guiggiani_1992.hpp:500
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::laurent_t
polar_laurent_coeffs< singular_core_t > laurent_t
the Laurent coefficients computing class
Definition: guiggiani_1992.hpp:516
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::scalar_t
elem_t::scalar_t scalar_t
the geometrical scalar type
Definition: guiggiani_1992.hpp:490
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::set_laurent_coeff
void set_laurent_coeff(std::integral_constant< T, order >, laurent_coeff_t const &v)
set a Laurent coefficient
Definition: guiggiani_1992.hpp:776
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::guiggiani
guiggiani(elem_t const &elem, kernel_base< kernel_t > const &kernel)
constructor
Definition: guiggiani_1992.hpp:538
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_input_t
kernel_traits< kernel_t >::trial_input_t trial_input_t
the kernel's trial input type
Definition: guiggiani_1992.hpp:508
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_nset_t
trial_field_t::nset_t trial_nset_t
shape function set type
Definition: guiggiani_1992.hpp:118
NiHu::kernel_base< kernel_t >
NiHu::semi_block_product
semi_block_product_result_type< mat, rightDerived >::type semi_block_product(mat const &m, Eigen::MatrixBase< rightDerived > const &r)
compute semi block product of a matrix and a vector m * v^T
Definition: block_product.hpp:194
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::elem_t
trial_field_t::elem_t elem_t
the element type
Definition: guiggiani_1992.hpp:103
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::total_result_t
semi_block_product_result_type< typename kernel_t::result_t, trial_n_shape_t >::type total_result_t
value type of the integral result
Definition: guiggiani_1992.hpp:146
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_n0
const x_t & get_n0(void) const
return the unit normal at the collocation point
Definition: guiggiani_1992.hpp:426
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::xi_t
domain_t::xi_t xi_t
the reference coordinate vector type
Definition: guiggiani_1992.hpp:488
NiHu::semi_block_product_result_type
metafunction returning the value type of a semi block product
Definition: block_product.hpp:180
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::singular_core_t
singular_kernel_traits< kernel_t >::singular_core_t singular_core_t
the singular core type
Definition: guiggiani_1992.hpp:134
NiHu::shape_derivative_index::dXI
@ dXI
index of xi in 1st derivative matrix
Definition: shapeset.hpp:49
NiHu::_2
std::integral_constant< int, 2 > _2
shorthand for constant two
Definition: guiggiani_1992.hpp:75
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::domain_t
elem_t::domain_t domain_t
the original reference domain type
Definition: guiggiani_1992.hpp:486
NiHu::_m1
std::integral_constant< int, -1 > _m1
shorthand for constant minus one
Definition: guiggiani_1992.hpp:69
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_field_t
TrialField trial_field_t
the trial field type
Definition: guiggiani_1992.hpp:101
NiHu::singular_kernel_traits::singular_core_t
kernel_traits_ns::singular_core< Derived >::type singular_core_t
the kernel's singular core type
Definition: kernel.hpp:106
location_normal.hpp
implementation of location and normal kernel inputs
NiHu::shape_derivative_index::dETA
@ dETA
index of eta in 1st derivative matrix
Definition: shapeset.hpp:50
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_rvec_series
const x_t & get_rvec_series(std::integral_constant< T, order >) const
return Taylor coefficient of the distance measured from the collocation point
Definition: guiggiani_1992.hpp:382
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::set_laurent_coeff
void set_laurent_coeff(std::integral_constant< T, order >, laurent_coeff_t const &v)
set a Laurent coefficient
Definition: guiggiani_1992.hpp:418
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_input_t
kernel_traits< kernel_t >::trial_input_t trial_input_t
the kernel's trial input type
Definition: guiggiani_1992.hpp:128
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_shape_series
const trial_n_shape_t & get_shape_series(std::integral_constant< T, order >) const
return Taylor coefficient of the shape set around the collocation point
Definition: guiggiani_1992.hpp:758
NiHu::exponential_covariance_kernel
Definition: covariance_kernel.hpp:42
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::kernel_t
Kernel kernel_t
the kernel type
Definition: guiggiani_1992.hpp:503
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_field_t
TrialField trial_field_t
the trial field type
Definition: guiggiani_1992.hpp:481
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::laurent_coeff_t
semi_block_product_result_type< typename singular_core_t::result_t, trial_n_shape_t >::type laurent_coeff_t
value type of the Laurent coefficients
Definition: guiggiani_1992.hpp:521
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::scalar_t
elem_t::scalar_t scalar_t
the geometrical scalar type
Definition: guiggiani_1992.hpp:110
NiHu::_1
std::integral_constant< int, 1 > _1
shorthand for constant one
Definition: guiggiani_1992.hpp:73
NiHu::volume_element::domain_t
typename base_t::domain_t domain_t
the domain type
Definition: element.hpp:637
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::guiggiani
guiggiani(elem_t const &elem, kernel_base< kernel_t > const &kernel)
constructor
Definition: guiggiani_1992.hpp:158
NiHu::shape_derivative_index::dXIETA
@ dXIETA
index of xi_eta in 2nd derivative matrix
Definition: shapeset.hpp:52
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::total_result_t
semi_block_product_result_type< typename kernel_t::result_t, trial_n_shape_t >::type total_result_t
value type of the integral result
Definition: guiggiani_1992.hpp:526
NiHu::_0
std::integral_constant< int, 0 > _0
shorthand for constant zero
Definition: guiggiani_1992.hpp:71
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::xi_t
domain_t::xi_t xi_t
the reference coordinate vector type
Definition: guiggiani_1992.hpp:108
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::test_input_t
kernel_traits< kernel_t >::test_input_t test_input_t
the kernel's test input type
Definition: guiggiani_1992.hpp:506
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::x_t
elem_t::x_t x_t
the physical coordinate vector type
Definition: guiggiani_1992.hpp:495
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::integrate
void integrate(result_t &&I, xi_t const &xi0, x_t const &normal)
the entry point of integration
Definition: guiggiani_1992.hpp:277
NiHu::weighted_input
the weigthed input is an extended input that contains the jacobian a well
Definition: weighted_input.hpp:19
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::domain_t
elem_t::domain_t domain_t
the original reference domain type
Definition: guiggiani_1992.hpp:106
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_rvec_series
const x_t & get_rvec_series(std::integral_constant< T, order >) const
return Taylor coefficient of the distance measured from the collocation point
Definition: guiggiani_1992.hpp:740
weighted_input.hpp
implementation of metafunction NiHu::weighted_input
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trans_t
Eigen::Matrix< scalar_t, domain_t::dimension, domain_t::dimension > trans_t
the Rong's transformation matrix type
Definition: guiggiani_1992.hpp:112
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::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_shape_series
const trial_n_shape_t & get_shape_series(std::integral_constant< T, order >) const
return Taylor coefficient of the shape set around the collocation point
Definition: guiggiani_1992.hpp:400
NiHu::_m2
std::integral_constant< int, -2 > _m2
shorthand for constant minus two
Definition: guiggiani_1992.hpp:64
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::w_trial_input_t
weighted_input< trial_input_t, elem_t >::type w_trial_input_t
the kernel's weighted trial input type
Definition: guiggiani_1992.hpp:511
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::w_trial_input_t
weighted_input< trial_input_t, elem_t >::type w_trial_input_t
the kernel's weighted trial input type
Definition: guiggiani_1992.hpp:131
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_Jvec_series
const x_t & get_Jvec_series(std::integral_constant< T, order >) const
return Taylor coefficient of the Jacobian vector around the collocation point
Definition: guiggiani_1992.hpp:391
NiHu::kernel_traits
traits class of a kernel
Definition: kernel.hpp:71
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_J_series
double get_J_series(std::integral_constant< T, order >) const
return Taylor coefficient of the Jacobian vector around the collocation point
Definition: guiggiani_1992.hpp:749
NiHu::shape_derivative_index::dETAXI
@ dETAXI
index of eta_xi in 2nd derivative matrix
Definition: shapeset.hpp:53
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_n_shape_t
trial_nset_t::shape_t trial_n_shape_t
the shape function vector type
Definition: guiggiani_1992.hpp:120
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trans_t
Eigen::Matrix< scalar_t, domain_t::dimension, domain_t::dimension > trans_t
the Rong's transformation matrix type
Definition: guiggiani_1992.hpp:492
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::laurent_t
polar_laurent_coeffs< singular_core_t > laurent_t
the Laurent coefficients computing class
Definition: guiggiani_1992.hpp:136
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::singular_core_t
singular_kernel_traits< kernel_t >::singular_core_t singular_core_t
the singular core type
Definition: guiggiani_1992.hpp:514
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::trial_nset_t
trial_field_t::nset_t trial_nset_t
shape function set type
Definition: guiggiani_1992.hpp:498
NiHu::shape_derivative_index::dXIXI
@ dXIXI
index of xi_xi in 2nd derivative matrix
Definition: shapeset.hpp:51
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::integrate
void integrate(result_t &&I, xi_t const &xi0)
the entry point of integration
Definition: guiggiani_1992.hpp:646
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::kernel_t
Kernel kernel_t
the kernel type
Definition: guiggiani_1992.hpp:123
NiHu::guiggiani
Implementation of Guiggiani's method.
Definition: guiggiani_1992.hpp:84
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< !element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::get_laurent_coeff
laurent_coeff_t & get_laurent_coeff(std::integral_constant< T, order >)
return a Laurent coefficient
Definition: guiggiani_1992.hpp:767
NiHu::line_quad_store
store-wrapper of a statically stored line quadrature
Definition: line_quad_store.hpp:11
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::laurent_coeff_t
semi_block_product_result_type< typename singular_core_t::result_t, trial_n_shape_t >::type laurent_coeff_t
value type of the Laurent coefficients
Definition: guiggiani_1992.hpp:141
NiHu::singular_kernel_traits
singular traits class of a kernel
Definition: kernel.hpp:101
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::test_input_t
kernel_traits< kernel_t >::test_input_t test_input_t
the kernel's test input type
Definition: guiggiani_1992.hpp:126
NiHu::guiggiani< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::x_t
elem_t::x_t x_t
the physical coordinate vector type
Definition: guiggiani_1992.hpp:115
NiHu::volume_element
class describing a volume element that has no normal vector
Definition: element.hpp:455