GetFEM  5.5
bgeot_poly_composite.cc
1 /*===========================================================================
2 
3  Copyright (C) 2002-2026 Yves Renard
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
21 #include "getfem/dal_singleton.h"
24 
25 namespace bgeot {
26 
27  inline scalar_type sfloor(scalar_type x)
28  { return (x >= 0) ? floor(x) : -floor(-x); }
29 
30 
32  const base_node &y) const {
33  size_type s = x.size();
34  scalar_type c1 = c_max, c2 = c_max * scalar_type(base);
35  GMM_ASSERT2(y.size() == s, "dimension error");
36 
37  base_node::const_iterator itx=x.begin(), itex=x.end(), ity=y.begin();
38  int ret = 0;
39  for (; itx != itex; ++itx, ++ity) {
40  long a = long(sfloor((*itx) * c1)), b = long(sfloor((*ity) * c1));
41  if ((scalar_type(gmm::abs(a)) > scalar_type(base))
42  || (scalar_type(gmm::abs(b)) > scalar_type(base))) {
43  exp_max++; c_max /= scalar_type(base);
44  return (*this)(x,y);
45  }
46  if (ret == 0) { if (a < b) ret = -1; else if (a > b) ret = 1; }
47  }
48  if (ret) return ret;
49 
50  for (int e = exp_max; e >= exp_min; --e, c1 *= scalar_type(base),
51  c2 *= scalar_type(base)) {
52  itx = x.begin(), itex = x.end(), ity = y.begin();
53  for (; itx != itex; ++itx, ++ity) {
54  int a = int(sfloor(((*itx) * c2) - sfloor((*itx) * c1)
55  * scalar_type(base)));
56  int b = int(sfloor(((*ity) * c2) - sfloor((*ity) * c1)
57  * scalar_type(base)));
58  if (a < b) return -1; else if (a > b) return 1;
59  }
60  }
61  return 0;
62  }
63 
64  mesh_precomposite::mesh_precomposite(const basic_mesh &m) : box_tree{1e-13} {
65  initialise(m);
66  }
67 
68  void mesh_precomposite::initialise(const basic_mesh &m) {
69  msh = &m;
70  det.resize(m.nb_convex()); orgs.resize(m.nb_convex());
71  gtrans.resize(m.nb_convex()); gtransinv.resize(m.nb_convex());
72  for (size_type i = 0; i <= m.points().index().last_true(); ++i)
73  vertices.add(m.points()[i]);
74 
75  base_node min, max;
76  for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
77 
78  pgeometric_trans pgt = m.trans_of_convex(cv);
79  size_type N = pgt->structure()->dim();
80  size_type P = m.dim();
81  GMM_ASSERT1(pgt->is_linear(), "Bad geometric transformation");
82 
83  base_matrix G(P, pgt->nb_points());
84  base_node X(N);
85 
86  m.points_of_convex(cv, G);
88  gtrans[cv] = ctx.K();
89  gtransinv[cv] = ctx.B();
90  det[cv] = ctx.J();
91 
92  auto points_of_convex = m.points_of_convex(cv);
93  orgs[cv] = pgt->transform(X, G);
94  bounding_box(min, max, points_of_convex);
95  box_to_convexes_map[box_tree.add_box(min, max)].push_back(cv);
96  }
97 
98  box_tree.build_tree();
99  }
100 
101  DAL_TRIPLE_KEY(base_poly_key, short_type, short_type,
102  std::vector<opt_long_scalar_type>);
103 
104  polynomial_composite::polynomial_composite(const mesh_precomposite &m,
105  bool lc, bool ff)
106  : mp(&m), local_coordinate(lc), faces_first(ff),
107  default_polys(mp->dim()+1) {
108  for (dim_type i = 0; i <= mp->dim(); ++i)
109  default_polys[i] = base_poly(i, 0.);
110  }
111 
112  static void mult_diff_transposed(const base_matrix &M, const base_node &p,
113  const base_node &p1, base_node &p2) {
114  for (dim_type d = 0; d < p2.size(); ++d) {
115  p2[d] = 0;
116  auto col = mat_col(M, d);
117  for (dim_type i = 0; i < p1.size(); ++i)
118  p2[d] += col[i] * (p[i] - p1[i]);
119  }
120  }
121 
122  scalar_type polynomial_composite::eval(const base_node &p,
123  size_type l) const {
124  if (l != size_type(-1)) {
125  if (!local_coordinate) return poly_of_subelt(l).eval(p.begin());
126  base_node p1(gmm::mat_ncols(mp->gtransinv[l]));
127  mult_diff_transposed(mp->gtransinv[l], p, mp->orgs[l], p1);
128  return poly_of_subelt(l).eval(p1.begin());
129  }
130 
131  auto dim = mp->dim();
132  base_node p1_stored, p1, p2(dim);
133  size_type cv_stored(-1);
134 
135  auto &box_tree = mp->box_tree;
136  rtree::pbox_set box_list;
137  box_tree.find_boxes_at_point(p, box_list);
138 
139  while (box_list.size()) {
140  auto pmax_box = *box_list.begin();
141 
142  if (box_list.size() > 1) {
143  auto max_rate = -1.0;
144  for (auto &&pbox : box_list) {
145  auto box_rate = 1.0;
146  for (size_type i = 0; i < dim; ++i) {
147  auto h = pbox->max->at(i) - pbox->min->at(i);
148  if (h > 0) {
149  auto rate = std::min(pbox->max->at(i) - p[i],
150  p[i] - pbox->min->at(i)) / h;
151  box_rate = std::min(rate, box_rate);
152  }
153  }
154  if (box_rate > max_rate) { pmax_box = pbox; max_rate = box_rate; }
155  }
156  }
157 
158  for (auto cv : mp->box_to_convexes_map.at(pmax_box->id)) {
159  dim_type elt_dim = dim_type(gmm::mat_ncols(mp->gtransinv[cv]));
160  p1.resize(elt_dim);
161  mult_diff_transposed(mp->gtransinv[cv], p, mp->orgs[cv], p1);
162  scalar_type ddist(0);
163 
164  if (elt_dim < dim) {
165  p2 = mp->orgs[cv]; gmm::mult_add(mp->gtrans[cv], p1, p2);
166  ddist = gmm::vect_dist2(p2, p);
167  }
168  if (mp->trans_of_convex(cv)->convex_ref()->is_in(p1) < 1E-9
169  && ddist < 1E-9) {
170  if (!faces_first || elt_dim < dim) {
171  scalar_type res = to_scalar(poly_of_subelt(cv).eval(local_coordinate
172  ? p1.begin() : p.begin()));
173  return res;
174  }
175  p1_stored = p1; cv_stored = cv;
176  }
177  }
178 
179  if (box_list.size() == 1) break;
180  box_list.erase(pmax_box);
181  }
182  if (cv_stored != size_type(-1)) {
183  scalar_type res =
184  to_scalar(poly_of_subelt(cv_stored).eval(local_coordinate
185  ? p1_stored.begin(): p.begin()));
186  return res;
187  }
188  GMM_ASSERT1(false, "Element not found in composite polynomial: " << p);
189  }
190 
191 
192  void polynomial_composite::derivative(short_type k) {
193  if (local_coordinate) {
194  dim_type P = mp->dim();
195  base_vector e(P), f(P); e[k] = 1.0;
196  for (size_type ic = 0; ic < mp->nb_convex(); ++ic) {
197  dim_type N = dim_type(gmm::mat_ncols(mp->gtransinv[ic]));
198  f.resize(N);
199  gmm::mult(gmm::transposed(mp->gtransinv[ic]), e, f);
200  base_poly Der(N, 0), Q;
201  if (polytab.find(ic) != polytab.end()) {
202  auto &poly = poly_of_subelt(ic);
203  for (dim_type n = 0; n < N; ++n) {
204  Q = poly;
205  Q.derivative(n);
206  Der += Q * f[n];
207  }
208  if (Der.is_zero()) polytab.erase(ic); else set_poly_of_subelt(ic,Der);
209  }
210  }
211  }
212  else
213  for (size_type ic = 0; ic < mp->nb_convex(); ++ic) {
214  auto poly = poly_of_subelt(ic);
215  poly.derivative(k);
216  if (polytab.find(ic) != polytab.end()) set_poly_of_subelt(ic, poly);
217  }
218  }
219 
220  void polynomial_composite::set_poly_of_subelt(size_type l,
221  const base_poly &poly) {
222  auto poly_key =
223  std::make_shared<base_poly_key>(poly.degree(), poly.dim(), poly);
224  pstored_base_poly o(std::dynamic_pointer_cast<const stored_base_poly>
225  (dal::search_stored_object(poly_key)));
226  if (!o) {
227  o = std::make_shared<stored_base_poly>(poly);
228  dal::add_stored_object(poly_key, o);
229  }
230  polytab[l] = o;
231  }
232 
233  const base_poly &polynomial_composite::poly_of_subelt(size_type l) const {
234  auto it = polytab.find(l);
235  if (it == polytab.end()) {
236  if (local_coordinate)
237  return default_polys[gmm::mat_ncols(mp->gtransinv[l])];
238  else
239  return default_polys[mp->dim()];
240  }
241  return *(it->second);
242  }
243 
244 
245  /* build a regularly refined mesh for a simplex of dimension <= 3.
246  All simplexes have the same orientation as the original simplex.
247  */
248  static void
249  structured_mesh_for_simplex_(pconvex_structure cvs,
250  pgeometric_trans opt_gt,
251  const std::vector<base_node> *opt_gt_pts,
252  short_type k, pbasic_mesh pm) {
253  scalar_type h = 1./k;
254  switch (cvs->dim()) {
255  case 1 :
256  {
257  base_node a(1), b(1);
258  for (short_type i = 0; i < k; ++i) {
259  a[0] = i * h; b[0] = (i+1) * h;
260  if (opt_gt) a = opt_gt->transform(a, *opt_gt_pts);
261  if (opt_gt) b = opt_gt->transform(b, *opt_gt_pts);
262  size_type na = pm->add_point(a);
263  size_type nb = pm->add_point(b);
264  pm->add_segment(na, nb);
265  }
266  }
267  break;
268  case 2 :
269  {
270  base_node A(2),B(2),C(2),D(2);
271  for (short_type i = 0; i < k; ++i) {
272  scalar_type a = i * h, b = (i+1) * h;
273  for (short_type l = 0; l+i < k; ++l) {
274  scalar_type c = l * h, d = (l+1) * h;
275  A[0] = a; A[1] = c;
276  B[0] = b; B[1] = c;
277  C[0] = a; C[1] = d;
278  D[0] = b; D[1] = d;
279  if (opt_gt) {
280  A = opt_gt->transform(A, *opt_gt_pts);
281  B = opt_gt->transform(B, *opt_gt_pts);
282  C = opt_gt->transform(C, *opt_gt_pts);
283  D = opt_gt->transform(D, *opt_gt_pts);
284  }
285  /* add triangle with correct orientation (det [B-A;C-A] > 0) */
286  size_type nA = pm->add_point(A);
287  size_type nB = pm->add_point(B);
288  size_type nC = pm->add_point(C);
289  size_type nD = pm->add_point(D);
290  pm->add_triangle(nA,nB,nC);
291  if (l+i+1 < k)
292  pm->add_triangle(nC,nB,nD);
293  }
294  }
295  }
296  break;
297  case 3 :
298  {
299  /* based on decompositions of small cubes
300  the number of tetrahedrons is k^3
301  */
302  base_node A,B,C,D,E,F,G,H;
303  for (short_type ci = 0; ci < k; ci++) {
304  scalar_type x = ci*h;
305  for (short_type cj = 0; cj < k-ci; cj++) {
306  scalar_type y=cj*h;
307  for (short_type ck = 0; ck < k-ci-cj; ck++) {
308  scalar_type z=ck*h;
309 
310  A = {x, y, z};
311  B = {x+h, y, z};
312  C = {x, y+h, z};
313  D = {x+h, y+h, z};
314  E = {x, y, z+h};
315  F = {x+h, y, z+h};
316  G = {x, y+h, z+h};
317  H = {x+h, y+h, z+h};
318  if (opt_gt) {
319  A = opt_gt->transform(A, *opt_gt_pts);
320  B = opt_gt->transform(B, *opt_gt_pts);
321  C = opt_gt->transform(C, *opt_gt_pts);
322  D = opt_gt->transform(D, *opt_gt_pts);
323  E = opt_gt->transform(E, *opt_gt_pts);
324  F = opt_gt->transform(F, *opt_gt_pts);
325  G = opt_gt->transform(G, *opt_gt_pts);
326  H = opt_gt->transform(H, *opt_gt_pts);
327  }
328  size_type t[8];
329  t[0] = pm->add_point(A);
330  t[1] = pm->add_point(B);
331  t[2] = pm->add_point(C);
332  t[4] = pm->add_point(E);
333  t[3] = t[5] = t[6] = t[7] = size_type(-1);
334  if (k > 1 && ci+cj+ck < k-1) {
335  t[3] = pm->add_point(D);
336  t[5] = pm->add_point(F);
337  t[6] = pm->add_point(G);
338  }
339  if (k > 2 && ci+cj+ck < k-2) {
340  t[7] = pm->add_point(H);
341  }
342  /**
343  Note that the orientation of each tetrahedron is the same
344  (det > 0)
345  */
346  pm->add_tetrahedron(t[0], t[1], t[2], t[4]);
347  if (k > 1 && ci+cj+ck < k-1) {
348  pm->add_tetrahedron(t[1], t[2], t[4], t[5]);
349  pm->add_tetrahedron(t[6], t[4], t[2], t[5]);
350  pm->add_tetrahedron(t[2], t[3], t[5], t[1]);
351  pm->add_tetrahedron(t[2], t[5], t[3], t[6]);
352  }
353  if (k > 2 && ci+cj+ck < k-2) {
354  pm->add_tetrahedron(t[3], t[5], t[7], t[6]);
355  }
356  }
357  }
358  }
359  }
360  break;
361  default :
362  GMM_ASSERT1(false, "Sorry, not implemented for simplices of "
363  "dimension " << int(cvs->dim()));
364  }
365  }
366 
367  static void structured_mesh_for_parallelepiped_
368  (pconvex_structure cvs, pgeometric_trans opt_gt,
369  const std::vector<base_node> *opt_gt_pts, short_type k, pbasic_mesh pm) {
370  scalar_type h = 1./k;
371  size_type n = cvs->dim();
372  size_type pow2n = (size_type(1) << n);
373  size_type powkn = 1; for (size_type i=0; i < n; ++i) powkn *= k;
374  std::vector<size_type> strides(n);
375  size_type nbpts = 1;
376  for (size_type i=0; i < n; ++i) { strides[i] = nbpts; nbpts *= (k+1); }
377  std::vector<short_type> kcnt; kcnt.resize(n+1,0);
378  std::vector<size_type> pids; pids.reserve(nbpts);
379  base_node pt(n);
380  size_type kk;
381  /* insert nodes and fill pids with their numbers */
382  while (kcnt[n] == 0) {
383  for (size_type z = 0; z < n; ++z)
384  pt[z] = h*kcnt[z];
385  if (opt_gt) pt = opt_gt->transform(pt, *opt_gt_pts);
386  pids.push_back(pm->add_point(pt));
387  kk=0;
388  while (kk <= n)
389  { kcnt[kk]++; if (kcnt[kk] == k+1) { kcnt[kk] = 0; kk++; } else break; }
390  }
391 
392  /*
393  insert convexes using node ids stored in 'pids'
394  */
395  std::vector<size_type> ppts(pow2n);
396  kcnt[n] = 0;
397  while (kcnt[n] == 0) {
398  for (kk = 0; kk < pow2n; ++kk) {
399  size_type pos = 0;
400  for (size_type z = 0; z < n; ++z) {
401  pos += kcnt[z]*strides[z];
402  if ((kk & (size_type(1) << z))) pos += strides[z];
403  }
404  ppts[kk] = pids.at(pos);
405  }
406  pm->add_convex(parallelepiped_linear_geotrans(n), ppts.begin());
407  kcnt[(kk = 0)]++;
408  while (kk < n && kcnt[kk] == k) { kcnt[kk] = 0; kcnt[++kk]++; }
409  }
410  }
411 
412  static void
413  structured_mesh_for_convex_(pconvex_structure cvs,
414  pgeometric_trans opt_gt,
415  const std::vector<base_node> *opt_gt_pts,
416  short_type k, pbasic_mesh pm) {
417  size_type nbp = basic_structure(cvs)->nb_points();
418  dim_type n = cvs->dim();
419  /* Identifying simplexes. */
420  if (nbp == size_type(n+1) &&
421  *key_of_stored_object(basic_structure(cvs))
422  ==*key_of_stored_object(simplex_structure(n))) {
423  // smc.pm->write_to_file(cout);
424  structured_mesh_for_simplex_(cvs,opt_gt,opt_gt_pts,k,pm);
425  /* Identifying parallelepipeds. */
426  } else if (nbp == (size_type(1) << n) &&
427  *key_of_stored_object(basic_structure(cvs))
428  == *key_of_stored_object(parallelepiped_structure(n))) {
429  structured_mesh_for_parallelepiped_(cvs,opt_gt,opt_gt_pts,k,pm);
430  } else if (nbp == size_type(2 * n) &&
431  *key_of_stored_object(basic_structure(cvs))
432  == *key_of_stored_object(prism_P1_structure(n))) {
433  GMM_ASSERT1(false, "Sorry, structured_mesh not implemented for prisms.");
434  } else {
435  GMM_ASSERT1(false, "This element is not taken into account. Contact us");
436  }
437  }
438 
439  /* extract the mesh_structure on faces */
440  static void structured_mesh_of_faces_(pconvex_ref cvr, dim_type f,
441  const basic_mesh &m,
442  mesh_structure &facem) {
443  facem.clear();
444  dal::bit_vector on_face;
445  for (size_type i = 0; i < m.nb_max_points(); ++i) {
446  if (m.is_point_valid(i)) {
447  if (gmm::abs(cvr->is_in_face(f, m.points()[i])) < 1e-12)
448  on_face.add(i);
449  }
450  }
451  //cerr << "on_face=" << on_face << endl;
452  for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
453  for (short_type ff=0; ff < m.structure_of_convex(cv)->nb_faces(); ++ff) {
454  mesh_structure::ind_pt_face_ct
455  ipts=m.ind_points_of_face_of_convex(cv,ff);
456  bool allin = true;
457  for (size_type i=0; i < ipts.size(); ++i) if (!on_face[ipts[i]])
458  { allin = false; break; }
459  if (allin) {
460  /* cerr << "ajout de la face " << ff << " du convexe " << cv << ":";
461  for (size_type i=0; i < ipts.size(); ++i)
462  cerr << on_face[ipts[i]] << "/" << ipts[i] << " ";
463  cerr << endl;
464  */
465  facem.add_convex(m.structure_of_convex(cv)->faces_structure()[ff],
466  ipts.begin());
467  }
468  }
469  }
470  }
471 
472  DAL_TRIPLE_KEY(str_mesh_key, pconvex_structure, short_type, bool);
473 
474  struct str_mesh_cv__ : virtual public dal::static_stored_object {
475  pconvex_structure cvs;
476  short_type n;
477  bool simplex_mesh; /* true if the convex has been splited into simplexes,
478  which were refined */
479  std::unique_ptr<basic_mesh> pm;
480  std::vector<std::unique_ptr<mesh_structure>> pfacem; /* array of mesh_structures for faces */
481  dal::bit_vector nodes_on_edges;
482  std::unique_ptr<mesh_precomposite> pmp;
483  str_mesh_cv__(pconvex_structure c, short_type k, bool smesh_) :
484  cvs(c), n(k), simplex_mesh(smesh_)
485  { DAL_STORED_OBJECT_DEBUG_CREATED(this, "cv mesh"); }
486  ~str_mesh_cv__() { DAL_STORED_OBJECT_DEBUG_DESTROYED(this,"cv mesh"); }
487  };
488 
489  typedef std::shared_ptr<const str_mesh_cv__> pstr_mesh_cv__;
490 
491  /**
492  * This function returns a mesh in pm which contains a refinement of the convex
493  * cvr if force_simplexification is false, refined convexes have the same
494  * basic_structure than cvr, if it is set to true, the cvr is decomposed
495  * into simplexes which are then refined.
496  * TODO: move it into another file and separate the pmesh_precomposite part ?
497  **/
498  void structured_mesh_for_convex(pconvex_ref cvr, short_type k,
499  pbasic_mesh &pm, pmesh_precomposite &pmp,
500  bool force_simplexification) {
501  size_type n = cvr->structure()->dim();
502  size_type nbp = basic_structure(cvr->structure())->nb_points();
503 
504  force_simplexification = force_simplexification || (nbp == n+1);
505  dal::pstatic_stored_object_key
506  pk = std::make_shared<str_mesh_key>(basic_structure(cvr->structure()),
507  k, force_simplexification);
508 
509  dal::pstatic_stored_object o = dal::search_stored_object_on_all_threads(pk);
510  pstr_mesh_cv__ psmc;
511  if (o)
512  psmc = std::dynamic_pointer_cast<const str_mesh_cv__>(o);
513  else {
514 
515  auto ppsmc = std::make_shared<str_mesh_cv__>
516  (basic_structure(cvr->structure()), k, force_simplexification);
517  str_mesh_cv__ &smc(*ppsmc);
518  psmc = ppsmc;
519 
520  smc.pm = std::make_unique<basic_mesh>();
521 
522  if (force_simplexification) {
523  // cout << "cvr = " << int(cvr->structure()->dim()) << " : "
524  // << cvr->structure()->nb_points() << endl;
525  const mesh_structure* splx_mesh
526  = basic_convex_ref(cvr)->simplexified_convex();
527  /* splx_mesh is correctly oriented */
528  for (size_type ic=0; ic < splx_mesh->nb_convex(); ++ic) {
529  std::vector<base_node> cvpts(splx_mesh->nb_points_of_convex(ic));
530  pgeometric_trans sgt
531  = simplex_geotrans(cvr->structure()->dim(), 1);
532  for (size_type j=0; j < cvpts.size(); ++j) {
533  size_type ip = splx_mesh->ind_points_of_convex(ic)[j];
534  cvpts[j] = basic_convex_ref(cvr)->points()[ip];
535  //cerr << "cvpts[" << j << "]=" << cvpts[j] << endl;
536  }
537  structured_mesh_for_convex_(splx_mesh->structure_of_convex(ic),
538  sgt, &cvpts, k, smc.pm.get());
539  }
540  } else {
541  structured_mesh_for_convex_(cvr->structure(), 0, 0, k, smc.pm.get());
542  }
543  smc.pfacem.resize(cvr->structure()->nb_faces());
544  for (dim_type f=0; f < cvr->structure()->nb_faces(); ++f) {
545  smc.pfacem[f] = std::make_unique<mesh_structure>();
546  structured_mesh_of_faces_(cvr, f, *(smc.pm), *(smc.pfacem[f]));
547  }
548 
549  smc.pmp = std::make_unique<mesh_precomposite>(*(smc.pm));
550  dal::add_stored_object(pk, psmc, basic_structure(cvr->structure()));
551  }
552  pm = psmc->pm.get();
553  pmp = psmc->pmp.get();
554  }
555 
556  const basic_mesh *
558  pbasic_mesh pm; pmesh_precomposite pmp;
559  structured_mesh_for_convex(cvr, k, pm, pmp, true);
560  return pm;
561  }
562 
563  const std::vector<std::unique_ptr<mesh_structure>>&
565  dal::pstatic_stored_object_key
566  pk = std::make_shared<str_mesh_key>(basic_structure(cvr->structure()),
567  k, true);
568  dal::pstatic_stored_object o = dal::search_stored_object(pk);
569  if (o) {
570  pstr_mesh_cv__ psmc = std::dynamic_pointer_cast<const str_mesh_cv__>(o);
571  return psmc->pfacem;
572  }
573  else GMM_ASSERT1(false,
574  "call refined_simplex_mesh_for_convex first (or fix me)");
575  }
576 
577 } /* end of namespace getfem. */
convenient initialization of vectors via overload of "operator,".
Handle composite polynomials.
the geotrans_interpolation_context structure is passed as the argument of geometric transformation in...
Mesh structure definition.
short_type nb_points_of_convex(size_type ic) const
Return the number of points of convex ic.
size_type nb_convex() const
The total number of convexes in the mesh.
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
const ind_set & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
base class for static stored objects
A simple singleton implementation.
void mult_add(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1790
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2(const V1 &v1, const V2 &v2)
Euclidean distance between two vectors.
Definition: gmm_blas.h:596
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
Basic Geometric Tools.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:72
const basic_mesh * refined_simplex_mesh_for_convex(pconvex_ref cvr, short_type k)
simplexify a convex_ref.
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
void structured_mesh_for_convex(pconvex_ref cvr, short_type k, pbasic_mesh &pm, pmesh_precomposite &pmp, bool force_simplexification)
This function returns a mesh in pm which contains a refinement of the convex cvr if force_simplexific...
pconvex_structure parallelepiped_structure(dim_type nc, dim_type k)
Give a pointer on the structures of a parallelepiped of dimension d.
pconvex_structure prism_P1_structure(dim_type nc)
Give a pointer on the structures of a prism of dimension d.
const std::vector< std::unique_ptr< mesh_structure > > & refined_simplex_mesh_for_convex_faces(pconvex_ref cvr, short_type k)
simplexify the faces of a convex_ref
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
pconvex_structure basic_structure(pconvex_structure cv)
Original structure (if concerned)
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
pconvex_ref basic_convex_ref(pconvex_ref cvr)
return the associated order 1 reference convex.
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
int operator()(const base_node &x, const base_node &y) const
comparaison function