26 #ifndef NIHU_SINGULAR_GALERKIN_QUADRATURE_HPP_INCLUDED
27 #define NIHU_SINGULAR_GALERKIN_QUADRATURE_HPP_INCLUDED
31 #include "../library/lib_shape.hpp"
49 template <
class quadrature_family_t,
class test_domain_t,
class trial_domain_t>
57 template <
class test_domain_t,
class trial_domain_t>
61 typedef typename test_domain_t::scalar_t
scalar_t;
73 template <
class match_type>
84 static bool const is_symmetric =
true;
86 static unsigned const num_domains = 1;
103 throw std::logic_error(
"invalid domain index for singular Galerkin quadrature on lines with 0d match ");
113 template <
class quadrature_family_t>
130 template <
class match_type>
134 unsigned singular_quadrature_order)
139 typedef typename hlp_t::scalar_t scalar_t;
141 typedef typename hlp_t::descartes_quad_t descartes_quad_t;
146 Eigen::Matrix<scalar_t, 2, 1> c(0.0, 1.0);
147 base_quad.template transform_inplace<line_1_shape_set>(c);
150 for (
unsigned i1 = 0; i1 < base_quad.size(); ++i1)
152 scalar_t x1 = base_quad[i1].get_xi()(0);
153 scalar_t w1 = base_quad[i1].get_w();
154 for (
unsigned i2 = 0; i2 < base_quad.size(); ++i2)
156 scalar_t x2 = base_quad[i2].get_xi()(0);
157 scalar_t w2 = base_quad[i2].get_w();
159 for (
unsigned idx = 0; idx < hlp_t::num_domains; ++idx)
162 descartes_quad_t x(x1, x2);
163 scalar_t w = w1 * w2;
166 hlp_t::transform_inplace(x, w, idx);
169 x = (2. * x).array() - 1.0;
177 if (hlp_t::is_symmetric)
195 template <
class match_type>
206 static bool const is_symmetric =
true;
208 static unsigned const num_domains = 3;
224 xi1 = (1-mu1) * x(2);
230 mu2 = x(0) * (x(1) - 1.0);
231 xi1 = (1-mu1+mu2) * x(2) - mu2;
232 xi2 = (xi1+mu2) * x(3) - mu2;
233 J = (1.0-mu1+mu2) * (xi1+mu2);
238 xi1 = (1-mu2) * x(2) + mu2 - mu1;
239 xi2 = (xi1-mu2+mu1) * x(3);
240 J = (1-mu2) * (xi1-mu2+mu1);
261 static bool const is_symmetric =
false;
263 static unsigned const num_domains = 6;
278 mu2 = -x(0) * x(1) * x(2);
279 xi1 = (1.0-x(0)) * x(3) + x(0);
280 xi2 = x(0) * (1.0-x(1) + x(1)*x(2));
284 mu2 = x(0) * x(1) * x(2);
285 xi1 = (1.0-x(0)) * x(3) + x(0) * (1.0-x(1));
286 xi2 = x(0) * (1.0-x(1));
289 mu1 = -x(0) * x(1) * x(2);
290 mu2 = x(0) * x(1) * (1.0 - x(2));
291 xi1 = (1.0-x(0)) * x(3) + x(0);
292 xi2 = x(0) * (1.0-x(1));
295 mu1 = x(0) * x(1) * x(2);
296 mu2 = x(0) * x(1) * (x(2) - 1.0);
297 xi1 = (1.0-x(0)) * x(3) + x(0) * (1.0 - x(1)*x(2));
298 xi2 = x(0) * (1.0 - x(1)*x(2));
301 mu1 = -x(0) * x(1) * x(2);
303 xi1 = (1.0-x(0)) * x(3) + x(0);
307 mu1 = x(0) * x(1) * x(2);
309 xi1 = (1.0-x(0)) * x(3) + x(0) * (1.0-x(1)*x(2));
310 xi2 = x(0) * (1.0-x(1));
313 throw std::runtime_error(
"Invalid idx argument in tria_helper::transform_inplace");
315 double J = x(1) * x(0)*x(0) * (1.0-x(0));
333 static bool const is_symmetric =
true;
335 static unsigned const num_domains = 1;
365 template <
class quadrature_family_t>
384 template <
class match_type>
388 unsigned singular_quadrature_order)
393 typedef typename hlp_t::scalar_t scalar_t;
395 typedef typename hlp_t::descartes_quad_t descartes_quad_t;
400 Eigen::Matrix<scalar_t, 2, 1> c(0.0, 1.0);
401 base_quad.template transform_inplace<line_1_shape_set>(c);
404 for (
unsigned i1 = 0; i1 < base_quad.size(); ++i1)
406 scalar_t x1 = base_quad[i1].get_xi()(0);
407 scalar_t w1 = base_quad[i1].get_w();
408 for (
unsigned i2 = 0; i2 < base_quad.size(); ++i2)
410 scalar_t x2 = base_quad[i2].get_xi()(0);
411 scalar_t w2 = base_quad[i2].get_w();
412 for (
unsigned i3 = 0; i3 < base_quad.size(); ++i3)
414 scalar_t x3 = base_quad[i3].get_xi()(0);
415 scalar_t w3 = base_quad[i3].get_w();
416 for (
unsigned i4 = 0; i4 < base_quad.size(); ++i4)
418 scalar_t x4 = base_quad[i4].get_xi()(0);
419 scalar_t w4 = base_quad[i4].get_w();
421 for (
unsigned idx = 0; idx < hlp_t::num_domains; ++idx)
424 descartes_quad_t x(x1, x2, x3, x4);
425 scalar_t w = w1 * w2 * w3 * w4;
428 hlp_t::transform_inplace(x, w, idx);
439 if (hlp_t::is_symmetric)
456 template <
class match_type>
464 static const unsigned num_domains = 4;
466 static const bool is_symmetric =
true;
485 static const unsigned num_domains = 6;
487 static const bool is_symmetric =
false;
497 return xi_t(eta(0), -2.0-eta(1));
506 static const unsigned num_domains = 5;
508 static const bool is_symmetric =
false;
518 return -2.0 * xi_t::Ones() - eta;
527 template <
class quadrature_family_t>
536 typedef typename quadrature_elem_t::xi_t
xi_t;
545 template <
class match_type>
549 unsigned singular_quadrature_order)
553 typedef typename hlp_t::scalar_t scalar_t;
558 for (
unsigned d = 0; d < hlp_t::num_domains; ++d)
561 Eigen::Matrix<scalar_t, 4, 2> corners;
564 for (
unsigned c = 0; c < 4; ++c)
565 for (
unsigned j = 0; j < 2; ++j)
566 corners(c,j) = hlp_t::corners[d][c][j];
569 quadrature_t outer_quad = base_quad.template transform<quad_1_shape_set>(corners);
571 for (
unsigned out_idx = 0; out_idx < outer_quad.size(); ++out_idx)
579 for (
unsigned j = 0; j < 2; ++j)
580 if (eta_lims[0](j) > eta_lims[1](j))
581 std::swap(eta_lims[0](j), eta_lims[1](j));
584 xi_t mu = outer_quad[out_idx].get_xi();
585 scalar_t out_w = outer_quad[out_idx].get_w();
587 -mu(0)+eta_lims[0](0), -mu(1)+eta_lims[0](1),
588 -mu(0)+eta_lims[1](0), -mu(1)+eta_lims[0](1),
589 -mu(0)+eta_lims[1](0), -mu(1)+eta_lims[1](1),
590 -mu(0)+eta_lims[0](0), -mu(1)+eta_lims[1](1);
594 for (
int i = 0; i < corners.rows(); ++i)
595 for (
unsigned j = 0; j < 2; ++j)
596 corners(i,j) = std::max(std::min(corners(i,j), ximax(j)), ximin(j));
598 quadrature_t inner_quad = base_quad.template transform<quad_1_shape_set>(corners);
600 for (
unsigned in_idx = 0; in_idx < inner_quad.size(); ++in_idx)
602 xi_t xi = inner_quad[in_idx].get_xi();
603 xi_t eta = hlp_t::transform_eta(mu + xi);
605 scalar_t w = out_w * inner_quad[in_idx].get_w();
610 if (hlp_t::is_symmetric)
627 template <
class quadrature_family_t>
638 typedef typename quadrature_elem_t::xi_t
xi_t;
649 template <
class match_type>
653 unsigned singular_quadrature_order)
656 generate(match_type(), test_quadrature, trial_quadrature, singular_quadrature_order);
667 static void generate(
669 test_quadrature_t &test_quadrature,
670 trial_quadrature_t &trial_quadrature,
671 unsigned singular_quadrature_order)
673 trial_quadrature_t test_base;
674 trial_quadrature_t trial_base;
675 base_sing_t::template generate<match::match_0d_type>(
676 test_base, trial_base, singular_quadrature_order);
678 unsigned corner_idx[2][3] = {
683 for (
unsigned d = 0; d < 2; ++d)
685 Eigen::Matrix<tria_domain::scalar_t, 3, 2> corners;
686 for (
unsigned i = 0; i < 3; ++i)
688 trial_quadrature_t test_trans = test_base.template transform<tria_1_shape_set>(corners);
690 for (
unsigned i = 0; i < test_trans.size(); ++i)
692 test_quadrature.push_back(test_trans[i]);
693 trial_quadrature.push_back(trial_base[i]);
704 static void generate(
706 test_quadrature_t &test_quadrature,
707 trial_quadrature_t &trial_quadrature,
708 unsigned singular_quadrature_order)
711 unsigned corner_idx[2][3] = {
717 Eigen::Matrix<tria_domain::scalar_t, 3, 2> corners;
720 trial_quadrature_t test_base;
721 trial_quadrature_t trial_base;
722 base_sing_t::template generate<match::match_1d_type>(
723 test_base, trial_base, singular_quadrature_order);
726 for (
unsigned i = 0; i < 3; ++i)
728 test_base.template transform_inplace<tria_1_shape_set>(corners);
729 for (
unsigned i = 0; i < test_base.size(); ++i)
731 test_quadrature.push_back(test_base[i]);
732 trial_quadrature.push_back(trial_base[i]);
740 base_sing_t::template generate<match::match_0d_type>(
741 test_base, trial_base, singular_quadrature_order);
744 for (
unsigned i = 0; i < 3; ++i)
746 test_base.template transform_inplace<tria_1_shape_set>(corners);
747 for (
unsigned i = 0; i < test_base.size(); ++i)
749 test_quadrature.push_back(test_base[i]);
750 trial_quadrature.push_back(trial_base[i]);
761 template <
class quadrature_family_t>
777 template <
class match_type>
781 unsigned singular_quadrature_order)
785 template generate<match_type>(trial_quadrature, test_quadrature, singular_quadrature_order);
791 #endif // NIHU_SINGULAR_GALERKIN_QUADRATURE_HPP_INCLUDED