23 #ifndef LAPLACE_2D_SINGULAR_COLLOCATION_INTEGRALS_HPP_INCLUDED
24 #define LAPLACE_2D_SINGULAR_COLLOCATION_INTEGRALS_HPP_INCLUDED
26 #include "../core/match_types.hpp"
27 #include "../core/singular_integral_shortcut.hpp"
28 #include "../util/math_functions.hpp"
29 #include "integral_shortcut_concepts.hpp"
32 #include "normal_derivative_singular_integrals.hpp"
33 #include "quadrature_store_helper.hpp"
35 #include <boost/math/constants/constants.hpp>
37 #define NIHU_PRINT_DEBUG
39 #ifdef NIHU_PRINT_DEBUG
55 template <
class TestField,
class TrialField,
size_t order>
58 typedef TestField test_field_t;
59 typedef TrialField trial_field_t;
61 typedef typename test_field_t::nset_t test_shape_t;
62 typedef typename trial_field_t::nset_t trial_shape_t;
64 static size_t const nTest = test_shape_t::num_nodes;
65 static size_t const nTrial = trial_shape_t::num_nodes;
67 typedef Eigen::Matrix<double, nTest, nTrial> result_t;
68 typedef Eigen::Matrix<double, 1, nTrial> result_row_t;
70 typedef typename trial_field_t::elem_t elem_t;
73 typedef typename domain_t::xi_t xi_t;
77 static size_t const inner_order =
78 trial_field_t::nset_t::polynomial_order +
79 elem_t::lset_t::jacobian_order * 2;
89 static result_row_t
eval_row(xi_t
const &xi0, elem_t
const &elem)
91 using boost::math::double_constants::two_pi;
93 result_row_t result_row;
97 x_t x = elem.get_x(xi0);
102 for (
int dom = 0; dom < 2; ++dom) {
103 xi_t xi_lim = domain_t::get_corner(dom);
104 double jac = std::abs(xi_lim(0) - xi0(0));
113 double v = (q.get_xi()(0) + 1.) / 2.;
114 double wv = q.get_w() / 2;
116 xi_t eta = xi0 + v * (xi_lim - xi0);
117 double r = (elem.get_x(eta) - x).norm();
118 double Jeta = elem.get_dx(eta).norm();
121 double Greg = -std::log(r / v) / two_pi;
124 result_row += Greg * Jeta * jac * wv
125 * trial_shape_t::template eval_shape<0>(eta);
130 double v = q.get_xi()(0);
131 double wv = q.get_w();
133 xi_t eta = xi0 + v * (xi_lim - xi0);
134 double Jeta = elem.get_dx(eta).norm();
137 double Glog = 1.0 / two_pi;
140 result_row += Glog * Jeta * jac * wv
141 * trial_shape_t::template eval_shape<0>(eta);
150 static result_t
eval(elem_t
const &elem)
152 #ifdef NIHU_PRINT_DEBUG
153 static bool printed =
false;
155 std::cout <<
"Using laplace_2d_SLP_collocation_curved, inner order: " << inner_order << std::endl;
163 for (
size_t i = 0; i < nTest; ++i) {
164 xi_t
const &xi0 = test_shape_t::corner_at(i);
165 result.row(i) =
eval_row(xi0, elem);
179 template <
class TestField,
class TrialField>
182 typedef TestField test_field_t;
183 typedef TrialField trial_field_t;
185 typedef typename test_field_t::nset_t test_shape_set_t;
186 typedef typename trial_field_t::nset_t trial_shape_set_t;
190 typedef typename test_shape_set_t::xi_t xi_t;
192 static size_t const rows = test_shape_set_t::num_nodes;
193 static size_t const cols = trial_shape_set_t::num_nodes;
195 typedef Eigen::Matrix<double, rows, cols> result_t;
196 typedef Eigen::Matrix<double, 1, cols> result_row_t;
206 using boost::math::double_constants::two_pi;
211 result_row_t result_row;
212 result_row.setZero();
214 for (
size_t s = 0; s < 2; s++)
216 double sign = (s == 0 ? 1. : -1.);
217 double rho = 1. + sign * xi0(0);
221 double d = jac * rho;
222 double logd = std::log(d);
224 auto N0 = trial_shape_set_t::template eval_shape<0>(xi0);
225 result_row += N0 * d * (1. - logd);
227 if (trial_shape_set_t::polynomial_order >= 1) {
228 auto N1 = (trial_shape_set_t::template eval_shape<1>(xi0) / jac).
eval();
229 result_row += -sign * N1 * d * d * (1. / 2. - logd) / 2.;
232 if (trial_shape_set_t::polynomial_order >= 2) {
233 auto N2 = (trial_shape_set_t::template eval_shape<2>(xi0) / jac / jac / 2.).eval();
234 result_row += N2 * d * d * d * (1. / 3. - logd) / 3.;
238 return result_row / two_pi;
247 #ifdef NIHU_PRINT_DEBUG
248 static bool printed =
false;
250 std::cout <<
"Using laplace_2d_SLP_collocation_straight" << std::endl;
257 for (
size_t i = 0; i < rows; ++i) {
258 xi_t
const &xi0 = test_shape_set_t::corner_at(i);
259 result.row(i) =
eval_row(xi0, elem);
272 template <
class TestField,
class TrialField,
size_t order>
275 typedef TestField test_field_t;
276 typedef TrialField trial_field_t;
278 typedef typename test_field_t::nset_t test_shape_t;
279 typedef typename trial_field_t::nset_t trial_shape_t;
281 static size_t const nTest = test_shape_t::num_nodes;
282 static size_t const nTrial = trial_shape_t::num_nodes;
284 typedef Eigen::Matrix<double, nTest, nTrial> result_t;
286 typedef typename trial_field_t::elem_t elem_t;
289 typedef typename domain_t::xi_t xi_t;
300 static result_t
eval(elem_t
const &elem)
302 #ifdef NIHU_PRINT_DEBUG
303 static bool printed =
false;
305 std::cout <<
"Using laplace_2d_DLP_collocation_curved" << std::endl;
312 result_t result = result_t::Zero();
315 for (
size_t i = 0; i < nTest; ++i) {
316 xi_t
const &xi0 = test_shape_t::corner_at(i);
319 x_t x = elem.get_x(xi0);
322 for (
int dom = 0; dom < 2; ++dom) {
323 double low = xi0(0), high = domain_t::get_corner(dom)(0);
325 center << (low + high) / 2.;
330 xi_t xi = q.get_xi() * ((high - low) / 2.) + center;
331 double w = q.get_w() * (std::abs(high - low) / 2.);
334 x_t y = elem.get_x(xi);
335 x_t Jy = elem.get_normal(xi);
338 double G = kernel(x, y, Jy);
340 auto Ny = trial_shape_t::template eval_shape<0>(xi);
342 result.row(i) += G * Ny * w;
358 template <
class TestField,
class TrialField,
size_t order>
361 typedef TestField test_field_t;
362 typedef TrialField trial_field_t;
364 typedef typename test_field_t::nset_t test_shape_t;
365 typedef typename trial_field_t::nset_t trial_shape_t;
367 static size_t const nTest = test_shape_t::num_nodes;
368 static size_t const nTrial = trial_shape_t::num_nodes;
370 typedef Eigen::Matrix<double, nTest, nTrial> result_t;
372 typedef typename trial_field_t::elem_t elem_t;
375 typedef typename domain_t::xi_t xi_t;
386 static result_t
eval(elem_t
const &elem)
388 #ifdef NIHU_PRINT_DEBUG
389 static bool printed =
false;
391 std::cout <<
"Using laplace_2d_DLPt_collocation_curved" << std::endl;
398 result_t result = result_t::Zero();
401 for (
size_t i = 0; i < nTest; ++i) {
402 xi_t
const &xi0 = test_shape_t::corner_at(i);
405 x_t x = elem.get_x(xi0);
406 x_t nx = elem.get_normal(xi0).normalized();
409 for (
int dom = 0; dom < 2; ++dom) {
410 double low = xi0(0), high = domain_t::get_corner(dom)(0);
412 center << (low + high) / 2.;
417 xi_t xi = q.get_xi() * ((high - low) / 2.) + center;
418 double w = q.get_w() * (std::abs(high - low) / 2.);
421 x_t y = elem.get_x(xi);
422 double Jy = elem.get_dx(xi).norm();
425 double G = kernel(x, y, nx);
427 auto Ny = trial_shape_t::template eval_shape<0>(xi);
429 result.row(i) += G * Jy * Ny * w;
444 template <
class TestField,
class TrialField,
size_t order>
447 typedef TestField test_field_t;
448 typedef TrialField trial_field_t;
450 typedef typename test_field_t::nset_t test_shape_t;
451 typedef typename trial_field_t::nset_t trial_shape_t;
453 static size_t const nTest = test_shape_t::num_nodes;
454 static size_t const nTrial = trial_shape_t::num_nodes;
456 typedef Eigen::Matrix<double, nTest, nTrial> result_t;
458 typedef typename trial_field_t::elem_t elem_t;
461 typedef typename domain_t::xi_t xi_t;
472 static result_t
eval(elem_t
const &elem)
474 #ifdef NIHU_PRINT_DEBUG
475 static bool printed =
false;
477 std::cout <<
"Using laplace_2d_HSP_collocation_curved" << std::endl;
482 using namespace boost::math::double_constants;
486 result_t result = result_t::Zero();
488 xi_t
const &a = domain_t::get_corner(0);
489 xi_t
const &b = domain_t::get_corner(1);
492 for (
size_t i = 0; i < nTest; ++i) {
493 xi_t
const &xi0 = test_shape_t::corner_at(i);
496 auto N0 = trial_shape_t::template eval_shape<0>(xi0);
497 auto N1 = trial_shape_t::template eval_shape<1>(xi0);
500 x_t x = elem.get_x(xi0);
501 x_t Jxvec = elem.get_normal(xi0);
502 x_t nx = Jxvec.normalized();
503 double jac0 = Jxvec.norm();
504 double twopiJ0 = two_pi * jac0;
506 for (
int dom = 0; dom < 2; ++dom) {
507 double high = domain_t::get_corner(dom)(0);
510 center << (low + high) / 2.;
515 xi_t xi = q.get_xi() * ((high - low) / 2.) + center;
516 double w = q.get_w() * (std::abs(high - low) / 2.);
517 double rho = xi(0) - xi0(0);
520 x_t y = elem.get_x(xi);
521 x_t Jyvec = elem.get_normal(xi);
522 x_t ny = Jyvec.normalized();
523 double jac = Jyvec.norm();
526 double G = kernel(x, y, nx, ny);
528 auto N = trial_shape_t::template eval_shape<0>(xi);
529 auto F = G * N * jac;
531 auto F0 = (N0 / rho + N1) / rho / twopiJ0;
534 result.row(i) += (F - F0) * w;
539 result.row(i) += ((1. / (a(0) - xi0(0)) - 1. / (b(0) - xi0(0))) * N0 +
540 std::log(std::abs((b(0) - xi0(0)) / (a(0) - xi0(0)))) * N1) / twopiJ0;
551 template <
class TestField,
class TrialField>
554 typedef TestField test_field_t;
555 typedef TrialField trial_field_t;
557 typedef typename test_field_t::nset_t test_shape_set_t;
558 typedef typename trial_field_t::nset_t trial_shape_set_t;
560 typedef typename test_field_t::elem_t elem_t;
562 typedef typename test_shape_set_t::xi_t xi_t;
564 static size_t const nTest = test_shape_set_t::num_nodes;
565 static size_t const nTrial = trial_shape_set_t::num_nodes;
567 typedef Eigen::Matrix<double, nTest, nTrial> result_t;
573 static result_t
eval(elem_t
const &elem)
575 using namespace boost::math::double_constants;
577 #ifdef NIHU_PRINT_DEBUG
578 static bool printed =
false;
580 std::cout <<
"Using laplace_2d_HSP_collocation_straight" << std::endl;
585 double jac = elem.get_normal().norm();
587 result_t result = result_t::Zero();
590 double const a = -1.;
591 double const b = +1.;
593 for (
size_t i = 0; i < nTest; ++i) {
594 xi_t xi0 = test_shape_set_t::corner_at(i);
595 auto N = trial_shape_set_t::template eval_shape<0>(xi0);
596 result.row(i) = N * (-1. / (b - xi0(0)) - -1. / (a - xi0(0)));
598 if (trial_shape_set_t::polynomial_order >= 1) {
599 auto dN = trial_shape_set_t::template eval_shape<1>(xi0);
600 result.row(i) += dN * std::log(std::abs((b - xi0(0)) / (a - xi0(0))));
603 if (trial_shape_set_t::polynomial_order >= 2) {
604 auto ddN = trial_shape_set_t::template eval_shape<2>(xi0);
605 result.row(i) += ddN / 2. * (b - a);
609 return result / (two_pi * jac);
616 template <
class TestField,
class TrialField>
618 typename std::enable_if<
619 is_collocational<TestField, TrialField>::value &&
620 is_straight_line<TrialField>::value
630 template <
class result_t>
639 TestField, TrialField
649 template <
class TestField,
class TrialField>
651 typename std::enable_if<
652 is_collocational<TestField, TrialField>::value &&
653 is_straight_line<TrialField>::value
657 typedef typename TrialField::elem_t trial_elem_t;
658 typedef typename trial_elem_t::domain_t domain_t;
659 typedef typename domain_t::xi_t xi_t;
660 static unsigned const order = 8;
662 typedef typename TestField::nset_t test_nset_t;
663 typedef typename TrialField::nset_t trial_nset_t;
664 static size_t const nTest = test_nset_t::num_nodes;
674 template <
class result_t>
683 auto test_singular_xi = TestField::elem_t::lset_t::corner_at(test_idx);
686 auto trial_singular_xi = TrialField::elem_t::lset_t::corner_at(trial_idx);
688 auto const &test_elem = test_field.
get_elem();
689 auto const &trial_elem = trial_field.
get_elem();
691 for (
size_t i = 0; i < nTest; ++i)
693 auto xi0 = TestField::nset_t::corner_at(i);
694 if (xi0 == test_singular_xi)
701 result.row(i).setZero();
702 for (
auto const &q : reg_quadrature_t::quadrature) {
703 xi_t xi = q.get_xi();
704 double w = q.get_w();
705 double jac = trial_elem.get_normal(xi).norm();
706 double K = kernel(test_elem.get_x(xi0), trial_elem.get_x(xi));
707 result.row(i) += (w * jac *
K) * trial_nset_t::template eval_shape<0>(xi);
721 template <
class TestField,
class TrialField>
723 typename std::enable_if<
724 is_collocational<TestField, TrialField>::value &&
725 is_straight_line<TrialField>::value
729 typedef typename TrialField::elem_t trial_elem_t;
730 typedef typename trial_elem_t::x_t x_t;
731 typedef typename trial_elem_t::domain_t domain_t;
732 typedef typename domain_t::xi_t xi_t;
733 static unsigned const order = 8;
735 typedef typename TestField::nset_t test_nset_t;
736 typedef typename TrialField::nset_t trial_nset_t;
737 static size_t const nTest = test_nset_t::num_nodes;
747 template <
class result_t>
756 auto test_singular_xi = TestField::elem_t::lset_t::corner_at(test_idx);
761 auto const &test_elem = test_field.
get_elem();
762 auto const &trial_elem = trial_field.
get_elem();
764 for (
size_t i = 0; i < nTest; ++i)
766 auto xi0 = TestField::nset_t::corner_at(i);
767 if (xi0 == test_singular_xi)
770 result.row(i).setZero();
774 result.row(i).setZero();
775 for (
auto const &q : reg_quadrature_t::quadrature) {
776 xi_t xi = q.get_xi();
777 double w = q.get_w();
778 x_t normal = trial_elem.get_normal(xi);
779 x_t unit_normal = normal.normalized();
780 double jac = normal.norm();
781 double K = kernel.derived()(test_elem.get_x(xi0), trial_elem.get_x(xi), unit_normal);
782 result.row(i) += (w * jac *
K) * trial_nset_t::template eval_shape<0>(xi);
797 template <
class TestField,
class TrialField>
800 typename std::enable_if<
801 is_collocational<TestField, TrialField>::value &&
802 !is_straight_line<TrialField>::value
812 template <
class result_t>
821 TestField, TrialField, 8
831 template <
class TestField,
class TrialField>
834 typename std::enable_if<
835 is_collocational<TestField, TrialField>::value &&
836 !is_straight_line<TrialField>::value
846 template <
class result_t>
864 template <
class TestField,
class TrialField>
867 typename std::enable_if<
868 is_collocational<TestField, TrialField>::value &&
869 !is_straight_line<TrialField>::value
879 template <
class result_t>
897 template <
class TestField,
class TrialField>
900 typename std::enable_if<
901 is_collocational<TestField, TrialField>::value &&
902 !is_straight_line<TrialField>::value
912 template <
class result_t>
921 TestField, TrialField, 10
931 template <
class TestField,
class TrialField>
934 typename std::enable_if<
935 is_collocational<TestField, TrialField>::value &&
936 is_straight_line<TrialField>::value
946 template <
class result_t>