31 std::vector<scalar_type>& __aux1(){
32 THREAD_SAFE_STATIC std::vector<scalar_type> v;
36 std::vector<scalar_type>& __aux2(){
37 THREAD_SAFE_STATIC std::vector<scalar_type> v;
41 std::vector<scalar_type>& __aux3(){
42 THREAD_SAFE_STATIC std::vector<scalar_type> v;
46 std::vector<long>& __ipvt_aux(){
47 THREAD_SAFE_STATIC std::vector<long> vi;
53 void mat_mult(
const scalar_type *A,
const scalar_type *B, scalar_type *C,
56 auto itC = C;
auto itB = B;
57 for (
size_type j = 0; j < P; ++j, itB += N)
58 for (
size_type i = 0; i < M; ++i, ++itC) {
59 auto itA = A+i, itB1 = itB;
60 *itC = (*itA) * (*itB1);
62 { itA += M; ++itB1; *itC += (*itA) * (*itB1); }
64 }
else std::fill(C, C+M*P, scalar_type(0));
70 void mat_tmult(
const scalar_type *A,
const scalar_type *B, scalar_type *C,
74 case 0 : std::fill(C, C+M*P, scalar_type(0));
break;
77 for (
size_type i = 0; i < M; ++i, ++itC) {
78 auto itA = A+i, itB = B+j;
79 *itC = (*itA) * (*itB);
84 for (
size_type i = 0; i < M; ++i, ++itC) {
85 auto itA = A+i, itB = B+j;
86 *itC = (*itA) * (*itB);
87 itA += M; itB += P; *itC += (*itA) * (*itB);
92 for (
size_type i = 0; i < M; ++i, ++itC) {
93 auto itA = A+i, itB = B+j;
94 *itC = (*itA) * (*itB);
95 itA += M; itB += P; *itC += (*itA) * (*itB);
96 itA += M; itB += P; *itC += (*itA) * (*itB);
101 for (
size_type i = 0; i < M; ++i, ++itC) {
102 auto itA = A+i, itB = B+j;
103 *itC = (*itA) * (*itB);
105 { itA += M; itB += P; *itC += (*itA) * (*itB); }
114 size_type lu_factor(scalar_type *A, std::vector<long> &ipvt,
119 for (j = 0; j < N_1; ++j) {
120 auto it = A + (j*(N+1));
121 scalar_type max = gmm::abs(*it); jp = j;
122 for (i = j+1; i < N; ++i) {
123 scalar_type ap = gmm::abs(*(++it));
124 if (ap > max) { jp = i; max = ap; }
126 ipvt[j] = long(jp + 1);
128 if (max == scalar_type(0)) { info = j + 1;
break; }
130 auto it1 = A+jp, it2 = A+j;
131 for (i = 0; i < N; ++i, it1+=N, it2+=N) std::swap(*it1, *it2);
133 it = A + (j*(N+1)); max = *it++;
134 for (i = j+1; i < N; ++i) *it++ /= max;
135 auto it22 = A + (j*N + j+1), it11 = it22;
136 auto it3 = A + ((j+1)*N+j);
139 auto it1 = it11, it2 = it22;
140 scalar_type a = *it3; it3 += N;
141 for (
size_type k = j+1; k < N; ++k) *it1++ -= *it2++ * a;
150 static void lower_tri_solve(
const scalar_type *T, scalar_type *x,
int N,
153 for (
int j = 0; j < N; ++j) {
154 auto itc = T + j*N, it = itc+(j+1), ite = itc+N;
156 if (!is_unit) *itx /= itc[j];
158 for (; it != ite ; ++it, ++itx) *itx -= x_j * (*it);
162 static void upper_tri_solve(
const scalar_type *T, scalar_type *x,
int N,
165 for (
int j = N - 1; j >= 0; --j) {
166 auto itc = T + j*N, it = itc, ite = itc+j;
168 if (!is_unit) x[j] /= itc[j];
169 for (x_j = x[j]; it != ite ; ++it, ++itx) *itx -= x_j * (*it);
173 static void lu_solve(
const scalar_type *LU,
const std::vector<long> &ipvt,
174 scalar_type *x, scalar_type *b,
int N) {
175 std::copy(b, b+N, x);
176 for(
int i = 0; i < N; ++i)
177 {
long perm = ipvt[i]-1;
if(i != perm) std::swap(x[i], x[perm]); }
178 bgeot::lower_tri_solve(LU, x, N,
true);
179 bgeot::upper_tri_solve(LU, x, N,
false);
182 scalar_type lu_det(
const scalar_type *LU,
const std::vector<long> &ipvt,
185 for (
size_type j = 0; j < N; ++j) det *= *(LU+j*(N+1));
186 for(
long i = 0; i < long(N); ++i)
if (i != ipvt[i]-1) { det = -det; }
190 scalar_type lu_det(
const scalar_type *A,
size_type N) {
193 case 2:
return (*A) * (A[3]) - (A[1]) * (A[2]);
196 scalar_type a0 = A[4]*A[8] - A[5]*A[7], a3 = A[5]*A[6] - A[3]*A[8];
197 scalar_type a6 = A[3]*A[7] - A[4]*A[6];
198 return A[0] * a0 + A[1] * a3 + A[2] * a6;
203 if (__aux1().size() < NN) __aux1().resize(N*N);
204 std::copy(A, A+NN, __aux1().begin());
205 __ipvt_aux().resize(N);
206 lu_factor(&(*(__aux1().begin())), __ipvt_aux(), N);
207 return lu_det(&(*(__aux1().begin())), __ipvt_aux(), N);
212 void lu_inverse(
const scalar_type *LU,
const std::vector<long> &ipvt,
217 __aux2()[i] = scalar_type(1);
218 bgeot::lu_solve(LU, ipvt, A+i*N, &(*(__aux2().begin())),
int(N));
219 __aux2()[i] = scalar_type(0);
223 scalar_type lu_inverse(scalar_type *A,
size_type N,
bool doassert) {
227 scalar_type det = *A;
228 GMM_ASSERT1(det != scalar_type(0),
"Non invertible matrix");
229 *A = scalar_type(1)/det;
234 scalar_type a = *A, b = A[2], c = A[1], d = A[3];
235 scalar_type det = a * d - b * c;
236 GMM_ASSERT1(det != scalar_type(0),
"Non invertible matrix");
237 *A++ = d/det; *A++ /= -det; *A++ /= -det; *A = a/det;
242 scalar_type a0 = A[4]*A[8] - A[5]*A[7], a1 = A[5]*A[6] - A[3]*A[8];
243 scalar_type a2 = A[3]*A[7] - A[4]*A[6];
244 scalar_type det = A[0] * a0 + A[1] * a1 + A[2] * a2;
245 GMM_ASSERT1(det != scalar_type(0),
"Non invertible matrix");
246 scalar_type a3 = (A[2]*A[7] - A[1]*A[8]), a6 = (A[1]*A[5] - A[2]*A[4]);
247 scalar_type a4 = (A[0]*A[8] - A[2]*A[6]), a7 = (A[2]*A[3] - A[0]*A[5]);
248 scalar_type a5 = (A[1]*A[6] - A[0]*A[7]), a8 = (A[0]*A[4] - A[1]*A[3]);
249 *A++ = a0 / det; *A++ = a3 / det; *A++ = a6 / det;
250 *A++ = a1 / det; *A++ = a4 / det; *A++ = a7 / det;
251 *A++ = a2 / det; *A++ = a5 / det; *A++ = a8 / det;
257 if (__aux1().size() < NN) __aux1().resize(NN);
258 std::copy(A, A+NN, __aux1().begin());
259 __ipvt_aux().resize(N);
260 size_type info = lu_factor(&(*(__aux1().begin())), __ipvt_aux(), N);
261 if (doassert) GMM_ASSERT1(!info,
"Non invertible matrix, pivot = "
263 if (!info) lu_inverse(&(*(__aux1().begin())), __ipvt_aux(), A, N);
264 return lu_det(&(*(__aux1().begin())), __ipvt_aux(), N);
272 (
const base_matrix &G,
const base_matrix &pc, base_matrix &K)
const {
275 size_type N=gmm::mat_nrows(G), P=gmm::mat_nrows(pc), Q=gmm::mat_ncols(pc);
277 auto itK = K.begin();
279 auto itpc_j = pc.begin() + j*P, itG_b = G.begin();
280 for (
size_type i = 0; i < N; ++i, ++itG_b) {
281 auto itG = itG_b, itpc = itpc_j;
282 scalar_type a = *(itG) * (*itpc);
284 { itG += N; a += *(itG) * (*++itpc); }
288 }
else gmm::clear(K);
293 if (pspt_) xref_ = (*pspt_)[
ii_];
294 else GMM_ASSERT1(
false,
"Missing xref");
309 GMM_ASSERT1(have_G(),
310 "Convex center can be provided only if matrix G is available");
311 if (!have_cv_center_) {
316 gmm::scale(
cv_center_, scalar_type(1)/scalar_type(nb_pts));
317 have_cv_center_ =
true;
322 void geotrans_interpolation_context::compute_J()
const {
323 GMM_ASSERT1(have_G() && have_pgt(),
"Unable to compute J\n");
325 const base_matrix &KK =
K();
327 B_factors.base_resize(P, P);
328 gmm::mult(gmm::transposed(KK), KK, B_factors);
330 J__ =
J_ =::sqrt(gmm::abs(bgeot::lu_inverse(&(*(B_factors.begin())), P)));
332 auto it = &(*(KK.begin()));
334 case 1: J__ = *it;
break;
335 case 2: J__ = (*it) * (it[3]) - (it[1]) * (it[2]);
break;
338 B_.base_resize(P, P);
339 auto itB = B_.begin();
340 scalar_type a0 = itB[0] = it[4]*it[8] - it[5]*it[7];
341 scalar_type a1 = itB[1] = it[5]*it[6] - it[3]*it[8];
342 scalar_type a2 = itB[2] = it[3]*it[7] - it[4]*it[6];
343 J__ = it[0] * a0 + it[1] * a1 + it[2] * a2;
346 B_factors.base_resize(P, P);
347 gmm::copy(gmm::transposed(KK), B_factors);
349 bgeot::lu_factor(&(*(B_factors.begin())), ipvt, P);
350 J__ = bgeot::lu_det(&(*(B_factors.begin())), ipvt, P);
360 GMM_ASSERT1(have_G() && have_pgt(),
"Unable to compute K\n");
362 K_.base_resize(N(), P);
366 PC.base_resize(
pgt_->nb_points(), P);
375 const base_matrix& geotrans_interpolation_context::B()
const {
377 const base_matrix &KK =
K();
378 size_type P =
pgt_->structure()->dim(), N_ = gmm::mat_nrows(KK);
379 B_.base_resize(N_, P);
380 if (!have_J_) compute_J();
381 GMM_ASSERT1(J__ != scalar_type(0),
"Non invertible matrix");
383 gmm::mult(KK, B_factors, B_);
386 case 1: B_(0, 0) = scalar_type(1) / J__;
break;
389 auto it = &(*(KK.begin()));
auto itB = &(*(B_.begin()));
390 *itB++ = it[3] / J__;
391 *itB++ = -it[2] / J__;
392 *itB++ = -it[1] / J__;
397 auto it = &(*(KK.begin()));
auto itB = &(*(B_.begin()));
398 *itB++ /= J__; *itB++ /= J__; *itB++ /= J__;
399 *itB++ = (it[2]*it[7] - it[1]*it[8]) / J__;
400 *itB++ = (it[0]*it[8] - it[2]*it[6]) / J__;
401 *itB++ = (it[1]*it[6] - it[0]*it[7]) / J__;
402 *itB++ = (it[1]*it[5] - it[2]*it[4]) / J__;
403 *itB++ = (it[2]*it[3] - it[0]*it[5]) / J__;
404 *itB = (it[0]*it[4] - it[1]*it[3]) / J__;
407 bgeot::lu_inverse(&(*(B_factors.begin())), ipvt, &(*(B_.begin())), P);
416 const base_matrix& geotrans_interpolation_context::B3()
const {
418 const base_matrix &BB = B();
419 size_type P=gmm::mat_ncols(BB), N_=gmm::mat_nrows(BB);
420 B3_.base_resize(N_*N_, P*P);
425 B3_(k + N_*l, i + P*j) = BB(k, i) * BB(l, j);
431 const base_matrix& geotrans_interpolation_context::B32()
const {
433 const base_matrix &BB = B();
434 size_type P=gmm::mat_ncols(BB), N_=gmm::mat_nrows(BB);
435 B32_.base_resize(N_*N_, P);
436 if (!pgt()->is_linear()) {
437 base_matrix B2(P*P, P), Htau(N_, P*P);
442 PC.base_resize(pgt()->nb_points(), P*P);
443 pgt()->poly_vector_hess(
xref(),
PC);
450 B2(i + P*j, k) += Htau(l, i + P*j) * BB(l,k);
460 if (
pgt_ && !pgt()->is_linear())
461 { have_K_ = have_B_ = have_B3_ = have_B32_ = have_J_ =
false; }
467 const base_matrix &G)
const {
471 base_matrix::const_iterator git = G.begin();
473 scalar_type a = val[l];
474 base_node::iterator pit = P.begin(), pite = P.end();
475 for (; pit != pite; ++git, ++pit) *pit += a * (*git);
480 void geometric_trans::fill_standard_vertices() {
484 for (
size_type i = 0; i < cvr->points()[ip].size(); ++i)
485 if (gmm::abs(cvr->points()[ip][i]) > 1e-10
486 && gmm::abs(cvr->points()[ip][i]-1.0) > 1e-10
487 && gmm::abs(cvr->points()[ip][i]+1.0) > 1e-10)
488 { vertex =
false;
break; }
489 if (vertex) vertices_.push_back(ip);
491 dim_type dimension =
dim();
492 if (
dynamic_cast<const torus_geom_trans *
>(
this)) --dimension;
493 GMM_ASSERT1(vertices_.size() > dimension,
"Internal error");
500 template <
class FUNC>
501 struct igeometric_trans :
public geometric_trans {
503 std::vector<FUNC> trans;
504 mutable std::vector<std::vector<FUNC>> grad_, hess_;
505 mutable bool grad_computed_ =
false;
506 mutable bool hess_computed_ =
false;
508 void compute_grad_()
const {
509 if (grad_computed_)
return;
511 if (grad_computed_)
return;
517 for (dim_type j = 0; j < n; ++j) {
518 grad_[i][j] = trans[i]; grad_[i][j].derivative(j);
521 grad_computed_ =
true;
524 void compute_hess_()
const {
525 if (hess_computed_)
return;
527 if (hess_computed_)
return;
532 hess_[i].resize(n*n);
533 for (dim_type j = 0; j < n; ++j) {
534 for (dim_type k = 0; k < n; ++k) {
535 hess_[i][j+k*n] = trans[i];
536 hess_[i][j+k*n].derivative(j); hess_[i][j+k*n].derivative(k);
540 hess_computed_ =
true;
543 virtual void poly_vector_val(
const base_node &pt, base_vector &val)
const {
546 val[k] = to_scalar(trans[k].eval(pt.begin()));
549 virtual void poly_vector_val(
const base_node &pt,
550 const convex_ind_ct &ind_ct,
551 base_vector &val)
const {
553 val.resize(nb_funcs);
555 val[k] = to_scalar(trans[ind_ct[k]].eval(pt.begin()));
558 virtual void poly_vector_grad(
const base_node &pt, base_matrix &pc)
const {
559 if (!grad_computed_) compute_grad_();
563 for (dim_type n = 0; n <
dim(); ++n)
564 pc(i, n) = to_scalar(grad_[i][n].eval(pt.begin()));
567 virtual void poly_vector_grad(
const base_node &pt,
568 const convex_ind_ct &ind_ct,
569 base_matrix &pc)
const {
570 if (!grad_computed_) compute_grad_();
573 pc.base_resize(nb_funcs,
dim());
575 for (dim_type n = 0; n <
dim(); ++n)
576 pc(i, n) = to_scalar(grad_[ind_ct[i]][n].eval(pt.begin()));
579 virtual void poly_vector_hess(
const base_node &pt, base_matrix &pc)
const {
580 if (!hess_computed_) compute_hess_();
584 for (dim_type n = 0; n <
dim(); ++n) {
585 for (dim_type m = 0; m <= n; ++m)
586 pc(i, n*
dim()+m) = pc(i, m*
dim()+n) =
587 to_scalar(hess_[i][m*
dim()+n].eval(pt.begin()));
593 typedef igeometric_trans<base_poly> poly_geometric_trans;
594 typedef igeometric_trans<polynomial_composite> comppoly_geometric_trans;
595 typedef igeometric_trans<base_rational_fraction> fraction_geometric_trans;
601 struct simplex_trans_ :
public poly_geometric_trans {
604 base_poly l0(N, 0), l1(N, 0);
606 l0.one(); l1.one(); p = l0;
607 for (
short_type nn = 0; nn < N; ++nn) l0 -= base_poly(N, 1, nn);
610 for (
int nn = 1; nn <= N; ++nn) {
611 w[nn]=
short_type(floor(0.5+(((cvr->points())[i])[nn-1]*
double(K))));
618 p *= (l0 * (scalar_type(K) / scalar_type(j+1)))
619 - (l1 * (scalar_type(j) / scalar_type(j+1)));
621 p *= (base_poly(N, 1,
short_type(nn-1)) * (scalar_type(K) / scalar_type(j+1)))
622 - (l1 * (scalar_type(j) / scalar_type(j+1)));
627 size_type R = cvr->structure()->nb_points();
631 for (
size_type r = 0; r < R; ++r) calc_base_func(trans[r], r, k);
632 fill_standard_vertices();
637 PK_gt(gt_param_list ¶ms,
638 std::vector<dal::pstatic_stored_object> &dependencies) {
639 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
640 << params.size() <<
" should be 2.");
641 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
642 "Bad type of parameters");
643 int n = int(::floor(params[0].num() + 0.01));
644 int k = int(::floor(params[1].num() + 0.01));
645 GMM_ASSERT1(n >= 0 && n < 100 && k >= 0 && k <= 150 &&
646 double(n) == params[0].num() &&
double(k) == params[1].num(),
649 return std::make_shared<simplex_trans_>(dim_type(n), dim_type(k));
656 struct cv_pr_t_ :
public poly_geometric_trans {
657 cv_pr_t_(
const poly_geometric_trans *a,
const poly_geometric_trans *b) {
660 complexity_ = a->complexity() * b->complexity();
662 size_type n1 = a->nb_points(), n2 = b->nb_points();
663 trans.resize(n1 * n2);
666 trans[i1 + i2 * n1] = a->trans[i1];
667 trans[i1 + i2 * n1].direct_product(b->trans[i2]);
669 for (
size_type i2 = 0; i2 < b->nb_vertices(); ++i2)
670 for (
size_type i1 = 0; i1 < a->nb_vertices(); ++i1)
671 vertices_.push_back(a->vertices()[i1] + b->vertices()[i2] * n1);
676 std::vector<dal::pstatic_stored_object> &dependencies) {
677 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
678 << params.size() <<
" should be 2.");
679 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
680 "Bad type of parameters");
683 dependencies.push_back(a); dependencies.push_back(b);
686 const poly_geometric_trans *aa
687 =
dynamic_cast<const poly_geometric_trans *
>(a.get());
688 const poly_geometric_trans *bb
689 =
dynamic_cast<const poly_geometric_trans *
>(b.get());
690 GMM_ASSERT1(aa && bb,
"The product of geometric transformations "
691 "is only defined for polynomial ones");
692 return std::make_shared<cv_pr_t_>(aa, bb);
699 struct cv_pr_tl_ :
public poly_geometric_trans {
700 cv_pr_tl_(
const poly_geometric_trans *a,
const poly_geometric_trans *b) {
701 GMM_ASSERT1(a->is_linear() && b->is_linear(),
702 "linear product of non-linear transformations");
705 complexity_ = std::max(a->complexity(), b->complexity());
707 trans.resize(a->nb_points() * b->nb_points());
708 std::fill(trans.begin(), trans.end(), null_poly(
dim()));
710 std::stringstream name;
711 name <<
"GT_PK(" << int(
dim()) <<
",1)";
713 const poly_geometric_trans *pgt
714 =
dynamic_cast<const poly_geometric_trans *
>(pgt_.get());
717 trans[cvr->structure()->ind_dir_points()[i]]
719 for (
size_type i2 = 0; i2 < b->nb_vertices(); ++i2)
720 for (
size_type i1 = 0; i1 < a->nb_vertices(); ++i1)
721 vertices_.push_back(a->vertices()[i1]
722 + b->vertices()[i2] * a->nb_points());
727 std::vector<dal::pstatic_stored_object> &dependencies) {
728 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
729 << params.size() <<
" should be 2.");
730 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
731 "Bad type of parameters");
734 dependencies.push_back(a); dependencies.push_back(b);
737 const poly_geometric_trans *aa
738 =
dynamic_cast<const poly_geometric_trans *
>(a.get());
739 const poly_geometric_trans *bb
740 =
dynamic_cast<const poly_geometric_trans *
>(b.get());
741 GMM_ASSERT1(aa && bb,
"The product of geometric transformations "
742 "is only defined for polynomial ones");
743 return std::make_shared<cv_pr_tl_>(aa, bb);
751 std::vector<dal::pstatic_stored_object> &) {
752 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
753 << params.size() <<
" should be 2.");
754 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
755 "Bad type of parameters");
756 int n = int(::floor(params[0].num() + 0.01));
757 int k = int(::floor(params[1].num() + 0.01));
758 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
759 double(n) == params[0].num() &&
double(k) == params[1].num(),
761 std::stringstream name;
763 name <<
"GT_PK(1," << k <<
")";
765 name <<
"GT_PRODUCT(GT_QK(" << n-1 <<
"," << k <<
"),GT_PK(1,"
771 prism_pk_gt(gt_param_list ¶ms,
772 std::vector<dal::pstatic_stored_object> &) {
773 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
774 << params.size() <<
" should be 2.");
775 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
776 "Bad type of parameters");
777 int n = int(::floor(params[0].num() + 0.01));
778 int k = int(::floor(params[1].num() + 0.01));
779 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
780 double(n) == params[0].num() &&
double(k) == params[1].num(),
782 std::stringstream name;
783 name <<
"GT_PRODUCT(GT_PK(" << n-1 <<
"," << k <<
"),GT_PK(1,"
789 linear_qk(gt_param_list ¶ms,
790 std::vector<dal::pstatic_stored_object> &) {
791 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : "
792 << params.size() <<
" should be 1.");
793 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
794 int n = int(::floor(params[0].num() + 0.01));
795 return parallelepiped_linear_geotrans(n);
804 struct Q2_incomplete_trans_:
public poly_geometric_trans {
805 Q2_incomplete_trans_(dim_type nc) {
807 size_type R = cvr->structure()->nb_points();
814 (
"1 - 2*x^2*y - 2*x*y^2 + 2*x^2 + 5*x*y + 2*y^2 - 3*x - 3*y;"
815 "4*(x^2*y - x^2 - x*y + x);"
816 "2*x*y*y - 2*x*x*y + 2*x*x - x*y - x;"
817 "4*(x*y*y - x*y - y*y + y);"
819 "2*x*x*y - 2*x*y*y - x*y + 2*y*y - y;"
821 "2*x*x*y + 2*x*y*y - 3*x*y;");
823 for (
int i = 0; i < 8; ++i)
827 (
"1 + 2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2"
828 " - 2*x^2*y - 2*x^2*z - 2*x*y^2 - 2*y^2*z - 2*y*z^2 - 2*x*z^2 - 7*x*y*z"
829 " + 2*x^2 + 2*y^2 + 2*z^2 + 5*y*z + 5*x*z + 5*x*y - 3*x - 3*y - 3*z;"
830 "4*( - x^2*y*z + x*y*z + x^2*z - x*z + x^2*y - x*y - x^2 + x);"
831 "2*x^2*y*z - 2*x*y^2*z - 2*x*y*z^2"
832 " - 2*x^2*y - 2*x^2*z + 2*x*y^2 + 2*x*z^2 + 3*x*y*z + 2*x^2 - x*y - x*z - x;"
833 "4*( - x*y^2*z + x*y^2 + y^2*z + x*y*z - x*y - y^2 - y*z + y);"
834 "4*(x*y^2*z - x*y^2 - x*y*z + x*y);"
835 " - 2*x^2*y*z + 2*x*y^2*z - 2*x*y*z^2"
836 " + 2*x^2*y - 2*x*y^2 - 2*y^2*z + 2*y*z^2 + 3*x*y*z - x*y + 2*y^2 - y*z - y;"
837 "4*(x^2*y*z - x^2*y - x*y*z + x*y);"
838 " - 2*x^2*y*z - 2*x*y^2*z + 2*x*y*z^2 + 2*x^2*y + 2*x*y^2 + x*y*z - 3*x*y;"
839 "4*( - x*y*z^2 + x*z^2 + y*z^2 + x*y*z - x*z - y*z - z^2 + z);"
840 "4*(x*y*z^2 - x*y*z - x*z^2 + x*z);"
841 "4*(x*y*z^2 - x*y*z - y*z^2 + y*z);"
842 "4*( - x*y*z^2 + x*y*z);"
843 " - 2*x^2*y*z - 2*x*y^2*z + 2*x*y*z^2"
844 " + 2*x^2*z + 2*y^2*z - 2*x*z^2 - 2*y*z^2 + 3*x*y*z - x*z - y*z + 2*z^2 - z;"
845 "4*(x^2*y*z - x^2*z - x*y*z + x*z);"
846 " - 2*x^2*y*z + 2*x*y^2*z - 2*x*y*z^2 + 2*x^2*z + 2*x*z^2 + x*y*z - 3*x*z;"
847 "4*(x*y^2*z - y^2*z - x*y*z + y*z);"
848 "4*( - x*y^2*z + x*y*z);"
849 "2*x^2*y*z - 2*x*y^2*z - 2*x*y*z^2 + 2*y^2*z + 2*y*z^2 + x*y*z - 3*y*z;"
850 "4*( - x^2*y*z + x*y*z);"
851 "2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2 - 5*x*y*z;");
853 for (
int i = 0; i < 20; ++i)
856 fill_standard_vertices();
861 Q2_incomplete_gt(gt_param_list& params,
862 std::vector<dal::pstatic_stored_object> &dependencies) {
863 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : "
864 << params.size() <<
" should be 1.");
865 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
866 int n = int(::floor(params[0].num() + 0.01));
867 GMM_ASSERT1(n == 2 || n == 3,
"Bad parameter, expected value 2 or 3");
870 return std::make_shared<Q2_incomplete_trans_>(dim_type(n));
874 std::stringstream name;
875 name <<
"GT_Q2_INCOMPLETE(" << nc <<
")";
883 struct pyramid_QK_trans_:
public fraction_geometric_trans {
886 size_type R = cvr->structure()->nb_points();
910 trans[ 0] = Q*Q*xi0*xi1*(x*y-z*un_z);
911 trans[ 1] = Q*Q*xi0*xi1*xi2*(xi1*2.-un_z)*4.;
912 trans[ 2] = Q*Q*xi1*xi2*(-x*y-z*un_z);
913 trans[ 3] = Q*Q*xi3*xi0*xi1*(xi0*2.-un_z)*4.;
914 trans[ 4] = Q*Q*xi0*xi1*xi2*xi3*16.;
915 trans[ 5] = Q*Q*xi1*xi2*xi3*(xi2*2.-un_z)*4.;
916 trans[ 6] = Q*Q*xi3*xi0*(-x*y-z*un_z);
917 trans[ 7] = Q*Q*xi2*xi3*xi0*(xi3*2.-un_z)*4.;
918 trans[ 8] = Q*Q*xi2*xi3*(x*y-z*un_z);
919 trans[ 9] = Q*z*xi0*xi1*4.;
920 trans[10] = Q*z*xi1*xi2*4.;
921 trans[11] = Q*z*xi3*xi0*4.;
922 trans[12] = Q*z*xi2*xi3*4.;
925 fill_standard_vertices();
930 pyramid_QK_gt(gt_param_list& params,
931 std::vector<dal::pstatic_stored_object> &deps) {
932 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : "
933 << params.size() <<
" should be 1.");
934 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
935 int k = int(::floor(params[0].num() + 0.01));
938 return std::make_shared<pyramid_QK_trans_>(dim_type(k));
945 std::stringstream name;
946 name <<
"GT_PYRAMID(" << k <<
")";
956 struct pyramid_Q2_incomplete_trans_:
public fraction_geometric_trans {
957 pyramid_Q2_incomplete_trans_() {
959 size_type R = cvr->structure()->nb_points();
984 trans[ 0] = mmm0_ * pmmm + base_rational_fraction(mmm0_ * xy, p00m);
985 trans[ 1] = base_rational_fraction(pp0m * pm0m * p0mm * 0.5, p00m);
986 trans[ 2] = mpm0_ * ppmm - base_rational_fraction(mpm0_ * xy, p00m);
987 trans[ 3] = base_rational_fraction(p0pm * p0mm * pm0m * 0.5, p00m);
988 trans[ 4] = base_rational_fraction(p0pm * p0mm * pp0m * 0.5, p00m);
989 trans[ 5] = mmp0_ * pmpm - base_rational_fraction(mmp0_ * xy, p00m);
990 trans[ 6] = base_rational_fraction(pp0m * pm0m * p0pm * 0.5, p00m);
991 trans[ 7] = mpp0_ * pppm + base_rational_fraction(mpp0_ * xy, p00m);
992 trans[ 8] = base_rational_fraction(pm0m * p0mm * z, p00m);
993 trans[ 9] = base_rational_fraction(pp0m * p0mm * z, p00m);
994 trans[10] = base_rational_fraction(pm0m * p0pm * z, p00m);
995 trans[11] = base_rational_fraction(pp0m * p0pm * z, p00m);
998 fill_standard_vertices();
1003 pyramid_Q2_incomplete_gt(gt_param_list& params,
1004 std::vector<dal::pstatic_stored_object> &deps) {
1005 GMM_ASSERT1(params.size() == 0,
"Bad number of parameters : "
1006 << params.size() <<
" should be 0.");
1009 return std::make_shared<pyramid_Q2_incomplete_trans_>();
1023 struct prism_incomplete_P2_trans_:
public poly_geometric_trans {
1024 prism_incomplete_P2_trans_() {
1026 size_type R = cvr->structure()->nb_points();
1032 (
"-2*y*z^2-2*x*z^2+2*z^2-2*y^2*z-4*x*y*z+5*y*z-2*x^2*z+5*x*z"
1033 "-3*z+2*y^2+4*x*y-3*y+2*x^2-3*x+1;"
1034 "4*(x*y*z+x^2*z-x*z-x*y-x^2+x);"
1035 "2*x*z^2-2*x^2*z-x*z+2*x^2-x;"
1036 "4*(y^2*z+x*y*z-y*z-y^2-x*y+y);"
1038 "2*y*z^2-2*y^2*z-y*z+2*y^2-y;"
1039 "4*(y*z^2+x*z^2-z^2-y*z-x*z+z);"
1042 "-2*y*z^2-2*x*z^2+2*z^2+2*y^2*z+4*x*y*z-y*z+2*x^2*z-x*z-z;"
1043 "4*(-x*y*z-x^2*z+x*z);"
1044 "2*x*z^2+2*x^2*z-3*x*z;"
1045 "4*(-y^2*z-x*y*z+y*z);"
1047 "2*y*z^2+2*y^2*z-3*y*z;");
1049 for (
int i = 0; i < 15; ++i)
1052 fill_standard_vertices();
1057 prism_incomplete_P2_gt(gt_param_list& params,
1058 std::vector<dal::pstatic_stored_object> &deps) {
1059 GMM_ASSERT1(params.size() == 0,
"Bad number of parameters : "
1060 << params.size() <<
" should be 0.");
1063 return std::make_shared<prism_incomplete_P2_trans_>();
1083 GMM_ASSERT1(c.
G().ncols() == c.pgt()->nb_points(),
"dimensions mismatch");
1085 gmm::mult(c.B(), c.pgt()->normals()[face], un);
1096 GMM_ASSERT1(c.
G().ncols() == c.pgt()->nb_points(),
"dimensions mismatch");
1098 size_type P = c.pgt()->structure()->dim();
1100 base_matrix baseP(P, P);
1101 gmm::copy(gmm::identity_matrix(), baseP);
1104 if (gmm::abs(up[i])>gmm::abs(up[i0])) i0=i;
1105 if (i0) gmm::copy(gmm::mat_col(baseP, 0), gmm::mat_col(baseP, i0));
1106 gmm::copy(up, gmm::mat_col(baseP, 0));
1108 base_matrix baseN(c.N(), P);
1109 gmm::mult(c.B(), baseP, baseN);
1114 gmm::add(gmm::scaled(gmm::mat_col(baseN,l),
1115 -gmm::vect_sp(gmm::mat_col(baseN,l),
1116 gmm::mat_col(baseN,k))),
1117 gmm::mat_col(baseN,k));
1119 gmm::scale(gmm::mat_col(baseN,k),
1120 1./gmm::vect_norm2(gmm::mat_col(baseN,k)));
1125 if (c.N() == P && c.N()>1 && gmm::lu_det(baseN) < 0) {
1126 gmm::scale(gmm::mat_col(baseN,1),-1.);
1138 struct geometric_trans_naming_system
1140 geometric_trans_naming_system() :
1141 dal::naming_system<geometric_trans>(
"GT") {
1142 add_suffix(
"PK", PK_gt);
1143 add_suffix(
"QK", QK_gt);
1144 add_suffix(
"PRISM_PK", prism_pk_gt);
1145 add_suffix(
"PRISM", prism_pk_gt);
1146 add_suffix(
"PRODUCT", product_gt);
1147 add_suffix(
"LINEAR_PRODUCT", linear_product_gt);
1148 add_suffix(
"LINEAR_QK", linear_qk);
1149 add_suffix(
"Q2_INCOMPLETE", Q2_incomplete_gt);
1150 add_suffix(
"PYRAMID_QK", pyramid_QK_gt);
1151 add_suffix(
"PYRAMID", pyramid_QK_gt);
1152 add_suffix(
"PYRAMID_Q2_INCOMPLETE", pyramid_Q2_incomplete_gt);
1153 add_suffix(
"PRISM_INCOMPLETE_P2", prism_incomplete_P2_gt);
1157 void add_geometric_trans_name
1166 auto ptrans = name_system.method(name, i);
1168 auto short_name = name_system.shorter_name_of_method(ptrans);
1169 trans.set_name(short_name);
1176 if (pgt_torus)
return instance.shorter_name_of_method(pgt_torus->get_original_transformation());
1177 return instance.shorter_name_of_method(p);
1186 if (d != n || r != k) {
1187 std::stringstream name;
1188 name <<
"GT_PK(" << n <<
"," << k <<
")";
1199 if (d != n || r != k) {
1200 std::stringstream name;
1201 name <<
"GT_QK(" << n <<
"," << k <<
")";
1208 static std::string name_of_linear_qk_trans(
size_type dim) {
1210 case 1:
return "GT_PK(1,1)";
1211 default:
return std::string(
"GT_LINEAR_PRODUCT(")
1212 + name_of_linear_qk_trans(dim-1)
1213 + std::string(
",GT_PK(1,1))");
1221 std::stringstream name(name_of_linear_qk_trans(n));
1232 std::stringstream name;
1233 name <<
"GT_LINEAR_PRODUCT(GT_PK(" << (n-1) <<
", 1), GT_PK(1,1))";
1242 std::stringstream name;
1252 if (d != n || r != k) {
1253 std::stringstream name;
1254 name <<
"GT_PRISM(" << n <<
"," << k <<
")";
1266 if (pg1 != pg1_ || pg2 != pg2_) {
1267 std::stringstream name;
1271 pg1_ = pg1; pg2_ = pg2;
1280 dim_type n = cvs->dim();
1287 return parallelepiped_geotrans(n, 1);
1292 case 1 :
return simplex_geotrans(1,
short_type(nbpt-1));
1297 }
else if (nbf == 4) {
1300 return parallelepiped_geotrans(2, k);
1310 }
else if (nbf == 6) {
1313 return parallelepiped_geotrans(3, k);
1314 }
else if (nbf == 5) {
1322 return pyramid_Q2_incomplete_geotrans();
1326 GMM_ASSERT1(
false,
"Unrecognized structure");
1338 pstored_point_tab ps)
1340 { DAL_STORED_OBJECT_DEBUG_CREATED(
this,
"Geotrans precomp"); }
1342 void geotrans_precomp_::init_val()
const {
1344 c.resize(pspt->size(), base_vector(pgt->nb_points()));
1345 for (
size_type j = 0; j < pspt->size(); ++j)
1346 pgt->poly_vector_val((*pspt)[j], c[j]);
1349 void geotrans_precomp_::init_grad()
const {
1350 dim_type N = pgt->dim();
1352 pc.resize(pspt->size(), base_matrix(pgt->nb_points() , N));
1353 for (
size_type j = 0; j < pspt->size(); ++j)
1354 pgt->poly_vector_grad((*pspt)[j], pc[j]);
1357 void geotrans_precomp_::init_hess()
const {
1359 dim_type N = pgt->structure()->dim();
1361 hpc.resize(pspt->size(), base_matrix(pgt->nb_points(), gmm::sqr(N)));
1362 for (
size_type j = 0; j < pspt->size(); ++j)
1363 pgt->poly_vector_hess((*pspt)[j], hpc[j]);
1366 base_node geotrans_precomp_::transform(
size_type i,
1367 const base_matrix &G)
const {
1368 if (c.empty()) init_val();
1369 size_type N = G.nrows(), k = pgt->nb_points();
1371 base_matrix::const_iterator git = G.begin();
1373 scalar_type a = c[i][l];
1374 base_node::iterator pit = P.begin(), pite = P.end();
1375 for (; pit != pite; ++git, ++pit) *pit += a * (*git);
1381 pstored_point_tab pspt,
1382 dal::pstatic_stored_object dep) {
1383 dal::pstatic_stored_object_key pk= std::make_shared<pre_geot_key_>(pg,pspt);
1385 if (o)
return std::dynamic_pointer_cast<const geotrans_precomp_>(o);
1386 pgeotrans_precomp p = std::make_shared<geotrans_precomp_>(pg, pspt);
1392 void delete_geotrans_precomp(pgeotrans_precomp pgp)
Geometric transformations on convexes.
Handle composite polynomials.
Description of a geometric transformation between a reference element and a real element.
dim_type dim() const
Dimension of the reference element.
size_type nb_points() const
Number of geometric nodes.
base_node transform(const base_node &pt, const CONT &PTAB) const
Apply the geometric transformation to point pt, PTAB contains the points of the real convex.
virtual void compute_K_matrix(const base_matrix &G, const base_matrix &pc, base_matrix &K) const
compute K matrix from multiplication of G with gradient
virtual void poly_vector_val(const base_node &pt, base_vector &val) const =0
Gives the value of the functions vector at a certain point.
the geotrans_interpolation_context structure is passed as the argument of geometric transformation in...
const base_matrix & K() const
See getfem kernel doc for these matrices.
const base_matrix & G() const
matrix whose columns are the vertices of the convex
size_type ii_
if pgp != 0, it is the same as pgp's one
const base_node & xreal() const
coordinates of the current point, in the real convex.
const base_matrix * G_
transformed point
pgeometric_trans pgt_
see documentation (getfem kernel doc) for more details
base_node cv_center_
pointer to the matrix of real nodes of the convex
void set_xref(const base_node &P)
change the current point (coordinates given in the reference convex)
const base_node & xref() const
coordinates of the current point, in the reference convex.
const base_node & cv_center() const
coordinates of the center of the real convex.
base_matrix K_
real center of convex (average of columns of G)
base_node xreal_
reference point
scalar_type J_
index of current point in the pgp
Associate a name to a method descriptor and store method descriptors.
static T & instance()
Instance from the current thread.
A simple singleton implementation.
a balanced tree stored in a dal::dynamic_array
void copy(const L1 &l1, L2 &l2)
*/
void clear(L &l)
clear (fill with zeros) a vector or matrix.
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
pconvex_ref convex_ref_product(pconvex_ref a, pconvex_ref b)
tensorial product of two convex ref.
pconvex_structure pyramid_Q2_incomplete_structure()
Give a pointer on the 3D quadratic incomplete pyramid structure.
gmm::uint16_type short_type
used as the common short type integer in the library
pconvex_structure pyramid_QK_structure(dim_type k)
Give a pointer on the 3D pyramid structure for a degree k = 1 or 2.
std::string name_of_geometric_trans(pgeometric_trans p)
Get the string name of a geometric transformation.
base_poly read_base_poly(short_type n, std::istream &f)
read a base_poly on the stream ist.
pconvex_ref pyramid_QK_of_reference(dim_type k)
pyramidal element of reference of degree k (k = 1 or 2 only)
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 convex_structure > pconvex_structure
Pointer on a convex structure description.
pconvex_structure parallelepiped_structure(dim_type nc, dim_type k)
Give a pointer on the structures of a parallelepiped of dimension d.
pconvex_ref pyramid_Q2_incomplete_of_reference()
incomplete quadratic pyramidal element of reference (13-node)
pconvex_ref prism_incomplete_P2_of_reference()
incomplete quadratic prism element of reference (15-node)
pconvex_structure prism_P1_structure(dim_type nc)
Give a pointer on the structures of a prism of dimension d.
base_matrix compute_local_basis(const geotrans_interpolation_context &c, size_type face)
return the local basis (i.e.
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
base_small_vector compute_normal(const geotrans_interpolation_context &c, size_type face)
norm of returned vector is the ratio between the face surface on the real element and the face surfac...
pgeometric_trans geometric_trans_descriptor(std::string name)
Get the geometric transformation from its string name.
size_t size_type
used as the common size type in the library
pconvex_ref Q2_incomplete_of_reference(dim_type nc)
incomplete Q2 quadrilateral/hexahedral of reference of dimension d = 2 or 3
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
An adaptor that adapts a two dimensional geometric_trans to include radial dimension.