NiHu  2.0
nearly_singular_collocational.hpp
1 #ifndef NIHU_NEARLY_SINGULAR_COLLOCATIONAL_HPP_INCLUDED
2 #define NIHU_NEARLY_SINGULAR_COLLOCATIONAL_HPP_INCLUDED
3 
4 #include <boost/math/constants/constants.hpp>
5 
6 #include "line_quad_store.hpp"
7 #include "location_normal.hpp"
8 #include "weighted_input.hpp"
9 #include "../core/element.hpp"
10 #include "../core/field.hpp"
11 #include "../core/inverse_mapping.hpp"
12 #include "../core/kernel.hpp"
13 #include "../core/nearly_singular_planar_constant_collocation_shortcut.hpp"
14 #include "../core/shapeset.hpp"
15 #include "../util/block_product.hpp"
16 
17 namespace NiHu
18 {
19 template <class TrialField, class Kernel,
20  unsigned RadialOrder, unsigned TangentialOrder,
21  class Enable = void>
23 
24 template <class TrialField, class Kernel,
25  unsigned RadialOrder, unsigned TangentialOrder>
26 class nearly_singular_collocational<TrialField, Kernel, RadialOrder, TangentialOrder,
27  typename std::enable_if<
28  element_traits::is_surface_element<typename TrialField::elem_t>::value
29  >::type>
30 {
31 public:
33  enum {
34  radial_order = RadialOrder,
35  tangential_order = TangentialOrder
36  };
37 
39  typedef TrialField trial_field_t;
41  typedef typename trial_field_t::elem_t elem_t;
42 
44  typedef typename elem_t::domain_t domain_t;
46  typedef typename domain_t::xi_t xi_t;
48  typedef typename elem_t::scalar_t scalar_t;
49 
51  typedef typename elem_t::x_t x_t;
52 
54  typedef typename trial_field_t::nset_t trial_nset_t;
56  typedef typename trial_nset_t::shape_t trial_n_shape_t;
57 
59  typedef Kernel kernel_t;
60 
65 
68 
70  typedef typename semi_block_product_result_type<
71  typename kernel_t::result_t, trial_n_shape_t
72  >::type total_result_t;
73 
79  field_base<trial_field_t> const &trial_field,
80  kernel_base<kernel_t> const &kernel)
81  : m_elem(trial_field.get_elem())
82  , m_kernel(kernel)
83  {
84  }
85 
86  template <class result_t>
87  void integrate(result_t &&I, test_input_t const &tsi)
88  {
89  using namespace boost::math::double_constants;
90 
91  // the reference point
92  x_t x0 = tsi.get_x();
93 
94  // perform inverse mapping to obtain image of reference point on element
95  double tol = 1e-5;
96  unsigned max_iter = 100;
97  // inverse mapping constrained inside element
98  inverse_mapping<elem_t> im(m_elem, true);
99  if (!im.eval(x0, tol, max_iter))
100  throw std::runtime_error("Could not perform inverse mapping");
101  auto res = im.get_result();
102  m_xi0 = res.topRows(xi_t::RowsAtCompileTime);
103  m_zeta = res(xi_t::RowsAtCompileTime);
104 
105  // compute linearized element
106  elem_t lin_elem = m_elem.get_linearized_elem(m_xi0);
107 
108  // get jacobian at the reference image
109  auto N0 = trial_nset_t::template eval_shape<0>(m_xi0);
110 
112  // geometrical parameters (planar helpers)
113  unsigned const N = domain_t::num_corners;
114  for (unsigned n = 0; n < N; ++n)
115  {
116  xi_t c1 = domain_t::get_corner(n); // corner
117  xi_t c2 = domain_t::get_corner((n + 1) % N); // next corner
118  xi_t l = xi_t::Zero();
119  l(0) = 1.0;
120  if ((c2 - c1).norm() > 1e-3)
121  l = (c2 - c1).normalized(); // side unit vector
122 
123  xi_t d1 = c1 - m_xi0; // vector to corners
124  xi_t d0 = d1 - l * d1.dot(l); // perpendicular to side
125 
126  m_theta_lim[n] = std::atan2(d1(1), d1(0)); // corner angle
127  m_theta0[n] = std::atan2(d0(1), d0(0)); // mid angle
128  m_ref_distance[n] = d0.norm(); // distance to side
129  }
130 
131  // iterate through triangles
132  for (unsigned n = 0; n < N; ++n)
133  {
134  // get angular integration limits
135  scalar_t t1 = m_theta_lim[n];
136  scalar_t t2 = m_theta_lim[(n + 1) % N];
137 
138  // angle check
139  if (std::abs(t2 - t1) > pi)
140  {
141  if (t2 > t1)
142  t1 += two_pi;
143  else t2 += two_pi;
144  }
145 
147  if (std::abs(t2 - t1) < 1e-3)
148  continue;
149 
150  // theta integration
151  for (auto const &q_theta : line_quad_store<tangential_order>::quadrature)
152  {
153  // compute theta base point and weight
154  scalar_t xx = q_theta.get_xi()(0);
155  scalar_t theta = ((1.0 - xx) * t1 + (1.0 + xx) * t2) / 2.0;
156  scalar_t w_theta = q_theta.get_w() * (t2 - t1) / 2.0;
157 
158  // reference domain's limit
159  scalar_t rho_lim = m_ref_distance[n] / std::cos(theta - m_theta0[n]);
160 
161  // radial part of surface integration
162  for (auto const &q_rho : line_quad_store<radial_order>::quadrature)
163  {
164  // quadrature base point and weight
165  scalar_t rho = (1.0 + q_rho.get_xi()(0)) * rho_lim / 2.0;
166  scalar_t w_rho = q_rho.get_w() * rho_lim / 2.0;
167 
168  // compute location in reference domain
169  xi_t xi(rho*std::cos(theta), rho*std::sin(theta));
170  xi += m_xi0;
171 
172  // evaluate weighted trial input
173  w_trial_input_t tri(m_elem, xi);
174  w_trial_input_t tri_lin(lin_elem, xi);
175 
176  // evaluate kernel
177  typename kernel_t::result_t GJ = m_kernel(tsi, tri)
178  * tri.get_jacobian();
179  typename kernel_t::result_t GJ_lin = m_kernel(tsi, tri_lin)
180  * tri_lin.get_jacobian();
181 
182  // get shape function
183  auto N = trial_nset_t::template eval_shape<0>(xi);
185  total_result_t F_lin = semi_block_product(GJ_lin, N0);
186 
187  I += w_theta * w_rho * rho * (F - F_lin);
188  } // end of loop over radial nodes
189  } // end of loop over tangential nodes
190  } // end of loop over triangles
191 
192  typename kernel_t::result_t anal_res =
194  tsi, lin_elem, m_kernel
195  );
196 
197  I += semi_block_product(anal_res, N0);
198 
199  } // end of function integrate
200 
201 private:
202  elem_t const &m_elem;
203  kernel_base<kernel_t> const &m_kernel;
204  xi_t m_xi0;
205  double m_zeta;
206 
207  double m_theta_lim[domain_t::num_corners];
208  double m_theta0[domain_t::num_corners];
209  double m_ref_distance[domain_t::num_corners];
210 };
211 
212 } // end of namespace NiHu
213 
214 #endif /* NIHU_NEARLY_SINGULAR_COLLOCATIONAL_HPP_INCLUDED */
NiHu::nearly_singular_collocational
Definition: nearly_singular_collocational.hpp:22
NiHu::nearly_singular_collocational< TrialField, Kernel, RadialOrder, TangentialOrder, typename std::enable_if< element_traits::is_surface_element< typename TrialField::elem_t >::value >::type >::nearly_singular_collocational
nearly_singular_collocational(field_base< trial_field_t > const &trial_field, kernel_base< kernel_t > const &kernel)
constructor
Definition: nearly_singular_collocational.hpp:78
NiHu::volume_element
class describing a volume element that has no normal vector
Definition: element.hpp:455
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:46
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:51
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:64
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:48
NiHu::line_quad_store
store-wrapper of a statically stored line quadrature
Definition: line_quad_store.hpp:11
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::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::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:72
NiHu::kernel_base< kernel_t >
NiHu::kernel_traits
traits class of a kernel
Definition: kernel.hpp:71
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:67
NiHu::nearly_singular_planar_constant_collocation_shortcut
Definition: nearly_singular_planar_constant_collocation_shortcut.hpp:8
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:59
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:54
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:62
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:44
NiHu::semi_block_product_result_type
metafunction returning the value type of a semi block product
Definition: block_product.hpp:180
NiHu::field_base
CRTP base class of all fields.
Definition: field.hpp:111
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:39
NiHu::volume_element::domain_t
typename base_t::domain_t domain_t
the domain type
Definition: element.hpp:637
location_normal.hpp
implementation of location and normal kernel inputs
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:56
NiHu::nearly_singular_collocational< 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, test_input_t const &tsi)
Definition: nearly_singular_collocational.hpp:87
NiHu::nearly_singular_collocational< 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: nearly_singular_collocational.hpp:41
NiHu::inverse_mapping
mapping from physical to intrinsic coordinates
Definition: inverse_mapping.hpp:23
weighted_input.hpp
implementation of metafunction NiHu::weighted_input
NiHu::weighted_input
the weigthed input is an extended input that contains the jacobian a well
Definition: weighted_input.hpp:19