31 std::vector<scalar_type>& __aux1(){
32 DEFINE_STATIC_THREAD_LOCAL(std::vector<scalar_type>, v);
36 std::vector<scalar_type>& __aux2(){
37 DEFINE_STATIC_THREAD_LOCAL(std::vector<scalar_type>, v);
41 std::vector<scalar_type>& __aux3(){
42 DEFINE_STATIC_THREAD_LOCAL(std::vector<scalar_type>, v);
46 std::vector<long>& __ipvt_aux(){
47 DEFINE_STATIC_THREAD_LOCAL(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 scalar_type a18 = 1 / det;
246 GMM_ASSERT1(det != scalar_type(0),
"Non invertible matrix");
247 scalar_type a3 = (A[2]*A[7] - A[1]*A[8]), a6 = (A[1]*A[5] - A[2]*A[4]);
248 scalar_type a4 = (A[0]*A[8] - A[2]*A[6]), a7 = (A[2]*A[3] - A[0]*A[5]);
249 scalar_type a5 = (A[1]*A[6] - A[0]*A[7]), a8 = (A[0]*A[4] - A[1]*A[3]);
250 *A++ = a0 / det; *A++ = a3 / det; *A++ = a6 / det;
251 *A++ = a1 / det; *A++ = a4 / det; *A++ = a7 / det;
252 *A++ = a2 / det; *A++ = a5 / det; *A++ = a8 / det;
258 if (__aux1().size() < NN) __aux1().resize(NN);
259 std::copy(A, A+NN, __aux1().begin());
260 __ipvt_aux().resize(N);
261 size_type info = lu_factor(&(*(__aux1().begin())), __ipvt_aux(), N);
262 if (doassert) GMM_ASSERT1(!info,
"Non invertible matrix, pivot = " 264 if (!info) lu_inverse(&(*(__aux1().begin())), __ipvt_aux(), A, N);
265 return lu_det(&(*(__aux1().begin())), __ipvt_aux(), N);
273 (
const base_matrix &G,
const base_matrix &pc, base_matrix &K)
const {
276 size_type N=gmm::mat_nrows(G), P=gmm::mat_nrows(pc), Q=gmm::mat_ncols(pc);
278 auto itK = K.begin();
280 auto itpc_j = pc.begin() + j*P, itG_b = G.begin();
281 for (
size_type i = 0; i < N; ++i, ++itG_b) {
282 auto itG = itG_b, itpc = itpc_j;
283 register scalar_type a = *(itG) * (*itpc);
285 { itG += N; a += *(itG) * (*++itpc); }
289 }
else gmm::clear(K);
294 if (pspt_) xref_ = (*pspt_)[
ii_];
295 else GMM_ASSERT1(
false,
"Missing xref");
310 GMM_ASSERT1(have_G(),
311 "Convex center can be provided only if matrix G is available");
312 if (!have_cv_center_) {
317 gmm::scale(
cv_center_, scalar_type(1)/scalar_type(nb_pts));
318 have_cv_center_ =
true;
323 void geotrans_interpolation_context::compute_J()
const {
324 GMM_ASSERT1(have_G() && have_pgt(),
"Unable to compute J\n");
326 const base_matrix &KK =
K();
328 B_factors.base_resize(P, P);
329 gmm::mult(gmm::transposed(KK), KK, B_factors);
331 J__ =
J_ =::sqrt(gmm::abs(bgeot::lu_inverse(&(*(B_factors.begin())), P)));
333 auto it = &(*(KK.begin()));
335 case 1: J__ = *it;
break;
336 case 2: J__ = (*it) * (it[3]) - (it[1]) * (it[2]);
break;
339 B_.base_resize(P, P);
340 auto itB = B_.begin();
341 scalar_type a0 = itB[0] = it[4]*it[8] - it[5]*it[7];
342 scalar_type a1 = itB[1] = it[5]*it[6] - it[3]*it[8];
343 scalar_type a2 = itB[2] = it[3]*it[7] - it[4]*it[6];
344 J__ = it[0] * a0 + it[1] * a1 + it[2] * a2;
347 B_factors.base_resize(P, P);
348 gmm::copy(gmm::transposed(KK), B_factors);
350 bgeot::lu_factor(&(*(B_factors.begin())), ipvt, P);
351 J__ = bgeot::lu_det(&(*(B_factors.begin())), ipvt, P);
361 GMM_ASSERT1(have_G() && have_pgt(),
"Unable to compute K\n");
363 K_.base_resize(N(), P);
367 PC.base_resize(
pgt_->nb_points(), P);
376 const base_matrix& geotrans_interpolation_context::B()
const {
378 const base_matrix &KK =
K();
379 size_type P =
pgt_->structure()->dim(), N_ = gmm::mat_nrows(KK);
380 B_.base_resize(N_, P);
381 if (!have_J_) compute_J();
382 GMM_ASSERT1(J__ != scalar_type(0),
"Non invertible matrix");
384 gmm::mult(KK, B_factors, B_);
387 case 1: B_(0, 0) = scalar_type(1) / J__;
break;
390 auto it = &(*(KK.begin()));
auto itB = &(*(B_.begin()));
391 *itB++ = it[3] / J__; *itB++ = -it[2] / J__;
392 *itB++ = -it[1] / J__; *itB = (*it) / 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);
438 gmm::mult(
G(), pgp_->hessian(
ii_), Htau);
441 PC.base_resize(pgt()->nb_points(), P*P);
442 pgt()->poly_vector_hess(
xref(),
PC);
443 gmm::mult(
G(),
PC, Htau);
449 B2(i + P*j, k) += Htau(l, i + P*j) * BB(l,k);
450 gmm::mult(B3(), B2, B32_);
451 }
else gmm::clear(B32_);
459 if (
pgt_ && !pgt()->is_linear())
460 { have_K_ = have_B_ = have_B3_ = have_B32_ = have_J_ =
false; }
466 const base_matrix &G)
const {
467 size_type N = G.nrows(), k = nb_points();
469 poly_vector_val(pt, val);
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() {
481 for (
size_type ip = 0; ip < nb_points(); ++ip) {
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>
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 auto guard = getfem::omp_guard{};
509 if (grad_computed_)
return;
515 for (dim_type j = 0; j < n; ++j) {
516 grad_[i][j] = trans[i]; grad_[i][j].derivative(j);
519 grad_computed_ =
true;
522 void compute_hess_()
const {
523 auto guard = getfem::omp_guard{};
524 if (hess_computed_)
return;
529 hess_[i].resize(n*n);
530 for (dim_type j = 0; j < n; ++j) {
531 for (dim_type k = 0; k < n; ++k) {
532 hess_[i][j+k*n] = trans[i];
533 hess_[i][j+k*n].derivative(j); hess_[i][j+k*n].derivative(k);
537 hess_computed_ =
true;
540 virtual void poly_vector_val(
const base_node &pt, base_vector &val)
const {
541 val.resize(nb_points());
542 for (
size_type k = 0; k < nb_points(); ++k)
543 val[k] = to_scalar(trans[k].eval(pt.begin()));
546 virtual void poly_vector_val(
const base_node &pt,
547 const convex_ind_ct &ind_ct,
548 base_vector &val)
const {
550 val.resize(nb_funcs);
552 val[k] = to_scalar(trans[ind_ct[k]].eval(pt.begin()));
555 virtual void poly_vector_grad(
const base_node &pt, base_matrix &pc)
const {
556 if (!grad_computed_) compute_grad_();
558 pc.base_resize(nb_points(),dim());
559 for (
size_type i = 0; i < nb_points(); ++i)
560 for (dim_type n = 0; n < dim(); ++n)
561 pc(i, n) = to_scalar(grad_[i][n].eval(pt.begin()));
564 virtual void poly_vector_grad(
const base_node &pt,
565 const convex_ind_ct &ind_ct,
566 base_matrix &pc)
const {
567 if (!grad_computed_) compute_grad_();
570 pc.base_resize(nb_funcs,dim());
572 for (dim_type n = 0; n < dim(); ++n)
573 pc(i, n) = to_scalar(grad_[ind_ct[i]][n].eval(pt.begin()));
576 virtual void poly_vector_hess(
const base_node &pt, base_matrix &pc)
const {
577 if (!hess_computed_) compute_hess_();
579 pc.base_resize(nb_points(),dim()*dim());
580 for (
size_type i = 0; i < nb_points(); ++i)
581 for (dim_type n = 0; n < dim(); ++n) {
582 for (dim_type m = 0; m <= n; ++m)
583 pc(i, n*dim()+m) = pc(i, m*dim()+n) =
584 to_scalar(hess_[i][m*dim()+n].eval(pt.begin()));
590 typedef igeometric_trans<base_poly> poly_geometric_trans;
591 typedef igeometric_trans<polynomial_composite> comppoly_geometric_trans;
592 typedef igeometric_trans<base_rational_fraction> fraction_geometric_trans;
598 struct simplex_trans_ :
public poly_geometric_trans {
603 l0.one(); l1.
one(); p = l0;
607 for (
int nn = 1; nn <= N; ++nn) {
608 w[nn]=
short_type(floor(0.5+(((cvr->points())[i])[nn-1]*double(K))));
615 p *= (l0 * (scalar_type(K) / scalar_type(j+1)))
616 - (l1 * (scalar_type(j) / scalar_type(j+1)));
619 - (l1 * (scalar_type(j) / scalar_type(j+1)));
624 size_type R = cvr->structure()->nb_points();
628 for (
size_type r = 0; r < R; ++r) calc_base_func(trans[r], r, k);
629 fill_standard_vertices();
634 PK_gt(gt_param_list ¶ms,
635 std::vector<dal::pstatic_stored_object> &dependencies) {
636 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 637 << params.size() <<
" should be 2.");
638 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
639 "Bad type of parameters");
640 int n = int(::floor(params[0].num() + 0.01));
641 int k = int(::floor(params[1].num() + 0.01));
642 GMM_ASSERT1(n >= 0 && n < 100 && k >= 0 && k <= 150 &&
643 double(n) == params[0].num() &&
double(k) == params[1].num(),
646 return std::make_shared<simplex_trans_>(dim_type(n), dim_type(k));
653 struct cv_pr_t_ :
public poly_geometric_trans {
654 cv_pr_t_(
const poly_geometric_trans *a,
const poly_geometric_trans *b) {
657 complexity_ = a->complexity() * b->complexity();
659 size_type n1 = a->nb_points(), n2 = b->nb_points();
660 trans.resize(n1 * n2);
663 trans[i1 + i2 * n1] = a->trans[i1];
664 trans[i1 + i2 * n1].direct_product(b->trans[i2]);
666 for (
size_type i2 = 0; i2 < b->nb_vertices(); ++i2)
667 for (
size_type i1 = 0; i1 < a->nb_vertices(); ++i1)
668 vertices_.push_back(a->vertices()[i1] + b->vertices()[i2] * n1);
673 std::vector<dal::pstatic_stored_object> &dependencies) {
674 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 675 << params.size() <<
" should be 2.");
676 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
677 "Bad type of parameters");
680 dependencies.push_back(a); dependencies.push_back(b);
683 const poly_geometric_trans *aa
684 =
dynamic_cast<const poly_geometric_trans *
>(a.get());
685 const poly_geometric_trans *bb
686 =
dynamic_cast<const poly_geometric_trans *
>(b.get());
687 GMM_ASSERT1(aa && bb,
"The product of geometric transformations " 688 "is only defined for polynomial ones");
689 return std::make_shared<cv_pr_t_>(aa, bb);
696 struct cv_pr_tl_ :
public poly_geometric_trans {
697 cv_pr_tl_(
const poly_geometric_trans *a,
const poly_geometric_trans *b) {
698 GMM_ASSERT1(a->is_linear() && b->is_linear(),
699 "linear product of non-linear transformations");
702 complexity_ = std::max(a->complexity(), b->complexity());
704 trans.resize(a->nb_points() * b->nb_points());
705 std::fill(trans.begin(), trans.end(), null_poly(dim()));
707 std::stringstream name;
708 name <<
"GT_PK(" << int(dim()) <<
",1)";
710 const poly_geometric_trans *pgt
711 =
dynamic_cast<const poly_geometric_trans *
>(pgt_.get());
714 trans[cvr->structure()->ind_dir_points()[i]]
716 for (
size_type i2 = 0; i2 < b->nb_vertices(); ++i2)
717 for (
size_type i1 = 0; i1 < a->nb_vertices(); ++i1)
718 vertices_.push_back(a->vertices()[i1]
719 + b->vertices()[i2] * a->nb_points());
724 std::vector<dal::pstatic_stored_object> &dependencies) {
725 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 726 << params.size() <<
" should be 2.");
727 GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
728 "Bad type of parameters");
731 dependencies.push_back(a); dependencies.push_back(b);
734 const poly_geometric_trans *aa
735 =
dynamic_cast<const poly_geometric_trans *
>(a.get());
736 const poly_geometric_trans *bb
737 =
dynamic_cast<const poly_geometric_trans *
>(b.get());
738 GMM_ASSERT1(aa && bb,
"The product of geometric transformations " 739 "is only defined for polynomial ones");
740 return std::make_shared<cv_pr_tl_>(aa, bb);
748 std::vector<dal::pstatic_stored_object> &) {
749 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 750 << params.size() <<
" should be 2.");
751 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
752 "Bad type of parameters");
753 int n = int(::floor(params[0].num() + 0.01));
754 int k = int(::floor(params[1].num() + 0.01));
755 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
756 double(n) == params[0].num() &&
double(k) == params[1].num(),
758 std::stringstream name;
760 name <<
"GT_PK(1," << k <<
")";
762 name <<
"GT_PRODUCT(GT_QK(" << n-1 <<
"," << k <<
"),GT_PK(1," 768 prism_pk_gt(gt_param_list ¶ms,
769 std::vector<dal::pstatic_stored_object> &) {
770 GMM_ASSERT1(params.size() == 2,
"Bad number of parameters : " 771 << params.size() <<
" should be 2.");
772 GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
773 "Bad type of parameters");
774 int n = int(::floor(params[0].num() + 0.01));
775 int k = int(::floor(params[1].num() + 0.01));
776 GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
777 double(n) == params[0].num() &&
double(k) == params[1].num(),
779 std::stringstream name;
780 name <<
"GT_PRODUCT(GT_PK(" << n-1 <<
"," << k <<
"),GT_PK(1," 786 linear_qk(gt_param_list ¶ms,
787 std::vector<dal::pstatic_stored_object> &) {
788 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : " 789 << params.size() <<
" should be 1.");
790 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
791 int n = int(::floor(params[0].num() + 0.01));
792 return parallelepiped_linear_geotrans(n);
801 struct Q2_incomplete_trans_:
public poly_geometric_trans {
802 Q2_incomplete_trans_(dim_type nc) {
804 size_type R = cvr->structure()->nb_points();
811 (
"1 - 2*x^2*y - 2*x*y^2 + 2*x^2 + 5*x*y + 2*y^2 - 3*x - 3*y;" 812 "4*(x^2*y - x^2 - x*y + x);" 813 "2*x*y*y - 2*x*x*y + 2*x*x - x*y - x;" 814 "4*(x*y*y - x*y - y*y + y);" 816 "2*x*x*y - 2*x*y*y - x*y + 2*y*y - y;" 818 "2*x*x*y + 2*x*y*y - 3*x*y;");
820 for (
int i = 0; i < 8; ++i)
824 (
"1 + 2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2" 825 " - 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" 826 " + 2*x^2 + 2*y^2 + 2*z^2 + 5*y*z + 5*x*z + 5*x*y - 3*x - 3*y - 3*z;" 827 "4*( - x^2*y*z + x*y*z + x^2*z - x*z + x^2*y - x*y - x^2 + x);" 828 "2*x^2*y*z - 2*x*y^2*z - 2*x*y*z^2" 829 " - 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;" 830 "4*( - x*y^2*z + x*y^2 + y^2*z + x*y*z - x*y - y^2 - y*z + y);" 831 "4*(x*y^2*z - x*y^2 - x*y*z + x*y);" 832 " - 2*x^2*y*z + 2*x*y^2*z - 2*x*y*z^2" 833 " + 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;" 834 "4*(x^2*y*z - x^2*y - x*y*z + x*y);" 835 " - 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;" 836 "4*( - x*y*z^2 + x*z^2 + y*z^2 + x*y*z - x*z - y*z - z^2 + z);" 837 "4*(x*y*z^2 - x*y*z - x*z^2 + x*z);" 838 "4*(x*y*z^2 - x*y*z - y*z^2 + y*z);" 839 "4*( - x*y*z^2 + x*y*z);" 840 " - 2*x^2*y*z - 2*x*y^2*z + 2*x*y*z^2" 841 " + 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;" 842 "4*(x^2*y*z - x^2*z - x*y*z + x*z);" 843 " - 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;" 844 "4*(x*y^2*z - y^2*z - x*y*z + y*z);" 845 "4*( - x*y^2*z + x*y*z);" 846 "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;" 847 "4*( - x^2*y*z + x*y*z);" 848 "2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2 - 5*x*y*z;");
850 for (
int i = 0; i < 20; ++i)
853 fill_standard_vertices();
858 Q2_incomplete_gt(gt_param_list& params,
859 std::vector<dal::pstatic_stored_object> &dependencies) {
860 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : " 861 << params.size() <<
" should be 1.");
862 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
863 int n = int(::floor(params[0].num() + 0.01));
864 GMM_ASSERT1(n == 2 || n == 3,
"Bad parameter, expected value 2 or 3");
867 return std::make_shared<Q2_incomplete_trans_>(dim_type(n));
871 std::stringstream name;
872 name <<
"GT_Q2_INCOMPLETE(" << nc <<
")";
880 struct pyramid_QK_trans_:
public fraction_geometric_trans {
883 size_type R = cvr->structure()->nb_points();
907 trans[ 0] = Q*Q*xi0*xi1*(x*y-z*un_z);
908 trans[ 1] = Q*Q*xi0*xi1*xi2*(xi1*2.-un_z)*4.;
909 trans[ 2] = Q*Q*xi1*xi2*(-x*y-z*un_z);
910 trans[ 3] = Q*Q*xi3*xi0*xi1*(xi0*2.-un_z)*4.;
911 trans[ 4] = Q*Q*xi0*xi1*xi2*xi3*16.;
912 trans[ 5] = Q*Q*xi1*xi2*xi3*(xi2*2.-un_z)*4.;
913 trans[ 6] = Q*Q*xi3*xi0*(-x*y-z*un_z);
914 trans[ 7] = Q*Q*xi2*xi3*xi0*(xi3*2.-un_z)*4.;
915 trans[ 8] = Q*Q*xi2*xi3*(x*y-z*un_z);
916 trans[ 9] = Q*z*xi0*xi1*4.;
917 trans[10] = Q*z*xi1*xi2*4.;
918 trans[11] = Q*z*xi3*xi0*4.;
919 trans[12] = Q*z*xi2*xi3*4.;
922 fill_standard_vertices();
927 pyramid_QK_gt(gt_param_list& params,
928 std::vector<dal::pstatic_stored_object> &deps) {
929 GMM_ASSERT1(params.size() == 1,
"Bad number of parameters : " 930 << params.size() <<
" should be 1.");
931 GMM_ASSERT1(params[0].type() == 0,
"Bad type of parameters");
932 int k = int(::floor(params[0].num() + 0.01));
935 return std::make_shared<pyramid_QK_trans_>(dim_type(k));
942 std::stringstream name;
943 name <<
"GT_PYRAMID(" << k <<
")";
953 struct pyramid_Q2_incomplete_trans_:
public fraction_geometric_trans {
954 pyramid_Q2_incomplete_trans_() {
956 size_type R = cvr->structure()->nb_points();
981 trans[ 0] = mmm0_ * pmmm + base_rational_fraction(mmm0_ * xy, p00m);
982 trans[ 1] = base_rational_fraction(pp0m * pm0m * p0mm * 0.5, p00m);
983 trans[ 2] = mpm0_ * ppmm - base_rational_fraction(mpm0_ * xy, p00m);
984 trans[ 3] = base_rational_fraction(p0pm * p0mm * pm0m * 0.5, p00m);
985 trans[ 4] = base_rational_fraction(p0pm * p0mm * pp0m * 0.5, p00m);
986 trans[ 5] = mmp0_ * pmpm - base_rational_fraction(mmp0_ * xy, p00m);
987 trans[ 6] = base_rational_fraction(pp0m * pm0m * p0pm * 0.5, p00m);
988 trans[ 7] = mpp0_ * pppm + base_rational_fraction(mpp0_ * xy, p00m);
989 trans[ 8] = base_rational_fraction(pm0m * p0mm * z, p00m);
990 trans[ 9] = base_rational_fraction(pp0m * p0mm * z, p00m);
991 trans[10] = base_rational_fraction(pm0m * p0pm * z, p00m);
992 trans[11] = base_rational_fraction(pp0m * p0pm * z, p00m);
995 fill_standard_vertices();
1000 pyramid_Q2_incomplete_gt(gt_param_list& params,
1001 std::vector<dal::pstatic_stored_object> &deps) {
1002 GMM_ASSERT1(params.size() == 0,
"Bad number of parameters : " 1003 << params.size() <<
" should be 0.");
1006 return std::make_shared<pyramid_Q2_incomplete_trans_>();
1020 struct prism_incomplete_P2_trans_:
public poly_geometric_trans {
1021 prism_incomplete_P2_trans_() {
1023 size_type R = cvr->structure()->nb_points();
1029 (
"-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" 1030 "-3*z+2*y^2+4*x*y-3*y+2*x^2-3*x+1;" 1031 "4*(x*y*z+x^2*z-x*z-x*y-x^2+x);" 1032 "2*x*z^2-2*x^2*z-x*z+2*x^2-x;" 1033 "4*(y^2*z+x*y*z-y*z-y^2-x*y+y);" 1035 "2*y*z^2-2*y^2*z-y*z+2*y^2-y;" 1036 "4*(y*z^2+x*z^2-z^2-y*z-x*z+z);" 1039 "-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;" 1040 "4*(-x*y*z-x^2*z+x*z);" 1041 "2*x*z^2+2*x^2*z-3*x*z;" 1042 "4*(-y^2*z-x*y*z+y*z);" 1044 "2*y*z^2+2*y^2*z-3*y*z;");
1046 for (
int i = 0; i < 15; ++i)
1049 fill_standard_vertices();
1054 prism_incomplete_P2_gt(gt_param_list& params,
1055 std::vector<dal::pstatic_stored_object> &deps) {
1056 GMM_ASSERT1(params.size() == 0,
"Bad number of parameters : " 1057 << params.size() <<
" should be 0.");
1060 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() :
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
1170 if (pgt_torus)
return instance.shorter_name_of_method(pgt_torus->get_original_transformation());
1171 return instance.shorter_name_of_method(p);
1180 if (d != n || r != k) {
1181 std::stringstream name;
1182 name <<
"GT_PK(" << n <<
"," << k <<
")";
1193 if (d != n || r != k) {
1194 std::stringstream name;
1195 name <<
"GT_QK(" << n <<
"," << k <<
")";
1202 static std::string name_of_linear_qk_trans(
size_type dim) {
1204 case 1:
return "GT_PK(1,1)";
1205 default:
return std::string(
"GT_LINEAR_PRODUCT(")
1206 + name_of_linear_qk_trans(dim-1)
1207 + std::string(
",GT_PK(1,1))");
1215 std::stringstream name(name_of_linear_qk_trans(n));
1226 std::stringstream name;
1227 name <<
"GT_LINEAR_PRODUCT(GT_PK(" << (n-1) <<
", 1), GT_PK(1,1))";
1236 std::stringstream name;
1246 if (d != n || r != k) {
1247 std::stringstream name;
1248 name <<
"GT_PRISM(" << n <<
"," << k <<
")";
1260 if (pg1 != pg1_ || pg2 != pg2_) {
1261 std::stringstream name;
1265 pg1_ = pg1; pg2_ = pg2;
1277 pstored_point_tab ps)
1279 { DAL_STORED_OBJECT_DEBUG_CREATED(
this,
"Geotrans precomp"); }
1281 void geotrans_precomp_::init_val()
const {
1283 c.resize(pspt->size(), base_vector(pgt->nb_points()));
1284 for (
size_type j = 0; j < pspt->size(); ++j)
1285 pgt->poly_vector_val((*pspt)[j], c[j]);
1288 void geotrans_precomp_::init_grad()
const {
1289 dim_type N = pgt->dim();
1291 pc.resize(pspt->size(), base_matrix(pgt->nb_points() , N));
1292 for (
size_type j = 0; j < pspt->size(); ++j)
1293 pgt->poly_vector_grad((*pspt)[j], pc[j]);
1296 void geotrans_precomp_::init_hess()
const {
1298 dim_type N = pgt->structure()->
dim();
1300 hpc.resize(pspt->size(), base_matrix(pgt->nb_points(), gmm::sqr(N)));
1301 for (
size_type j = 0; j < pspt->size(); ++j)
1302 pgt->poly_vector_hess((*pspt)[j], hpc[j]);
1306 const base_matrix &G)
const {
1307 if (c.empty()) init_val();
1308 size_type N = G.nrows(), k = pgt->nb_points();
1310 base_matrix::const_iterator git = G.begin();
1312 scalar_type a = c[i][l];
1313 base_node::iterator pit = P.begin(), pite = P.end();
1314 for (; pit != pite; ++git, ++pit) *pit += a * (*git);
1320 pstored_point_tab pspt,
1321 dal::pstatic_stored_object dep) {
1322 dal::pstatic_stored_object_key pk= std::make_shared<pre_geot_key_>(pg,pspt);
1325 pgeotrans_precomp p = std::make_shared<geotrans_precomp_>(pg, pspt);
1331 void delete_geotrans_precomp(pgeotrans_precomp pgp)
base_matrix compute_local_basis(const geotrans_interpolation_context &c, size_type face)
return the local basis (i.e.
const base_matrix * G_
transformed point
Geometric transformations on convexes.
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
scalar_type J_
index of current point in the pgp
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)
Handle composite polynomials.
Description of a geometric transformation between a reference element and a real element.
pgeometric_trans pgt_
see documentation (getfem kernel doc) for more details
the geotrans_interpolation_context structure is passed as the argument of geometric transformation in...
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
pgeometric_trans geometric_trans_descriptor(std::string name)
Get the geometric transformation from its string name.
pconvex_ref Q2_incomplete_of_reference(dim_type nc)
incomplete Q2 quadrilateral/hexahedral of reference of dimension d = 2 or 3
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...
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
const base_node & cv_center() const
coordinates of the center of the real convex.
const base_node & xreal() const
coordinates of the current point, in the real convex.
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.
Associate a name to a method descriptor and store method descriptors.
size_t size_type
used as the common size type in the library
precomputed geometric transformation operations use this for repetitive evaluation of a geometric tra...
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
Vector of integer (16 bits type) which represent the powers of a monomial.
A simple singleton implementation.
base_node cv_center_
pointer to the matrix of real nodes of the convex
a balanced tree stored in a dal::dynamic_array
size_type ii_
if pgp != 0, it is the same as pgp's one
pconvex_ref prism_incomplete_P2_of_reference()
incomplete quadratic prism element of reference (15-node)
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
base_matrix K_
real center of convex (average of columns of G)
short_type dim() const
Gives the dimension (number of variables)
void clear(L &l)
clear (fill with zeros) a vector or matrix.
gmm::uint16_type short_type
used as the common short type integer in the library
std::string name_of_geometric_trans(pgeometric_trans p)
Get the string name of a geometric transformation.
const base_node & xref() const
coordinates of the current point, in the reference convex.
base_node xreal_
reference point
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...
pconvex_ref pyramid_Q2_incomplete_of_reference()
incomplete quadratic pyramidal element of reference (13-node)
void transform(const CONT &G, stored_point_tab &pt_tab) const
Apply the geometric transformation from the reference convex to the convex whose vertices are stored ...
const base_matrix & G() const
matrix whose columns are the vertices of the convex
const base_matrix & K() const
See getfem kernel doc for these matrices.
void set_xref(const base_node &P)
change the current point (coordinates given in the reference convex)
An adaptor that adapts a two dimensional geometric_trans to include radial dimension.
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