1 #ifndef NIHU_NEARLY_SINGULAR_COLLOCATIONAL_HPP_INCLUDED
2 #define NIHU_NEARLY_SINGULAR_COLLOCATIONAL_HPP_INCLUDED
4 #include <boost/math/constants/constants.hpp>
6 #include "line_quad_store.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"
19 template <
class TrialField,
class Kernel,
20 unsigned RadialOrder,
unsigned TangentialOrder,
24 template <
class TrialField,
class Kernel,
25 unsigned RadialOrder,
unsigned TangentialOrder>
27 typename std::enable_if<
28 element_traits::is_surface_element<typename TrialField::elem_t>::value
34 radial_order = RadialOrder,
35 tangential_order = TangentialOrder
41 typedef typename trial_field_t::elem_t
elem_t;
46 typedef typename domain_t::xi_t
xi_t;
81 : m_elem(trial_field.get_elem())
86 template <
class result_t>
89 using namespace boost::math::double_constants;
96 unsigned max_iter = 100;
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);
106 elem_t lin_elem = m_elem.get_linearized_elem(m_xi0);
109 auto N0 = trial_nset_t::template eval_shape<0>(m_xi0);
113 unsigned const N = domain_t::num_corners;
114 for (
unsigned n = 0; n < N; ++n)
116 xi_t c1 = domain_t::get_corner(n);
117 xi_t c2 = domain_t::get_corner((n + 1) % N);
118 xi_t l = xi_t::Zero();
120 if ((c2 - c1).norm() > 1e-3)
121 l = (c2 - c1).normalized();
123 xi_t d1 = c1 - m_xi0;
124 xi_t d0 = d1 - l * d1.dot(l);
126 m_theta_lim[n] = std::atan2(d1(1), d1(0));
127 m_theta0[n] = std::atan2(d0(1), d0(0));
128 m_ref_distance[n] = d0.norm();
132 for (
unsigned n = 0; n < N; ++n)
136 scalar_t t2 = m_theta_lim[(n + 1) % N];
139 if (std::abs(t2 - t1) > pi)
147 if (std::abs(t2 - t1) < 1e-3)
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;
159 scalar_t rho_lim = m_ref_distance[n] / std::cos(theta - m_theta0[n]);
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;
169 xi_t xi(rho*std::cos(theta), rho*std::sin(theta));
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();
183 auto N = trial_nset_t::template eval_shape<0>(xi);
187 I += w_theta * w_rho * rho * (F - F_lin);
192 typename kernel_t::result_t anal_res =
194 tsi, lin_elem, m_kernel
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];