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