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