26 #include "getfem/bgeot_permutations.h" 38 static pintegration_method
im_none(im_param_list ¶ms,
39 std::vector<dal::pstatic_stored_object> &) {
40 GMM_ASSERT1(params.size() == 0,
"IM_NONE does not accept any parameter");
41 return std::make_shared<integration_method>();
45 long_scalar_type res = 0.0;
46 if (P.size() > int_monomials.size()) {
47 std::vector<long_scalar_type> *hum = &int_monomials;
48 size_type i = P.size(), j = int_monomials.size();
52 (*hum)[k-1] = int_monomial(mi);
54 base_poly::const_iterator it = P.begin(), ite = P.end();
55 std::vector<long_scalar_type>::const_iterator itb = int_monomials.begin();
56 for ( ; it != ite; ++it, ++itb) {
57 res += long_scalar_type(*it) * long_scalar_type(*itb);
64 long_scalar_type res = 0.0;
65 std::vector<long_scalar_type> *hum = &(int_face_monomials[f]);
66 if (P.size() > hum->size()) {
71 (*hum)[k-1] = int_monomial_on_face(mi, f);
73 base_poly::const_iterator it = P.begin(), ite = P.end();
74 std::vector<long_scalar_type>::const_iterator itb = hum->begin();
75 for ( ; it != ite; ++it, ++itb)
76 res += long_scalar_type(*it) * long_scalar_type(*itb);
92 { cvs = c; int_face_monomials.resize(c->nb_faces()); }
98 long_scalar_type res = LONG_SCAL(1);
100 bgeot::power_index::const_iterator itm = power.begin(),
102 for ( ; itm != itme; ++itm)
103 for (
int k = 1; k <= *itm; ++k, ++fa)
104 res *= long_scalar_type(k) / long_scalar_type(fa);
106 for (
int k = 0; k < cvs->dim(); k++) { res /= long_scalar_type(fa); fa++; }
110 long_scalar_type simplex_poly_integration_::int_monomial_on_face
112 long_scalar_type res = LONG_SCAL(0);
114 if (f == 0 || power[f-1] == 0.0) {
115 res = (f == 0) ? sqrt(long_scalar_type(cvs->dim())) : LONG_SCAL(1);
117 bgeot::power_index::const_iterator itm = power.begin(),
119 for ( ; itm != itme; ++itm)
120 for (
int k = 1; k <= *itm; ++k, ++fa)
121 res *= long_scalar_type(k) / long_scalar_type(fa);
123 for (
int k = 1; k < cvs->dim(); k++) { res/=long_scalar_type(fa); fa++; }
128 static pintegration_method
129 exact_simplex(im_param_list ¶ms,
130 std::vector<dal::pstatic_stored_object> &dependencies) {
131 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : " 132 << params.size() <<
" should be 1.");
133 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
134 int n = int(::floor(params[0].num() + 0.01));
135 GMM_ASSERT1(n > 0 && n < 100 &&
double(n) == params[0].num(),
138 ppoly_integration ppi = std::make_shared<simplex_poly_integration_>
140 return std::make_shared<integration_method>(ppi);
148 ppoly_integration cv1, cv2;
155 plyint_mul_structure_(ppoly_integration a, ppoly_integration b);
158 long_scalar_type plyint_mul_structure_::int_monomial
161 std::copy(power.begin(), power.begin() + cv1->dim(), mi1.begin());
162 std::copy(power.begin() + cv1->dim(), power.end(), mi2.begin());
163 return cv1->int_monomial(mi1) * cv2->int_monomial(mi2);
166 long_scalar_type plyint_mul_structure_::int_monomial_on_face
169 std::copy(power.begin(), power.begin() + cv1->dim(), mi1.begin());
170 std::copy(power.begin() + cv1->dim(), power.end(), mi2.begin());
171 short_type nfx = cv1->structure()->nb_faces();
173 return cv1->int_monomial_on_face(mi1,f) * cv2->int_monomial(mi2);
175 return cv1->int_monomial(mi1)
176 * cv2->int_monomial_on_face(mi2,
short_type(f-nfx));
179 plyint_mul_structure_::plyint_mul_structure_(ppoly_integration a,
180 ppoly_integration b) {
184 int_face_monomials.resize(cvs->nb_faces());
187 static pintegration_method
188 product_exact(im_param_list ¶ms,
189 std::vector<dal::pstatic_stored_object> &dependencies) {
190 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 191 << params.size() <<
" should be 2.");
192 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
193 "Bad type of parameters");
194 pintegration_method a = params[0].method();
195 pintegration_method b = params[1].method();
196 GMM_ASSERT1(a->type() == IM_EXACT && b->type() == IM_EXACT,
198 dependencies.push_back(a); dependencies.push_back(b);
201 ppoly_integration ppi = std::make_shared<plyint_mul_structure_>
202 (a->exact_method(), b->exact_method());
203 return std::make_shared<integration_method>(ppi);
210 static pintegration_method
211 exact_parallelepiped(im_param_list ¶ms,
212 std::vector<dal::pstatic_stored_object> &) {
213 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : " 214 << params.size() <<
" should be 1.");
215 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
216 int n = int(::floor(params[0].num() + 0.01));
217 GMM_ASSERT1(n > 0 && n < 100 &&
double(n) == params[0].num(),
220 std::stringstream name;
222 name <<
"IM_EXACT_SIMPLEX(1)";
224 name <<
"IM_PRODUCT(IM_EXACT_PARALLELEPIPED(" << n-1
225 <<
"),IM_EXACT_SIMPLEX(1)))";
229 static pintegration_method
230 exact_prism(im_param_list ¶ms,
231 std::vector<dal::pstatic_stored_object> &) {
232 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : " 233 << params.size() <<
" should be 1.");
234 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
235 int n = int(::floor(params[0].num() + 0.01));
236 GMM_ASSERT1(n > 1 && n < 100 &&
double(n) == params[0].num(),
239 std::stringstream name;
240 name <<
"IM_PRODUCT(IM_EXACT_SIMPLEX(" << n-1
241 <<
"),IM_EXACT_SIMPLEX(1))";
249 void approx_integration::add_point(
const base_node &pt,
252 bool include_empty) {
253 GMM_ASSERT1(!valid,
"Impossible to modify a valid integration method.");
254 if (gmm::abs(w) > 1.0E-15 || include_empty) {
256 if (gmm::abs(w) <= 1.0E-15) w = scalar_type(0);
257 GMM_ASSERT1(f <= cvr->
structure()->nb_faces(),
"Wrong argument.");
258 size_type i = pt_to_store[f].search_node(pt);
260 i = pt_to_store[f].add_node(pt);
261 int_coeffs.resize(int_coeffs.size() + 1);
262 for (
size_type j = f; j <= cvr->structure()->nb_faces(); ++j)
264 for (
size_type j = int_coeffs.size(); j > repartition[f]; --j)
265 int_coeffs[j-1] = int_coeffs[j-2];
266 int_coeffs[repartition[f]-1] = 0.0;
268 int_coeffs[((f == 0) ? 0 : repartition[f-1]) + i] += w;
272 void approx_integration::add_point_norepeat(
const base_node &pt,
276 if (pt_to_store[f2].search_node(pt) ==
size_type(-1)) add_point(pt,w,f);
279 void approx_integration::add_point_full_symmetric(base_node pt,
281 dim_type n = cvr->structure()->dim();
284 if (n+1 == cvr->structure()->nb_faces()) {
289 std::copy(pt.begin(), pt.end(), pt3.begin());
290 pt3[n] = 1;
for (k = 0; k < n; ++k) pt3[n] -= pt[k];
291 std::vector<int> ind(n); std::fill(ind.begin(), ind.end(), 0);
292 std::vector<bool> ind2(n+1);
295 std::fill(ind2.begin(), ind2.end(),
false);
297 for (k = 0; k < n; ++k)
298 if (ind2[ind[k]]) { good =
false;
break; }
else ind2[ind[k]] =
true;
300 for (k = 0; k < n; ++k) pt2[k] = pt3[ind[k]];
301 add_point_norepeat(pt2, w);
304 while(ind[k] == n+1) { ind[k++] = 0;
if (k == n)
return; ind[k]++; }
308 else if (cvr->structure()->nb_points() == (
size_type(1) << n)) {
311 for (k = 0; k < n; ++k)
312 if (i & (
size_type(1) << k)) pt2[k]=pt[k];
else pt2[k] = 1.0-pt[k];
313 add_point_norepeat(pt2, w);
317 GMM_ASSERT1(
false,
"Fully symmetric option is only valid for" 318 "simplices and parallelepipedic elements");
321 void approx_integration::add_method_on_face(pintegration_method ppi,
323 papprox_integration pai = ppi->approx_method();
324 GMM_ASSERT1(!valid,
"Impossible to modify a valid integration method.");
325 GMM_ASSERT1(pai->structure() ==
structure()->faces_structure()[f],
326 "structures missmatch");
327 GMM_ASSERT1(ppi->type() == IM_APPROX,
"Impossible with an exact method.");
329 dim_type N = pai->structure()->dim();
330 scalar_type det = 1.0;
332 std::vector<base_node> pts(N);
334 pts[i] = (cvr->dir_points_of_face(f))[i+1]
335 - (cvr->dir_points_of_face(f))[0];
337 base_matrix a(N+1, N), b(N, N), tmp(N, N);
338 for (dim_type i = 0; i < N+1; ++i)
339 for (dim_type j = 0; j < N; ++j)
342 gmm::mult(gmm::transposed(a), a, b);
343 det = ::sqrt(gmm::abs(gmm::lu_det(b)));
345 for (
size_type i = 0; i < pai->nb_points_on_convex(); ++i) {
346 pt = (cvr->dir_points_of_face(f))[0];
347 for (dim_type j = 0; j < N; ++j)
348 pt += pts[j] * ((*(pai->pintegration_points()))[i])[j];
349 add_point(pt, pai->coeff(i) * det, f);
353 void approx_integration::valid_method() {
354 std::vector<base_node> ptab(int_coeffs.size());
357 for (
short_type f = 0; f <= cvr->structure()->nb_faces(); ++f) {
359 for (PT_TAB::const_iterator it = pt_to_store[f].begin();
360 it != pt_to_store[f].end(); ++it ) {
365 GMM_ASSERT1(i == int_coeffs.size(),
"internal error.");
366 pint_points = bgeot::store_point_tab(ptab);
367 pt_to_store = std::vector<PT_TAB>();
377 static pintegration_method
378 im_list_integration(std::string name,
379 std::vector<dal::pstatic_stored_object> &dependencies) {
381 for (
int i = 0; i < NB_IM; ++i)
382 if (!name.compare(im_desc_tab[i].method_name)) {
385 dim_type N = pgt->structure()->dim();
387 auto pai = std::make_shared<approx_integration>(pgt->convex_ref());
389 for (
size_type j = 0; j < im_desc_tab[i].nb_points; ++j) {
390 for (dim_type k = 0; k < N; ++k)
391 pt[k] = atof(im_desc_real[fr+j*(N+1)+k]);
394 switch (im_desc_node_type[im_desc_tab[i].firsttype + j]) {
396 base_node pt2(pt.size());
399 pai->add_point_full_symmetric(pt2,
400 atof(im_desc_real[fr+j*(N+1)+N]));
406 pai->add_point_full_symmetric(pt,atof(im_desc_real[fr+j*(N+1)+N]));
411 pai->add_point(pt, atof(im_desc_real[fr+j*(N+1)+N]));
414 default: GMM_ASSERT1(
false,
"");
418 for (
short_type f = 0; N > 0 && f < pgt->structure()->nb_faces(); ++f)
419 pai->add_method_on_face
421 (im_desc_face_meth[im_desc_tab[i].firstface + f]), f);
426 pintegration_method p(std::make_shared<integration_method>(pai));
427 dependencies.push_back(p->approx_method()->ref_convex());
428 dependencies.push_back(p->approx_method()->pintegration_points());
431 return pintegration_method();
439 struct Legendre_polynomials {
440 std::vector<base_poly> polynomials;
441 std::vector<std::vector<long_scalar_type>> roots;
443 Legendre_polynomials() : nb_lp(-1) {}
445 polynomials.resize(de+2);
448 polynomials[0] = base_poly(1,0);
449 polynomials[0].one();
450 polynomials[1] = base_poly(1,1,0);
458 (base_poly(1,1,0) * polynomials[nb_lp-1]
459 * ((2.0 * long_scalar_type(nb_lp) - 1.0) / long_scalar_type(nb_lp)))
460 + (polynomials[nb_lp-2]
461 * ((1.0 - long_scalar_type(nb_lp)) / long_scalar_type(nb_lp)));
462 roots[nb_lp].resize(nb_lp);
463 roots[nb_lp][nb_lp/2] = 0.0;
464 long_scalar_type a = -1.0, b, c, d, e, cv, ev, ecart, ecart2;
465 for (
int k = 0; k < nb_lp / 2; ++k) {
466 b = roots[nb_lp-1][k];
469 cv = polynomials[nb_lp].eval(&c);
471 ecart = 2.0 * (d - c);
473 --imax;
if (imax == 0)
break;
475 ecart2 = d - c;
if (ecart2 >= ecart)
break;
477 ev = polynomials[nb_lp].eval(&e);
478 if (ev * cv < 0.) { d = e; }
else { c = e; cv = ev; }
482 roots[nb_lp][nb_lp-k-1] = -c;
489 struct gauss_approx_integration_ :
public approx_integration {
493 gauss_approx_integration_::gauss_approx_integration_(
short_type nbpt) {
494 GMM_ASSERT1(nbpt <= 32000,
"too much points");
497 std::vector<base_node> int_points(nbpt+2);
498 int_coeffs.resize(nbpt+2);
499 repartition.resize(3);
500 repartition[0] = nbpt;
501 repartition[1] = nbpt + 1;
502 repartition[2] = nbpt + 2;
504 Legendre_polynomials Lp;
508 int_points[i].resize(1);
509 long_scalar_type lr = Lp.roots[nbpt][i];
510 int_points[i][0] = 0.5 + 0.5 * bgeot::to_scalar(lr);
511 int_coeffs[i] = bgeot::to_scalar((1.0 - gmm::sqr(lr))
512 / gmm::sqr( long_scalar_type(nbpt)
513 * (Lp.polynomials[nbpt-1].eval(&lr))));
516 int_points[nbpt].resize(1);
517 int_points[nbpt][0] = 1.0; int_coeffs[nbpt] = 1.0;
519 int_points[nbpt+1].resize(1);
520 int_points[nbpt+1][0] = 0.0; int_coeffs[nbpt+1] = 1.0;
521 pint_points = bgeot::store_point_tab(int_points);
526 static pintegration_method
527 gauss1d(im_param_list ¶ms,
528 std::vector<dal::pstatic_stored_object> &dependencies) {
529 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : " 530 << params.size() <<
" should be 1.");
531 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
532 int n = int(::floor(params[0].num() + 0.01));
533 GMM_ASSERT1(n >= 0 && n < 32000 &&
double(n) == params[0].num(),
536 std::stringstream name;
537 name <<
"IM_GAUSS1D(" << n-1 <<
")";
542 pai = std::make_shared<gauss_approx_integration_>(
short_type(n/2 + 1));
543 pintegration_method p = std::make_shared<integration_method>(pai);
544 dependencies.push_back(p->approx_method()->ref_convex());
545 dependencies.push_back(p->approx_method()->pintegration_points());
554 struct Newton_Cotes_approx_integration_ :
public approx_integration
557 Newton_Cotes_approx_integration_(dim_type nc,
short_type k);
560 Newton_Cotes_approx_integration_::Newton_Cotes_approx_integration_
567 add_point(c, scalar_type(1));
571 std::stringstream name;
572 name <<
"IM_EXACT_SIMPLEX(" << int(nc) <<
")";
576 c.fill(scalar_type(0.0));
577 if (k == 0) c.fill(1.0 / scalar_type(nc+1));
579 gmm::dense_matrix<long_scalar_type> M(R, R);
580 std::vector<long_scalar_type> F(R), U(R);
581 std::vector<bgeot::power_index> base(R);
582 std::vector<base_node> nodes(R);
586 for (
size_type r = 0; r < R; ++r, ++pi) {
587 base[r] = pi; nodes[r] = c;
588 if (k != 0 && nc > 0) {
589 l = 0; c[l] += 1.0 / scalar_type(k); sum++;
591 sum -= int(floor(0.5+(c[l] * k)));
592 c[l] = 0.0; l++;
if (l == nc)
break;
593 c[l] += 1.0 / scalar_type(k); sum++;
612 F[r] = ppi->int_monomial(base[r]);
626 M(r, q) = bgeot::eval_monomial(base[r], nodes[q].begin());
630 gmm::lu_solve(M, U, F);
632 add_point(nodes[r], bgeot::to_scalar(U[r]));
634 std::stringstream name2;
635 name2 <<
"IM_NC(" << int(nc-1) <<
"," << int(k) <<
")";
642 static pintegration_method
643 Newton_Cotes(im_param_list ¶ms,
644 std::vector<dal::pstatic_stored_object> &dependencies) {
645 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 646 << params.size() <<
" should be 2.");
647 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
648 "Bad type of parameters");
649 int n = int(::floor(params[0].num() + 0.01));
650 int k = int(::floor(params[1].num() + 0.01));
651 GMM_ASSERT1(n >= 0 && n < 100 && k >= 0 && k <= 150 &&
652 double(n) == params[0].num() &&
double(k) == params[1].num(),
655 pai = std::make_shared<Newton_Cotes_approx_integration_>(dim_type(n),
657 pintegration_method p = std::make_shared<integration_method>(pai);
658 dependencies.push_back(p->approx_method()->ref_convex());
659 dependencies.push_back(p->approx_method()->pintegration_points());
667 struct a_int_pro_integration :
public approx_integration
669 a_int_pro_integration(papprox_integration a, papprox_integration b);
673 a_int_pro_integration::a_int_pro_integration(papprox_integration a,
674 papprox_integration b) {
678 std::vector<base_node> int_points;
679 int_points.resize(n1 * n2);
680 int_coeffs.resize(n1 * n2);
681 repartition.resize(cvr->structure()->nb_faces()+1);
682 repartition[0] = n1 * n2;
685 int_coeffs[i1 + i2 * n1] = a->coeff(i1) * b->coeff(i2);
686 int_points[i1 + i2 * n1].resize(
dim());
687 std::copy(a->point(i1).begin(), a->point(i1).end(),
688 int_points[i1 + i2 * n1].begin());
689 std::copy(b->point(i2).begin(), b->point(i2).end(),
690 int_points[i1 + i2 * n1].begin() + a->dim());
693 for (
short_type f1 = 0; f1 < a->structure()->nb_faces(); ++f1, ++f) {
694 n1 = a->nb_points_on_face(f1);
695 n2 = b->nb_points_on_convex();
697 repartition[f+1] = w + n1 * n2;
698 int_points.resize(repartition[f+1]);
699 int_coeffs.resize(repartition[f+1]);
702 int_coeffs[w + i1 + i2 * n1] = a->coeff_on_face(f1, i1)
704 int_points[w + i1 + i2 * n1].resize(
dim());
705 std::copy(a->point_on_face(f1, i1).begin(),
706 a->point_on_face(f1, i1).end(),
707 int_points[w + i1 + i2 * n1].begin());
708 std::copy(b->point(i2).begin(), b->point(i2).end(),
709 int_points[w + i1 + i2 * n1].begin() + a->dim());
712 for (
short_type f2 = 0; f2 < b->structure()->nb_faces(); ++f2, ++f) {
713 n1 = a->nb_points_on_convex();
714 n2 = b->nb_points_on_face(f2);
716 repartition[f+1] = w + n1 * n2;
717 int_points.resize(repartition[f+1]);
718 int_coeffs.resize(repartition[f+1]);
721 int_coeffs[w + i1 + i2 * n1] = a->coeff(i1)
722 * b->coeff_on_face(f2, i2);
723 int_points[w + i1 + i2 * n1].resize(
dim());
724 std::copy(a->point(i1).begin(), a->point(i1).end(),
725 int_points[w + i1 + i2 * n1].begin());
726 std::copy(b->point_on_face(f2, i2).begin(),
727 b->point_on_face(f2, i2).end(),
728 int_points[w + i1 + i2 * n1].begin() + a->dim());
731 pint_points = bgeot::store_point_tab(int_points);
735 static pintegration_method
736 product_approx(im_param_list ¶ms,
737 std::vector<dal::pstatic_stored_object> &dependencies) {
738 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 739 << params.size() <<
" should be 2.");
740 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
741 "Bad type of parameters");
742 pintegration_method a = params[0].method();
743 pintegration_method b = params[1].method();
744 GMM_ASSERT1(a->type() == IM_APPROX && b->type() == IM_APPROX,
747 pai = std::make_shared<a_int_pro_integration>(a->approx_method(),
749 pintegration_method p = std::make_shared<integration_method>(pai);
750 dependencies.push_back(p->approx_method()->ref_convex());
751 dependencies.push_back(p->approx_method()->pintegration_points());
755 static pintegration_method
756 product_which(im_param_list ¶ms,
757 std::vector<dal::pstatic_stored_object> &dependencies) {
758 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 759 << params.size() <<
" should be 2.");
760 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
761 "Bad type of parameters");
762 pintegration_method a = params[0].method();
763 pintegration_method b = params[1].method();
764 if (a->type() == IM_EXACT || b->type() == IM_EXACT)
765 return product_exact(params, dependencies);
766 else return product_approx(params, dependencies);
774 static pintegration_method
775 Newton_Cotes_para(im_param_list ¶ms,
776 std::vector<dal::pstatic_stored_object> &) {
777 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 778 << params.size() <<
" should be 2.");
779 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
780 "Bad type of parameters");
781 int n = int(::floor(params[0].num() + 0.01));
782 int k = int(::floor(params[1].num() + 0.01));
783 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
784 double(n) == params[0].num() &&
double(k) == params[1].num(),
787 std::stringstream name;
789 name <<
"IM_NC(1," << k <<
")";
791 name <<
"IM_PRODUCT(IM_NC_PARALLELEPIPED(" << n-1 <<
"," << k
792 <<
"),IM_NC(1," << k <<
"))";
796 static pintegration_method
797 Newton_Cotes_prism(im_param_list ¶ms,
798 std::vector<dal::pstatic_stored_object> &) {
799 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 800 << params.size() <<
" should be 2.");
801 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
802 "Bad type of parameters");
803 int n = int(::floor(params[0].num() + 0.01));
804 int k = int(::floor(params[1].num() + 0.01));
805 GMM_ASSERT1(n > 1 && n < 100 && k >= 0 && k <= 150 &&
806 double(n) == params[0].num() &&
double(k) == params[1].num(),
809 std::stringstream name;
810 name <<
"IM_PRODUCT(IM_NC(" << n-1 <<
"," << k <<
"),IM_NC(1," 819 static pintegration_method
820 Gauss_paramul(im_param_list ¶ms,
821 std::vector<dal::pstatic_stored_object> &) {
822 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 823 << params.size() <<
" should be 2.");
824 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
825 "Bad type of parameters");
826 int n = int(::floor(params[0].num() + 0.01));
827 int k = int(::floor(params[1].num() + 0.01));
828 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
829 double(n) == params[0].num() &&
double(k) == params[1].num(),
832 std::stringstream name;
834 name <<
"IM_GAUSS1D(" << k <<
")";
836 name <<
"IM_PRODUCT(IM_GAUSS_PARALLELEPIPED(" << n-1 <<
"," << k
837 <<
"),IM_GAUSS1D(" << k <<
"))";
845 struct quasi_polar_integration :
public approx_integration {
846 quasi_polar_integration(papprox_integration base_im,
854 enum { SQUARE, PRISM, TETRA_CYL, PRISM2, PYRAMID } what;
855 if (N == 2) what = SQUARE;
857 what = (ip2 ==
size_type(-1) || ip1 == ip2) ? PRISM2 : PRISM;
862 else GMM_ASSERT1(
false,
"Incoherent integration method");
869 std::vector<base_node> nodes1 = pgt1->convex_ref()->points();
871 std::vector<base_node> nodes2(N+1);
872 if (what == PYRAMID) {
873 pgt2 = bgeot::pyramid_QK_geotrans(1);
876 std::vector<size_type> other_nodes;
878 std::vector<base_node> nodes3(N+1);
882 nodes1[3] = nodes1[1];
883 nodes2[ip1] = nodes1[1]; ip2 = ip1;
884 other_nodes.push_back(0);
885 other_nodes.push_back(2);
888 nodes1[4] = nodes1[0]; nodes1[5] = nodes1[1];
889 nodes2[ip1] = nodes1[0];
890 nodes2[ip2] = nodes1[1];
891 other_nodes.push_back(2);
892 other_nodes.push_back(6);
895 nodes3[0] = nodes1[0]; nodes3[1] = nodes1[1];
896 nodes3[2] = nodes1[2]; nodes3[3] = nodes1[4];
898 nodes2[ip1] = nodes1[1]; ip2 = ip1;
899 other_nodes.push_back(0);
900 other_nodes.push_back(2);
901 other_nodes.push_back(4);
904 nodes2[ip1] = nodes1[4];
905 other_nodes.push_back(0);
906 other_nodes.push_back(1);
907 other_nodes.push_back(2);
911 nodes1[0] = base_node(-1.,-1., 0.);
912 nodes1[1] = base_node( 1.,-1., 0.);
913 nodes1[2] = base_node(-1., 1., 0.);
914 nodes1[3] = base_node( 1., 1., 0.);
915 nodes1[4] = base_node( 0., 0., 1.);
916 nodes1[5] = nodes1[6] = nodes1[7] = nodes1[4];
917 nodes2[ip1] = nodes1[0];
918 other_nodes.push_back(4);
919 other_nodes.push_back(3);
920 other_nodes.push_back(2);
921 other_nodes.push_back(1);
924 for (
size_type i = 0; i <= nodes2.size()-1; ++i)
925 if (i != ip1 && i != ip2) {
926 GMM_ASSERT3(!other_nodes.empty(),
"");
927 nodes2[i] = nodes1[other_nodes.back()];
928 other_nodes.pop_back();
931 base_matrix G1, G2, G3;
932 base_matrix K(N, N), grad(N, N), K3(N, N), K4(N, N);
933 base_node normal1(N), normal2(N);
935 scalar_type J1, J2, J3(1), J4(1);
937 bgeot::vectors_to_base_matrix(G1, nodes1);
938 bgeot::vectors_to_base_matrix(G2, nodes2);
942 if (what == TETRA_CYL) {
943 if (nc == 1) nodes3[0] = nodes1[3];
944 bgeot::vectors_to_base_matrix(G3, nodes3);
945 pgt3->poly_vector_grad(nodes1[0], grad);
946 gmm::mult(gmm::transposed(grad), gmm::transposed(G3), K3);
947 J3 = gmm::abs(gmm::lu_inverse(K3));
950 for (
size_type i=0; i < base_im->nb_points(); ++i) {
952 gmm::copy(gmm::identity_matrix(), K4); J4 = J1 = scalar_type(1);
955 if (i >= base_im->nb_points_on_convex()) {
956 size_type ii = i - base_im->nb_points_on_convex();
957 for (
short_type ff=0; ff < base_im->structure()->nb_faces(); ++ff) {
958 if (ii < base_im->nb_points_on_face(ff)) { fp = ff;
break; }
959 else ii -= base_im->nb_points_on_face(ff);
961 normal1 = base_im->ref_convex()->normals()[fp];
964 base_node P = base_im->point(i);
965 if (what == TETRA_CYL) {
966 P = pgt3->transform(P, nodes3);
967 scalar_type x = P[0], y = P[1], one_minus_z = 1.0 - P[2];
968 K4(0, 1) = - y / one_minus_z;
969 K4(1, 1) = 1.0 - x / one_minus_z;
970 K4(2, 1) = - x * y / gmm::sqr(one_minus_z);
971 J4 = gmm::abs(gmm::lu_det(K4));
972 P[1] *= (1.0 - x / one_minus_z);
974 if (what == PRISM2) {
975 scalar_type x = P[0], y = P[1], one_minus_z = 1.0 - P[2];
976 K4(0,0) = one_minus_z; K4(2,0) = -x;
977 K4(1,1) = one_minus_z; K4(2,1) = -y;
978 J4 = gmm::abs(gmm::lu_det(K4));
983 base_node P1 = pgt1->transform(P, nodes1), P2(N);
984 pgt1->poly_vector_grad(P, grad);
985 gmm::mult(gmm::transposed(grad), gmm::transposed(G1), K);
986 J1 = gmm::abs(gmm::lu_det(K)) * J3 * J4;
988 if (fp !=
size_type(-1) && J1 > 1E-10 && J4 > 1E-10) {
989 if (what == TETRA_CYL) {
990 gmm::mult(K3, normal1, normal2);
995 gmm::mult(K4, normal1, normal2);
996 gmm::mult(K, normal2, normal1);
998 J1 *= gmm::vect_norm2(normal2);
999 normal2 /= gmm::vect_norm2(normal2);
1002 GMM_ASSERT1(pgt2->convex_ref()->is_in(P2) < 1E-8,
1003 "Point not in the convex ref : " << P2);
1005 pgt2->poly_vector_grad(P2, grad);
1006 gmm::mult(gmm::transposed(grad), gmm::transposed(G2), K);
1007 J2 = gmm::abs(gmm::lu_det(K));
1009 if (i < base_im->nb_points_on_convex())
1010 add_point(P2, base_im->coeff(i)*J1/J2,
short_type(-1));
1011 else if (J1 > 1E-10) {
1014 if (gmm::abs(pgt2->convex_ref()->is_in_face(ff, P2)) < 1E-8) {
1016 "An integration point is common to two faces");
1020 gmm::mult(K, normal2, normal1);
1021 add_point(P2,base_im->coeff(i)*J1*gmm::vect_norm2(normal1)/J2,f);
1026 if (what != TETRA_CYL)
break;
1033 static pintegration_method
1034 quasi_polar(im_param_list ¶ms,
1035 std::vector<dal::pstatic_stored_object> &dependencies) {
1036 GMM_ASSERT1(params.size() >= 1 && params[0].type() == 1,
1037 "Bad parameters for quasi polar integration: the first " 1038 "parameter should be an integration method");
1039 pintegration_method a = params[0].method();
1040 GMM_ASSERT1(a->type()==IM_APPROX,
"need an approximate integration method");
1041 int ip1 = 0, ip2 = 0;
1043 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters");
1045 GMM_ASSERT1(params.size() == 2 || params.size() == 3,
1046 "Bad number of parameters : " << params.size()
1047 <<
" should be 2 or 3.");
1048 GMM_ASSERT1(params[1].type() == 0
1049 && params.back().type() == 0,
"Bad type of parameters");
1050 ip1 = int(::floor(params[1].num() + 0.01));
1051 ip2 = int(::floor(params.back().num() + 0.01));
1053 int N = a->approx_method()->dim();
1054 GMM_ASSERT1(N >= 2 && N <= 3 && ip1 >= 0 && ip2 >= 0 && ip1 <= N
1055 && ip2 <= N,
"Bad parameters");
1058 pai = std::make_shared<quasi_polar_integration>(a->approx_method(),
1060 pintegration_method p = std::make_shared<integration_method>(pai);
1061 dependencies.push_back(p->approx_method()->ref_convex());
1062 dependencies.push_back(p->approx_method()->pintegration_points());
1066 static pintegration_method
1067 pyramid(im_param_list ¶ms,
1068 std::vector<dal::pstatic_stored_object> &dependencies) {
1069 GMM_ASSERT1(params.size() == 1 && params[0].type() == 1,
1070 "Bad parameters for pyramid integration: the first " 1071 "parameter should be an integration method");
1072 pintegration_method a = params[0].method();
1073 GMM_ASSERT1(a->type()==IM_APPROX,
"need an approximate integration method");
1074 int N = a->approx_method()->dim();
1075 GMM_ASSERT1(N == 3,
"Bad parameters");
1078 pai = std::make_shared<quasi_polar_integration>(a->approx_method(), 0, 0);
1079 pintegration_method p = std::make_shared<integration_method>(pai);
1080 dependencies.push_back(p->approx_method()->ref_convex());
1081 dependencies.push_back(p->approx_method()->pintegration_points());
1092 structured_composite_int_method(im_param_list &,
1093 std::vector<dal::pstatic_stored_object> &);
1094 pintegration_method HCT_composite_int_method(im_param_list ¶ms,
1095 std::vector<dal::pstatic_stored_object> &dependencies);
1097 pintegration_method QUADC1_composite_int_method(im_param_list ¶ms,
1098 std::vector<dal::pstatic_stored_object> &dependencies);
1100 pintegration_method pyramid_composite_int_method(im_param_list ¶ms,
1101 std::vector<dal::pstatic_stored_object> &dependencies);
1106 add_suffix(
"EXACT_SIMPLEX", exact_simplex);
1107 add_suffix(
"PRODUCT", product_which);
1108 add_suffix(
"EXACT_PARALLELEPIPED",exact_parallelepiped);
1109 add_suffix(
"EXACT_PRISM", exact_prism);
1110 add_suffix(
"GAUSS1D", gauss1d);
1111 add_suffix(
"NC", Newton_Cotes);
1112 add_suffix(
"NC_PARALLELEPIPED", Newton_Cotes_para);
1113 add_suffix(
"NC_PRISM", Newton_Cotes_prism);
1114 add_suffix(
"GAUSS_PARALLELEPIPED", Gauss_paramul);
1115 add_suffix(
"QUASI_POLAR", quasi_polar);
1116 add_suffix(
"PYRAMID", pyramid);
1117 add_suffix(
"STRUCTURED_COMPOSITE",
1118 structured_composite_int_method);
1119 add_suffix(
"HCT_COMPOSITE",
1120 HCT_composite_int_method);
1121 add_suffix(
"QUADC1_COMPOSITE",
1122 QUADC1_composite_int_method);
1123 add_suffix(
"PYRAMID_COMPOSITE",
1124 pyramid_composite_int_method);
1125 add_generic_function(im_list_integration);
1130 bool throw_if_not_found) {
1133 (name, i, throw_if_not_found);
1137 if (!(p.get()))
return "IM_NONE";
1142 void add_integration_name(std::string name,
1151 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(pintegration_method, pim, 0);
1152 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(
size_type, d, -2);
1154 std::stringstream name;
1155 name <<
"IM_EXACT_SIMPLEX(" << n <<
")";
1163 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(pintegration_method, pim, 0);
1164 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(
size_type, d, -2);
1166 std::stringstream name;
1167 name <<
"IM_EXACT_PARALLELEPIPED(" << n <<
")";
1175 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(pintegration_method, pim, 0);
1176 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(
size_type, d, -2);
1178 std::stringstream name;
1179 name <<
"IM_EXACT_PRISM(" << n <<
")";
1193 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(pintegration_method, im_last, 0);
1196 if (cvs_last == cvs)
1201 std::stringstream name;
1207 { name <<
"IM_EXACT_SIMPLEX("; found =
true; }
1211 if (!found && nbp == (
size_type(1) << n))
1213 { name <<
"IM_EXACT_PARALLELEPIPED("; found =
true; }
1217 if (!found && nbp == 2 * n)
1219 { name <<
"IM_EXACT_PRISM("; found =
true; }
1224 name << int(n) <<
')';
1230 GMM_ASSERT1(
false,
"This element is not taken into account. Contact us");
1238 static pintegration_method
1241 std::stringstream name;
1243 if(bgeot::is_torus_structure(cvs) && n == 3) n = 2;
1245 degree = std::max<dim_type>(degree, 1);
1251 case 1: name <<
"IM_GAUSS1D";
break;
1252 case 2: name <<
"IM_TRIANGLE";
break;
1253 case 3: name <<
"IM_TETRAHEDRON";
break;
1254 case 4: name <<
"IM_SIMPLEX4D";
break;
1255 default: GMM_ASSERT1(
false,
"no approximate integration method " 1256 "for simplexes of dimension " << n);
1259 std::stringstream name2;
1260 name2 << name.str() <<
"(" << k <<
")";
1264 GMM_ASSERT1(
false,
"could not find an " << name.str()
1265 <<
" of degree >= " << int(degree));
1267 GMM_ASSERT1(n == 3,
"Wrong dimension");
1268 name <<
"IM_PYRAMID(IM_GAUSS_PARALLELEPIPED(3," << degree <<
"))";
1269 }
else if (cvs->is_product(&a,&b) ||
1272 name <<
"IM_PRODUCT(" 1275 }
else GMM_ASSERT1(
false,
"unknown convex structure!");
1282 DEFINE_STATIC_THREAD_LOCAL(dim_type, degree_last);
1283 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(pintegration_method, im_last, 0);
1284 if (pgt_last == pgt && degree == degree_last)
1286 im_last = classical_approx_im_(pgt->structure(),degree);
1287 degree_last = degree;
1293 DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(pintegration_method,im_last,0);
1300 scalar_type test_integration_error(papprox_integration pim, dim_type order) {
1303 opt_long_scalar_type error(0);
1305 opt_long_scalar_type sum(0), realsum;
1306 for (
size_type i=0; i < pim->nb_points_on_convex(); ++i) {
1307 opt_long_scalar_type prod = pim->coeff(i);
1309 prod *= pow(opt_long_scalar_type(pim->point(i)[d]), idx[d]);
1312 realsum = exact->exact_method()->int_monomial(idx);
1313 error = std::max(error, gmm::abs(realsum-sum));
1315 return bgeot::to_scalar(error);
1318 papprox_integration get_approx_im_or_fail(pintegration_method pim) {
1319 GMM_ASSERT1(pim->type() == IM_APPROX,
"error estimate work only with " 1320 "approximate integration methods");
1321 return pim->approx_method();
pconvex_ref pyramid_QK_of_reference(dim_type k)
pyramidal element of reference of degree k (k = 1 or 2 only)
generation of permutations, and ranking/unranking of these.
Description of an exact integration of polynomials.
Provides mesh and mesh fem of torus.
pconvex_structure prism_P1_structure(dim_type nc)
Give a pointer on the structures of a prism of dimension d.
pintegration_method int_method_descriptor(std::string name, bool throw_if_not_found=true)
Get an integration method from its name .
does the inversion of the geometric transformation for a given convex
Integration methods (exact and approximated) on convexes.
pgeometric_trans geometric_trans_descriptor(std::string name)
Get the geometric transformation from its string name.
Tools for multithreaded, OpenMP and Boost based parallelization.
This file is generated by cubature/make_getfem_list.
pintegration_method exact_parallelepiped_im(size_type n)
return IM_EXACT_PARALLELEPIPED(n)
dim_type dim(void) const
Dimension of convex of reference.
pconvex_ref convex_ref_product(pconvex_ref a, pconvex_ref b)
tensorial product of two convex ref.
static T & instance()
Instance from the current thread.
pintegration_method exact_classical_im(bgeot::pgeometric_trans pgt) IS_DEPRECATED
use classical_exact_im instead.
long_scalar_type int_poly(const base_poly &P) const
Evaluate the integral of the polynomial P on the reference element.
Associate a name to a method descriptor and store method descriptors.
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
size_t size_type
used as the common size type in the library
Inversion of geometric transformations.
pconvex_structure pyramid_QK_structure(dim_type k)
Give a pointer on the 3D pyramid structure for a degree k = 1 or 2.
Vector of integer (16 bits type) which represent the powers of a monomial.
pintegration_method im_none(void)
return IM_NONE
std::string name_of_int_method(pintegration_method p)
Get the string name of an integration method .
pconvex_structure convex_product_structure(pconvex_structure a, pconvex_structure b)
Give a pointer on the structures of a convex which is the direct product of the convexes represented ...
A simple singleton implementation.
bool invert(const base_node &n, base_node &n_ref, scalar_type IN_EPS=1e-12)
given the node on the real element, returns the node on the reference element (even if it is outside ...
GEneric Tool for Finite Element Methods.
pintegration_method classical_exact_im(bgeot::pgeometric_trans pgt)
return an exact integration method for convex type handled by pgt.
gmm::uint16_type short_type
used as the common short type integer in the library
pconvex_structure parallelepiped_structure(dim_type nc, dim_type k)
Give a pointer on the structures of a parallelepiped of dimension d.
bgeot::pconvex_structure structure(void) const
{Structure of convex of reference.
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
LU factorizations and determinant computation for dense matrices.
pintegration_method classical_approx_im(bgeot::pgeometric_trans pgt, dim_type degree)
try to find an approximate integration method for the geometric transformation pgt which is able to i...
pconvex_structure basic_structure(pconvex_structure cv)
Original structure (if concerned)
pintegration_method exact_prism_im(size_type n)
return IM_EXACT_PRISM(n)
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree ...
long_scalar_type int_poly_on_face(const base_poly &P, short_type f) const
Evaluate the integral of the polynomial P on the face f of the reference element. ...
pintegration_method exact_simplex_im(size_type n)
return IM_EXACT_SIMPLEX(n)
pconvex_ref simplex_of_reference(dim_type nc, short_type K)
returns a simplex of reference of dimension nc and degree k
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
short_type degree() const
Gives the degree.