30 std::vector<scalar_type>& __aux1(){
31 THREAD_SAFE_STATIC std::vector<scalar_type> v;
35 std::vector<scalar_type>& __aux2(){
36 THREAD_SAFE_STATIC std::vector<scalar_type> v;
40 std::vector<scalar_type>& __aux3(){
41 THREAD_SAFE_STATIC std::vector<scalar_type> v;
45 std::vector<long>& __ipvt_aux(){
46 THREAD_SAFE_STATIC std::vector<long> vi;
52 void mat_mult(
const scalar_type *A,
const scalar_type *B, scalar_type *C,
55 auto itC = C;
auto itB = B;
56 for (
size_type j = 0; j < P; ++j, itB += N)
57 for (
size_type i = 0; i < M; ++i, ++itC) {
58 auto itA = A+i, itB1 = itB;
59 *itC = (*itA) * (*itB1);
61 { itA += M; ++itB1; *itC += (*itA) * (*itB1); }
63 }
else std::fill(C, C+M*P, scalar_type(0));
69 void mat_tmult(
const scalar_type *A,
const scalar_type *B, scalar_type *C,
73 case 0 : std::fill(C, C+M*P, scalar_type(0));
break;
76 for (
size_type i = 0; i < M; ++i, ++itC) {
77 auto itA = A+i, itB = B+j;
78 *itC = (*itA) * (*itB);
83 for (
size_type i = 0; i < M; ++i, ++itC) {
84 auto itA = A+i, itB = B+j;
85 *itC = (*itA) * (*itB);
86 itA += M; itB += P; *itC += (*itA) * (*itB);
91 for (
size_type i = 0; i < M; ++i, ++itC) {
92 auto itA = A+i, itB = B+j;
93 *itC = (*itA) * (*itB);
94 itA += M; itB += P; *itC += (*itA) * (*itB);
95 itA += M; itB += P; *itC += (*itA) * (*itB);
100 for (
size_type i = 0; i < M; ++i, ++itC) {
101 auto itA = A+i, itB = B+j;
102 *itC = (*itA) * (*itB);
104 { itA += M; itB += P; *itC += (*itA) * (*itB); }
113 size_type lu_factor(scalar_type *A, std::vector<long> &ipvt,
118 for (j = 0; j < N_1; ++j) {
119 auto it = A + (j*(N+1));
120 scalar_type max = gmm::abs(*it); jp = j;
121 for (i = j+1; i < N; ++i) {
122 scalar_type ap = gmm::abs(*(++it));
123 if (ap > max) { jp = i; max = ap; }
125 ipvt[j] = long(jp + 1);
127 if (max == scalar_type(0)) { info = j + 1;
break; }
129 auto it1 = A+jp, it2 = A+j;
130 for (i = 0; i < N; ++i, it1+=N, it2+=N) std::swap(*it1, *it2);
132 it = A + (j*(N+1)); max = *it++;
133 for (i = j+1; i < N; ++i) *it++ /= max;
134 auto it22 = A + (j*N + j+1), it11 = it22;
135 auto it3 = A + ((j+1)*N+j);
138 auto it1 = it11, it2 = it22;
139 scalar_type a = *it3; it3 += N;
140 for (
size_type k = j+1; k < N; ++k) *it1++ -= *it2++ * a;
149 static void lower_tri_solve(
const scalar_type *T, scalar_type *x,
int N,
152 for (
int j = 0; j < N; ++j) {
153 auto itc = T + j*N, it = itc+(j+1), ite = itc+N;
155 if (!is_unit) *itx /= itc[j];
157 for (; it != ite ; ++it, ++itx) *itx -= x_j * (*it);
161 static void upper_tri_solve(
const scalar_type *T, scalar_type *x,
int N,
164 for (
int j = N - 1; j >= 0; --j) {
165 auto itc = T + j*N, it = itc, ite = itc+j;
167 if (!is_unit) x[j] /= itc[j];
168 for (x_j = x[j]; it != ite ; ++it, ++itx) *itx -= x_j * (*it);
172 static void lu_solve(
const scalar_type *LU,
const std::vector<long> &ipvt,
173 scalar_type *x, scalar_type *b,
int N) {
174 std::copy(b, b+N, x);
175 for(
int i = 0; i < N; ++i)
176 {
long perm = ipvt[i]-1;
if(i != perm) std::swap(x[i], x[perm]); }
177 bgeot::lower_tri_solve(LU, x, N,
true);
178 bgeot::upper_tri_solve(LU, x, N,
false);
181 scalar_type lu_det(
const scalar_type *LU,
const std::vector<long> &ipvt,
184 for (
size_type j = 0; j < N; ++j) det *= *(LU+j*(N+1));
185 for(
long i = 0; i < long(N); ++i)
if (i != ipvt[i]-1) { det = -det; }
189 scalar_type lu_det(
const scalar_type *A,
size_type N) {
192 case 2:
return (*A) * (A[3]) - (A[1]) * (A[2]);
195 scalar_type a0 = A[4]*A[8] - A[5]*A[7], a3 = A[5]*A[6] - A[3]*A[8];
196 scalar_type a6 = A[3]*A[7] - A[4]*A[6];
197 return A[0] * a0 + A[1] * a3 + A[2] * a6;
202 if (__aux1().size() < NN) __aux1().resize(N*N);
203 std::copy(A, A+NN, __aux1().begin());
204 __ipvt_aux().resize(N);
205 lu_factor(&(*(__aux1().begin())), __ipvt_aux(), N);
206 return lu_det(&(*(__aux1().begin())), __ipvt_aux(), N);
211 void lu_inverse(
const scalar_type *LU,
const std::vector<long> &ipvt,
216 __aux2()[i] = scalar_type(1);
217 bgeot::lu_solve(LU, ipvt, A+i*N, &(*(__aux2().begin())),
int(N));
218 __aux2()[i] = scalar_type(0);
222 scalar_type lu_inverse(scalar_type *A,
size_type N,
bool doassert) {
226 scalar_type det = *A;
227 GMM_ASSERT1(!doassert || det != scalar_type(0),
"Non invertible matrix");
228 *A = scalar_type(1)/det;
233 scalar_type a = *A, b = A[2], c = A[1], d = A[3];
234 scalar_type det = a * d - b * c;
235 GMM_ASSERT1(!doassert || det != scalar_type(0),
"Non invertible matrix");
236 *A++ = d/det; *A++ /= -det; *A++ /= -det; *A = a/det;
241 scalar_type a0 = A[4]*A[8] - A[5]*A[7], a1 = A[5]*A[6] - A[3]*A[8];
242 scalar_type a2 = A[3]*A[7] - A[4]*A[6];
243 scalar_type det = A[0] * a0 + A[1] * a1 + A[2] * a2;
244 GMM_ASSERT1(!doassert || det != scalar_type(0),
"Non invertible matrix");
245 scalar_type a3 = (A[2]*A[7] - A[1]*A[8]), a6 = (A[1]*A[5] - A[2]*A[4]);
246 scalar_type a4 = (A[0]*A[8] - A[2]*A[6]), a7 = (A[2]*A[3] - A[0]*A[5]);
247 scalar_type a5 = (A[1]*A[6] - A[0]*A[7]), a8 = (A[0]*A[4] - A[1]*A[3]);
248 *A++ = a0 / det; *A++ = a3 / det; *A++ = a6 / det;
249 *A++ = a1 / det; *A++ = a4 / det; *A++ = a7 / det;
250 *A++ = a2 / det; *A++ = a5 / det; *A++ = a8 / det;
256 if (__aux1().size() < NN) __aux1().resize(NN);
257 std::copy(A, A+NN, __aux1().begin());
258 __ipvt_aux().resize(N);
259 size_type info = lu_factor(&(*(__aux1().begin())), __ipvt_aux(), N);
260 GMM_ASSERT1(!doassert || !info,
"Non invertible matrix, pivot = "
262 if (!info) lu_inverse(&(*(__aux1().begin())), __ipvt_aux(), A, N);
263 return lu_det(&(*(__aux1().begin())), __ipvt_aux(), N);
271 (
const base_matrix &G,
const base_matrix &pc, base_matrix &K)
const {
274 size_type N=gmm::mat_nrows(G), P=gmm::mat_nrows(pc), Q=gmm::mat_ncols(pc);
276 auto itK = K.begin();
278 auto itpc_j = pc.begin() + j*P, itG_b = G.begin();
279 for (
size_type i = 0; i < N; ++i, ++itG_b) {
280 auto itG = itG_b, itpc = itpc_j;
281 scalar_type a = *(itG) * (*itpc);
283 { itG += N; a += *(itG) * (*++itpc); }
287 }
else gmm::clear(K);
292 if (pspt_) xref_ = (*pspt_)[
ii_];
293 else GMM_ASSERT1(
false,
"Missing xref");
308 GMM_ASSERT1(have_G(),
309 "Convex center can be provided only if matrix G is available");
310 if (!have_cv_center_) {
315 gmm::scale(
cv_center_, scalar_type(1)/scalar_type(nb_pts));
316 have_cv_center_ =
true;
321 void geotrans_interpolation_context::compute_J()
const {
322 GMM_ASSERT1(have_G() && have_pgt(),
"Unable to compute J\n");
324 const base_matrix &KK =
K();
326 B_factors.base_resize(P, P);
327 gmm::mult(gmm::transposed(KK), KK, B_factors);
329 J__ =
J_ =::sqrt(gmm::abs(bgeot::lu_inverse(&(*(B_factors.begin())), P)));
331 auto it = &(*(KK.begin()));
333 case 1: J__ = *it;
break;
334 case 2: J__ = (*it) * (it[3]) - (it[1]) * (it[2]);
break;
337 B_.base_resize(P, P);
338 auto itB = B_.begin();
339 scalar_type a0 = itB[0] = it[4]*it[8] - it[5]*it[7];
340 scalar_type a1 = itB[1] = it[5]*it[6] - it[3]*it[8];
341 scalar_type a2 = itB[2] = it[3]*it[7] - it[4]*it[6];
342 J__ = it[0] * a0 + it[1] * a1 + it[2] * a2;
345 B_factors.base_resize(P, P);
346 gmm::copy(gmm::transposed(KK), B_factors);
348 bgeot::lu_factor(&(*(B_factors.begin())), ipvt, P);
349 J__ = bgeot::lu_det(&(*(B_factors.begin())), ipvt, P);
359 GMM_ASSERT1(have_G() && have_pgt(),
"Unable to compute K\n");
361 K_.base_resize(N(), P);
365 PC.base_resize(
pgt_->nb_points(), P);
374 const base_matrix& geotrans_interpolation_context::B()
const {
376 const base_matrix &KK =
K();
377 size_type P =
pgt_->structure()->dim(), N_ = gmm::mat_nrows(KK);
378 B_.base_resize(N_, P);
379 if (!have_J_) compute_J();
380 GMM_ASSERT1(J__ != scalar_type(0),
"Non invertible matrix");
382 gmm::mult(KK, B_factors, B_);
385 case 1: B_(0, 0) = scalar_type(1) / J__;
break;
388 auto it = &(*(KK.begin()));
auto itB = &(*(B_.begin()));
389 *itB++ = it[3] / J__;
390 *itB++ = -it[2] / J__;
391 *itB++ = -it[1] / J__;
396 auto it = &(*(KK.begin()));
auto itB = &(*(B_.begin()));
397 *itB++ /= J__; *itB++ /= J__; *itB++ /= J__;
398 *itB++ = (it[2]*it[7] - it[1]*it[8]) / J__;
399 *itB++ = (it[0]*it[8] - it[2]*it[6]) / J__;
400 *itB++ = (it[1]*it[6] - it[0]*it[7]) / J__;
401 *itB++ = (it[1]*it[5] - it[2]*it[4]) / J__;
402 *itB++ = (it[2]*it[3] - it[0]*it[5]) / J__;
403 *itB = (it[0]*it[4] - it[1]*it[3]) / J__;
406 bgeot::lu_inverse(&(*(B_factors.begin())), ipvt, &(*(B_.begin())), P);
415 const base_matrix& geotrans_interpolation_context::B3()
const {
417 const base_matrix &BB = B();
418 size_type P=gmm::mat_ncols(BB), N_=gmm::mat_nrows(BB);
419 B3_.base_resize(N_*N_, P*P);
424 B3_(k + N_*l, i + P*j) = BB(k, i) * BB(l, j);
430 const base_matrix& geotrans_interpolation_context::B32()
const {
432 const base_matrix &BB = B();
433 size_type P=gmm::mat_ncols(BB), N_=gmm::mat_nrows(BB);
434 B32_.base_resize(N_*N_, P);
435 if (!pgt()->is_linear()) {
436 base_matrix B2(P*P, P), Htau(N_, P*P);
441 PC.base_resize(pgt()->nb_points(), P*P);
442 pgt()->poly_vector_hess(
xref(),
PC);
449 B2(i + P*j, k) += Htau(l, i + P*j) * BB(l,k);
459 if (
pgt_ && !pgt()->is_linear())
460 { have_K_ = have_B_ = have_B3_ = have_B32_ = have_J_ =
false; }
466 const base_matrix &G)
const {
470 base_matrix::const_iterator git = G.begin();
472 scalar_type a = val[l];
473 base_node::iterator pit = P.begin(), pite = P.end();
474 for (; pit != pite; ++git, ++pit) *pit += a * (*git);
479 void geometric_trans::fill_standard_vertices() {
483 for (
size_type i = 0; i < cvr->points()[ip].size(); ++i)
484 if (gmm::abs(cvr->points()[ip][i]) > 1e-10
485 && gmm::abs(cvr->points()[ip][i]-1.0) > 1e-10
486 && gmm::abs(cvr->points()[ip][i]+1.0) > 1e-10)
487 { vertex =
false;
break; }
488 if (vertex) vertices_.push_back(ip);
490 dim_type dimension =
dim();
491 if (
dynamic_cast<const torus_geom_trans *
>(
this)) --dimension;
492 GMM_ASSERT1(vertices_.size() > dimension,
"Internal error");
499 template <
class FUNC>
500 struct igeometric_trans :
public geometric_trans {
502 std::vector<FUNC> trans;
503 mutable std::vector<std::vector<FUNC>> grad_, hess_;
504 mutable bool grad_computed_ =
false;
505 mutable bool hess_computed_ =
false;
507 void compute_grad_()
const {
508 if (grad_computed_)
return;
510 if (grad_computed_)
return;
516 for (dim_type j = 0; j < n; ++j) {
517 grad_[i][j] = trans[i]; grad_[i][j].derivative(j);
520 grad_computed_ =
true;
523 void compute_hess_()
const {
524 if (hess_computed_)
return;
526 if (hess_computed_)
return;
531 hess_[i].resize(n*n);
532 for (dim_type j = 0; j < n; ++j) {
533 for (dim_type k = 0; k < n; ++k) {
534 hess_[i][j+k*n] = trans[i];
535 hess_[i][j+k*n].derivative(j); hess_[i][j+k*n].derivative(k);
539 hess_computed_ =
true;
542 virtual void poly_vector_val(
const base_node &pt, base_vector &val)
const {
545 val[k] = to_scalar(trans[k].eval(pt.begin()));
548 virtual void poly_vector_val(
const base_node &pt,
549 const convex_ind_ct &ind_ct,
550 base_vector &val)
const {
552 val.resize(nb_funcs);
554 val[k] = to_scalar(trans[ind_ct[k]].eval(pt.begin()));
557 virtual void poly_vector_grad(
const base_node &pt, base_matrix &pc)
const {
558 if (!grad_computed_) compute_grad_();
562 for (dim_type n = 0; n <
dim(); ++n)
563 pc(i, n) = to_scalar(grad_[i][n].eval(pt.begin()));
566 virtual void poly_vector_grad(
const base_node &pt,
567 const convex_ind_ct &ind_ct,
568 base_matrix &pc)
const {
569 if (!grad_computed_) compute_grad_();
572 pc.base_resize(nb_funcs,
dim());
574 for (dim_type n = 0; n <
dim(); ++n)
575 pc(i, n) = to_scalar(grad_[ind_ct[i]][n].eval(pt.begin()));
578 virtual void poly_vector_hess(
const base_node &pt, base_matrix &pc)
const {
579 if (!hess_computed_) compute_hess_();
583 for (dim_type n = 0; n <
dim(); ++n) {
584 for (dim_type m = 0; m <= n; ++m)
585 pc(i, n*
dim()+m) = pc(i, m*
dim()+n) =
586 to_scalar(hess_[i][m*
dim()+n].eval(pt.begin()));
592 typedef igeometric_trans<base_poly> poly_geometric_trans;
593 typedef igeometric_trans<polynomial_composite> comppoly_geometric_trans;
594 typedef igeometric_trans<base_rational_fraction> fraction_geometric_trans;
600 struct simplex_trans_ :
public poly_geometric_trans {
603 base_poly l0(N, 0), l1(N, 0);
605 l0.one(); l1.one(); p = l0;
606 for (
short_type nn = 0; nn < N; ++nn) l0 -= base_poly(N, 1, nn);
609 for (
int nn = 1; nn <= N; ++nn) {
610 w[nn]=
short_type(floor(0.5+(((cvr->points())[i])[nn-1]*
double(K))));
617 p *= (l0 * (scalar_type(K) / scalar_type(j+1)))
618 - (l1 * (scalar_type(j) / scalar_type(j+1)));
620 p *= (base_poly(N, 1,
short_type(nn-1)) * (scalar_type(K) / scalar_type(j+1)))
621 - (l1 * (scalar_type(j) / scalar_type(j+1)));
626 size_type R = cvr->structure()->nb_points();
630 for (
size_type r = 0; r < R; ++r) calc_base_func(trans[r], r, k);
631 fill_standard_vertices();
636 PK_gt(gt_param_list ¶ms,
637 std::vector<dal::pstatic_stored_object> &dependencies) {
638 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
639 << params.size() <<
" should be 2.");
640 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
641 "Bad type of parameters");
642 int n = int(::floor(params[0].num() + 0.01));
643 int k = int(::floor(params[1].num() + 0.01));
644 GMM_ASSERT1(n >= 0 && n < 100 && k >= 0 && k <= 150 &&
645 double(n) == params[0].num() &&
double(k) == params[1].num(),
648 return std::make_shared<simplex_trans_>(dim_type(n), dim_type(k));
655 struct cv_pr_t_ :
public poly_geometric_trans {
656 cv_pr_t_(
const poly_geometric_trans *a,
const poly_geometric_trans *b) {
659 complexity_ = a->complexity() * b->complexity();
661 size_type n1 = a->nb_points(), n2 = b->nb_points();
662 trans.resize(n1 * n2);
665 trans[i1 + i2 * n1] = a->trans[i1];
666 trans[i1 + i2 * n1].direct_product(b->trans[i2]);
668 for (
size_type i2 = 0; i2 < b->nb_vertices(); ++i2)
669 for (
size_type i1 = 0; i1 < a->nb_vertices(); ++i1)
670 vertices_.push_back(a->vertices()[i1] + b->vertices()[i2] * n1);
675 std::vector<dal::pstatic_stored_object> &dependencies) {
676 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
677 << params.size() <<
" should be 2.");
678 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
679 "Bad type of parameters");
682 dependencies.push_back(a); dependencies.push_back(b);
685 const poly_geometric_trans *aa
686 =
dynamic_cast<const poly_geometric_trans *
>(a.get());
687 const poly_geometric_trans *bb
688 =
dynamic_cast<const poly_geometric_trans *
>(b.get());
689 GMM_ASSERT1(aa && bb,
"The product of geometric transformations "
690 "is only defined for polynomial ones");
691 return std::make_shared<cv_pr_t_>(aa, bb);
698 struct cv_pr_tl_ :
public poly_geometric_trans {
699 cv_pr_tl_(
const poly_geometric_trans *a,
const poly_geometric_trans *b) {
700 GMM_ASSERT1(a->is_linear() && b->is_linear(),
701 "linear product of non-linear transformations");
704 complexity_ = std::max(a->complexity(), b->complexity());
706 trans.resize(a->nb_points() * b->nb_points());
707 std::fill(trans.begin(), trans.end(), null_poly(
dim()));
709 std::stringstream name;
710 name <<
"GT_PK(" << int(
dim()) <<
",1)";
712 const poly_geometric_trans *pgt
713 =
dynamic_cast<const poly_geometric_trans *
>(pgt_.get());
716 trans[cvr->structure()->ind_dir_points()[i]]
718 for (
size_type i2 = 0; i2 < b->nb_vertices(); ++i2)
719 for (
size_type i1 = 0; i1 < a->nb_vertices(); ++i1)
720 vertices_.push_back(a->vertices()[i1]
721 + b->vertices()[i2] * a->nb_points());
726 std::vector<dal::pstatic_stored_object> &dependencies) {
727 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
728 << params.size() <<
" should be 2.");
729 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
730 "Bad type of parameters");
733 dependencies.push_back(a); dependencies.push_back(b);
736 const poly_geometric_trans *aa
737 =
dynamic_cast<const poly_geometric_trans *
>(a.get());
738 const poly_geometric_trans *bb
739 =
dynamic_cast<const poly_geometric_trans *
>(b.get());
740 GMM_ASSERT1(aa && bb,
"The product of geometric transformations "
741 "is only defined for polynomial ones");
742 return std::make_shared<cv_pr_tl_>(aa, bb);
750 std::vector<dal::pstatic_stored_object> &) {
751 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
752 << params.size() <<
" should be 2.");
753 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
754 "Bad type of parameters");
755 int n = int(::floor(params[0].num() + 0.01));
756 int k = int(::floor(params[1].num() + 0.01));
757 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
758 double(n) == params[0].num() &&
double(k) == params[1].num(),
760 std::stringstream name;
762 name <<
"GT_PK(1," << k <<
")";
764 name <<
"GT_PRODUCT(GT_QK(" << n-1 <<
"," << k <<
"),GT_PK(1,"
770 prism_pk_gt(gt_param_list ¶ms,
771 std::vector<dal::pstatic_stored_object> &) {
772 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : "
773 << params.size() <<
" should be 2.");
774 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
775 "Bad type of parameters");
776 int n = int(::floor(params[0].num() + 0.01));
777 int k = int(::floor(params[1].num() + 0.01));
778 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
779 double(n) == params[0].num() &&
double(k) == params[1].num(),
781 std::stringstream name;
782 name <<
"GT_PRODUCT(GT_PK(" << n-1 <<
"," << k <<
"),GT_PK(1,"
788 linear_qk(gt_param_list ¶ms,
789 std::vector<dal::pstatic_stored_object> &) {
790 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : "
791 << params.size() <<
" should be 1.");
792 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
793 int n = int(::floor(params[0].num() + 0.01));
794 return parallelepiped_linear_geotrans(n);
803 struct Q2_incomplete_trans_:
public poly_geometric_trans {
804 Q2_incomplete_trans_(dim_type nc) {
806 size_type R = cvr->structure()->nb_points();
813 (
"1 - 2*x^2*y - 2*x*y^2 + 2*x^2 + 5*x*y + 2*y^2 - 3*x - 3*y;"
814 "4*(x^2*y - x^2 - x*y + x);"
815 "2*x*y*y - 2*x*x*y + 2*x*x - x*y - x;"
816 "4*(x*y*y - x*y - y*y + y);"
818 "2*x*x*y - 2*x*y*y - x*y + 2*y*y - y;"
820 "2*x*x*y + 2*x*y*y - 3*x*y;");
822 for (
int i = 0; i < 8; ++i)
826 (
"1 + 2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2"
827 " - 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"
828 " + 2*x^2 + 2*y^2 + 2*z^2 + 5*y*z + 5*x*z + 5*x*y - 3*x - 3*y - 3*z;"
829 "4*( - x^2*y*z + x*y*z + x^2*z - x*z + x^2*y - x*y - x^2 + x);"
830 "2*x^2*y*z - 2*x*y^2*z - 2*x*y*z^2"
831 " - 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;"
832 "4*( - x*y^2*z + x*y^2 + y^2*z + x*y*z - x*y - y^2 - y*z + y);"
833 "4*(x*y^2*z - x*y^2 - x*y*z + x*y);"
834 " - 2*x^2*y*z + 2*x*y^2*z - 2*x*y*z^2"
835 " + 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;"
836 "4*(x^2*y*z - x^2*y - x*y*z + x*y);"
837 " - 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;"
838 "4*( - x*y*z^2 + x*z^2 + y*z^2 + x*y*z - x*z - y*z - z^2 + z);"
839 "4*(x*y*z^2 - x*y*z - x*z^2 + x*z);"
840 "4*(x*y*z^2 - x*y*z - y*z^2 + y*z);"
841 "4*( - x*y*z^2 + x*y*z);"
842 " - 2*x^2*y*z - 2*x*y^2*z + 2*x*y*z^2"
843 " + 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;"
844 "4*(x^2*y*z - x^2*z - x*y*z + x*z);"
845 " - 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;"
846 "4*(x*y^2*z - y^2*z - x*y*z + y*z);"
847 "4*( - x*y^2*z + x*y*z);"
848 "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;"
849 "4*( - x^2*y*z + x*y*z);"
850 "2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2 - 5*x*y*z;");
852 for (
int i = 0; i < 20; ++i)
855 fill_standard_vertices();
860 Q2_incomplete_gt(gt_param_list& params,
861 std::vector<dal::pstatic_stored_object> &dependencies) {
862 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : "
863 << params.size() <<
" should be 1.");
864 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
865 int n = int(::floor(params[0].num() + 0.01));
866 GMM_ASSERT1(n == 2 || n == 3,
"Bad parameter, expected value 2 or 3");
869 return std::make_shared<Q2_incomplete_trans_>(dim_type(n));
873 std::stringstream name;
874 name <<
"GT_Q2_INCOMPLETE(" << nc <<
")";
882 struct pyramid_QK_trans_:
public fraction_geometric_trans {
885 size_type R = cvr->structure()->nb_points();
909 trans[ 0] = Q*Q*xi0*xi1*(x*y-z*un_z);
910 trans[ 1] = Q*Q*xi0*xi1*xi2*(xi1*2.-un_z)*4.;
911 trans[ 2] = Q*Q*xi1*xi2*(-x*y-z*un_z);
912 trans[ 3] = Q*Q*xi3*xi0*xi1*(xi0*2.-un_z)*4.;
913 trans[ 4] = Q*Q*xi0*xi1*xi2*xi3*16.;
914 trans[ 5] = Q*Q*xi1*xi2*xi3*(xi2*2.-un_z)*4.;
915 trans[ 6] = Q*Q*xi3*xi0*(-x*y-z*un_z);
916 trans[ 7] = Q*Q*xi2*xi3*xi0*(xi3*2.-un_z)*4.;
917 trans[ 8] = Q*Q*xi2*xi3*(x*y-z*un_z);
918 trans[ 9] = Q*z*xi0*xi1*4.;
919 trans[10] = Q*z*xi1*xi2*4.;
920 trans[11] = Q*z*xi3*xi0*4.;
921 trans[12] = Q*z*xi2*xi3*4.;
924 fill_standard_vertices();
929 pyramid_QK_gt(gt_param_list& params,
930 std::vector<dal::pstatic_stored_object> &deps) {
931 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : "
932 << params.size() <<
" should be 1.");
933 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
934 int k = int(::floor(params[0].num() + 0.01));
937 return std::make_shared<pyramid_QK_trans_>(dim_type(k));
944 std::stringstream name;
945 name <<
"GT_PYRAMID(" << k <<
")";
955 struct pyramid_Q2_incomplete_trans_:
public fraction_geometric_trans {
956 pyramid_Q2_incomplete_trans_() {
958 size_type R = cvr->structure()->nb_points();
983 trans[ 0] = mmm0_ * pmmm + base_rational_fraction(mmm0_ * xy, p00m);
984 trans[ 1] = base_rational_fraction(pp0m * pm0m * p0mm * 0.5, p00m);
985 trans[ 2] = mpm0_ * ppmm - base_rational_fraction(mpm0_ * xy, p00m);
986 trans[ 3] = base_rational_fraction(p0pm * p0mm * pm0m * 0.5, p00m);
987 trans[ 4] = base_rational_fraction(p0pm * p0mm * pp0m * 0.5, p00m);
988 trans[ 5] = mmp0_ * pmpm - base_rational_fraction(mmp0_ * xy, p00m);
989 trans[ 6] = base_rational_fraction(pp0m * pm0m * p0pm * 0.5, p00m);
990 trans[ 7] = mpp0_ * pppm + base_rational_fraction(mpp0_ * xy, p00m);
991 trans[ 8] = base_rational_fraction(pm0m * p0mm * z, p00m);
992 trans[ 9] = base_rational_fraction(pp0m * p0mm * z, p00m);
993 trans[10] = base_rational_fraction(pm0m * p0pm * z, p00m);
994 trans[11] = base_rational_fraction(pp0m * p0pm * z, p00m);
997 fill_standard_vertices();
1002 pyramid_Q2_incomplete_gt(gt_param_list& params,
1003 std::vector<dal::pstatic_stored_object> &deps) {
1004 GMM_ASSERT1(params.size() == 0,
"Bad number of parameters : "
1005 << params.size() <<
" should be 0.");
1008 return std::make_shared<pyramid_Q2_incomplete_trans_>();
1022 struct prism_incomplete_P2_trans_:
public poly_geometric_trans {
1023 prism_incomplete_P2_trans_() {
1025 size_type R = cvr->structure()->nb_points();
1031 (
"-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"
1032 "-3*z+2*y^2+4*x*y-3*y+2*x^2-3*x+1;"
1033 "4*(x*y*z+x^2*z-x*z-x*y-x^2+x);"
1034 "2*x*z^2-2*x^2*z-x*z+2*x^2-x;"
1035 "4*(y^2*z+x*y*z-y*z-y^2-x*y+y);"
1037 "2*y*z^2-2*y^2*z-y*z+2*y^2-y;"
1038 "4*(y*z^2+x*z^2-z^2-y*z-x*z+z);"
1041 "-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;"
1042 "4*(-x*y*z-x^2*z+x*z);"
1043 "2*x*z^2+2*x^2*z-3*x*z;"
1044 "4*(-y^2*z-x*y*z+y*z);"
1046 "2*y*z^2+2*y^2*z-3*y*z;");
1048 for (
int i = 0; i < 15; ++i)
1051 fill_standard_vertices();
1056 prism_incomplete_P2_gt(gt_param_list& params,
1057 std::vector<dal::pstatic_stored_object> &deps) {
1058 GMM_ASSERT1(params.size() == 0,
"Bad number of parameters : "
1059 << params.size() <<
" should be 0.");
1062 return std::make_shared<prism_incomplete_P2_trans_>();
1082 GMM_ASSERT1(c.
G().ncols() == c.pgt()->nb_points(),
"dimensions mismatch");
1084 gmm::mult(c.B(), c.pgt()->normals()[face], un);
1095 GMM_ASSERT1(c.
G().ncols() == c.pgt()->nb_points(),
"dimensions mismatch");
1097 size_type P = c.pgt()->structure()->dim();
1099 base_matrix baseP(P, P);
1100 gmm::copy(gmm::identity_matrix(), baseP);
1103 if (gmm::abs(up[i])>gmm::abs(up[i0])) i0=i;
1104 if (i0) gmm::copy(gmm::mat_col(baseP, 0), gmm::mat_col(baseP, i0));
1105 gmm::copy(up, gmm::mat_col(baseP, 0));
1107 base_matrix baseN(c.N(), P);
1108 gmm::mult(c.B(), baseP, baseN);
1113 gmm::add(gmm::scaled(gmm::mat_col(baseN,l),
1114 -gmm::vect_sp(gmm::mat_col(baseN,l),
1115 gmm::mat_col(baseN,k))),
1116 gmm::mat_col(baseN,k));
1118 gmm::scale(gmm::mat_col(baseN,k),
1119 1./gmm::vect_norm2(gmm::mat_col(baseN,k)));
1124 if (c.N() == P && c.N()>1 && gmm::lu_det(baseN) < 0) {
1125 gmm::scale(gmm::mat_col(baseN,1),-1.);
1137 struct geometric_trans_naming_system
1139 geometric_trans_naming_system() :
1140 dal::naming_system<geometric_trans>(
"GT") {
1141 add_suffix(
"PK", PK_gt);
1142 add_suffix(
"QK", QK_gt);
1143 add_suffix(
"PRISM_PK", prism_pk_gt);
1144 add_suffix(
"PRISM", prism_pk_gt);
1145 add_suffix(
"PRODUCT", product_gt);
1146 add_suffix(
"LINEAR_PRODUCT", linear_product_gt);
1147 add_suffix(
"LINEAR_QK", linear_qk);
1148 add_suffix(
"Q2_INCOMPLETE", Q2_incomplete_gt);
1149 add_suffix(
"PYRAMID_QK", pyramid_QK_gt);
1150 add_suffix(
"PYRAMID", pyramid_QK_gt);
1151 add_suffix(
"PYRAMID_Q2_INCOMPLETE", pyramid_Q2_incomplete_gt);
1152 add_suffix(
"PRISM_INCOMPLETE_P2", prism_incomplete_P2_gt);
1156 void add_geometric_trans_name
1165 auto ptrans = name_system.method(name, i);
1167 auto short_name = name_system.shorter_name_of_method(ptrans);
1168 trans.set_name(short_name);
1175 if (pgt_torus)
return instance.shorter_name_of_method(pgt_torus->get_original_transformation());
1176 return instance.shorter_name_of_method(p);
1185 if (d != n || r != k) {
1186 std::stringstream name;
1187 name <<
"GT_PK(" << n <<
"," << k <<
")";
1198 if (d != n || r != k) {
1199 std::stringstream name;
1200 name <<
"GT_QK(" << n <<
"," << k <<
")";
1207 static std::string name_of_linear_qk_trans(
size_type dim) {
1209 case 1:
return "GT_PK(1,1)";
1210 default:
return std::string(
"GT_LINEAR_PRODUCT(")
1211 + name_of_linear_qk_trans(dim-1)
1212 + std::string(
",GT_PK(1,1))");
1220 std::stringstream name(name_of_linear_qk_trans(n));
1231 std::stringstream name;
1232 name <<
"GT_LINEAR_PRODUCT(GT_PK(" << (n-1) <<
", 1), GT_PK(1,1))";
1241 std::stringstream name;
1251 if (d != n || r != k) {
1252 std::stringstream name;
1253 name <<
"GT_PRISM(" << n <<
"," << k <<
")";
1265 if (pg1 != pg1_ || pg2 != pg2_) {
1266 std::stringstream name;
1270 pg1_ = pg1; pg2_ = pg2;
1279 dim_type n = cvs->dim();
1286 return parallelepiped_geotrans(n, 1);
1291 case 1 :
return simplex_geotrans(1,
short_type(nbpt-1));
1296 }
else if (nbf == 4) {
1299 return parallelepiped_geotrans(2, k);
1309 }
else if (nbf == 6) {
1312 return parallelepiped_geotrans(3, k);
1313 }
else if (nbf == 5) {
1321 return pyramid_Q2_incomplete_geotrans();
1325 GMM_ASSERT1(
false,
"Unrecognized structure");
1337 pstored_point_tab ps)
1339 { DAL_STORED_OBJECT_DEBUG_CREATED(
this,
"Geotrans precomp"); }
1341 void geotrans_precomp_::init_val()
const {
1343 c.resize(pspt->size(), base_vector(pgt->nb_points()));
1344 for (
size_type j = 0; j < pspt->size(); ++j)
1345 pgt->poly_vector_val((*pspt)[j], c[j]);
1348 void geotrans_precomp_::init_grad()
const {
1349 dim_type N = pgt->dim();
1351 pc.resize(pspt->size(), base_matrix(pgt->nb_points() , N));
1352 for (
size_type j = 0; j < pspt->size(); ++j)
1353 pgt->poly_vector_grad((*pspt)[j], pc[j]);
1356 void geotrans_precomp_::init_hess()
const {
1358 dim_type N = pgt->structure()->dim();
1360 hpc.resize(pspt->size(), base_matrix(pgt->nb_points(), gmm::sqr(N)));
1361 for (
size_type j = 0; j < pspt->size(); ++j)
1362 pgt->poly_vector_hess((*pspt)[j], hpc[j]);
1365 base_node geotrans_precomp_::transform(
size_type i,
1366 const base_matrix &G)
const {
1367 if (c.empty()) init_val();
1368 size_type N = G.nrows(), k = pgt->nb_points();
1370 base_matrix::const_iterator git = G.begin();
1372 scalar_type a = c[i][l];
1373 base_node::iterator pit = P.begin(), pite = P.end();
1374 for (; pit != pite; ++git, ++pit) *pit += a * (*git);
1380 pstored_point_tab pspt,
1381 dal::pstatic_stored_object dep) {
1382 dal::pstatic_stored_object_key pk= std::make_shared<pre_geot_key_>(pg,pspt);
1384 if (o)
return std::dynamic_pointer_cast<const geotrans_precomp_>(o);
1385 pgeotrans_precomp p = std::make_shared<geotrans_precomp_>(pg, pspt);
1391 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.