GetFEM++  5.3
bgeot_convex_ref.cc
1 /*===========================================================================
2 
3  Copyright (C) 2001-2017 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, write to the Free Software Foundation,
18  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ===========================================================================*/
21 
22 #include "getfem/dal_singleton.h"
26 
27 namespace bgeot {
28 
29  // ******************************************************************
30  // Interface with qhull
31  // ******************************************************************
32 
33 # ifndef GETFEM_HAVE_LIBQHULL_QHULL_A_H
34  void qhull_delaunay(const std::vector<base_node> &,
35  gmm::dense_matrix<size_type>&) {
36  GMM_ASSERT1(false, "Qhull header files not installed. "
37  "Install qhull library and reinstall GetFEM++ library.");
38  }
39 # else
40 
41  extern "C" {
42  // #ifdef _MSC_VER
43 # include <libqhull/qhull_a.h>
44  // #else
45  // # include <qhull/qhull.h>
46  // # include <qhull/mem.h>
47  // # include <qhull/qset.h>
48  // # include <qhull/geom.h>
49  // # include <qhull/merge.h>
50  // # include <qhull/poly.h>
51  // # include <qhull/io.h>
52  // # include <qhull/stat.h>
53  // #endif
54  }
55 
56  void qhull_delaunay(const std::vector<base_node> &pts,
57  gmm::dense_matrix<size_type>& simplexes) {
58  // cout << "running delaunay with " << pts.size() << " points\n";
59  size_type dim = pts[0].size(); /* points dimension. */
60  if (pts.size() <= dim) { gmm::resize(simplexes, dim+1, 0); return; }
61  if (pts.size() == dim+1) {
62  gmm::resize(simplexes, dim+1, 1);
63  for (size_type i=0; i <= dim; ++i) simplexes(i, 0) = i;
64  return;
65  }
66  std::vector<coordT> Pts(dim * pts.size());
67  for (size_type i=0; i < pts.size(); ++i)
68  gmm::copy(pts[i], gmm::sub_vector(Pts, gmm::sub_interval(i*dim, dim)));
69  boolT ismalloc=0; /* True if qhull should free points in
70  * qh_freeqhull() or reallocation */
71  /* Be Aware: option QJ could destabilizate all, it can break everything. */
72  /* option Qbb -> QbB (????) */
73  /* option flags for qhull, see qh_opt.htm */
74  char flags[]= "qhull QJ d Qbb Pp T0"; //QJ s i TO";//"qhull Tv";
75  FILE *outfile= 0; /* output from qh_produce_output()
76  * use NULL to skip qh_produce_output() */
77  FILE *errfile= stderr; /* error messages from qhull code */
78  int exitcode; /* 0 if no error from qhull */
79  facetT *facet; /* set by FORALLfacets */
80  int curlong, totlong; /* memory remaining after qh_memfreeshort */
81  vertexT *vertex, **vertexp;
82  exitcode = qh_new_qhull (int(dim), int(pts.size()), &Pts[0], ismalloc,
83  flags, outfile, errfile);
84  if (!exitcode) { /* if no error */
85  size_type nbf=0;
86  FORALLfacets { if (!facet->upperdelaunay) nbf++; }
87  gmm::resize(simplexes, dim+1, nbf);
88  /* 'qh facet_list' contains the convex hull */
89  nbf=0;
90  FORALLfacets {
91  if (!facet->upperdelaunay) {
92  size_type s=0;
93  FOREACHvertex_(facet->vertices) {
94  assert(s < (unsigned)(dim+1));
95  simplexes(s++,nbf) = qh_pointid(vertex->point);
96  }
97  nbf++;
98  }
99  }
100  }
101  qh_freeqhull(!qh_ALL);
102  qh_memfreeshort (&curlong, &totlong);
103  if (curlong || totlong)
104  cerr << "qhull internal warning (main): did not free " << totlong <<
105  " bytes of long memory (" << curlong << " pieces)\n";
106 
107  }
108 
109 #endif
110 
111 
112 
113  size_type simplexified_tab(pconvex_structure cvs, size_type **tab);
114 
115  static void simplexify_convex(bgeot::convex_of_reference *cvr,
116  mesh_structure &m) {
117  pconvex_structure cvs = cvr->structure();
118  m.clear();
119  auto basic_cvs = basic_structure(cvs);
120  dim_type n = basic_cvs->dim();
121  std::vector<size_type> ipts(n+1);
122  if (basic_cvs->nb_points() == n + 1) {
123  for (size_type i = 0; i <= n; ++i) ipts[i] = i;
124  m.add_simplex(n, ipts.begin());
125  }
126  else {
127  size_type *tab;
128  size_type nb = simplexified_tab(basic_cvs, &tab);
129  if (nb) {
130  for (size_type nc = 0; nc < nb; ++nc) {
131  for (size_type i = 0; i <= n; ++i) ipts[i] = *tab++;
132  m.add_simplex(n, ipts.begin());
133  }
134  } else {
135 # ifdef GETFEM_HAVE_LIBQHULL_QHULL_A_H
136  gmm::dense_matrix<size_type> t;
137  qhull_delaunay(cvr->points(), t);
138  for (size_type nc = 0; nc < gmm::mat_ncols(t); ++nc) {
139  for (size_type i = 0; i <= n; ++i) ipts[i] = t(i,nc);
140  m.add_simplex(n, ipts.begin());
141  }
142 # endif
143  }
144  }
145  }
146 
147  /* ********************************************************************* */
148  /* Point tab storage. */
149  /* ********************************************************************* */
150 
151  struct stored_point_tab_key : virtual public dal::static_stored_object_key {
152  const stored_point_tab *pspt;
153  virtual bool compare(const static_stored_object_key &oo) const {
154  const stored_point_tab_key &o
155  = dynamic_cast<const stored_point_tab_key &>(oo);
156  const stored_point_tab &x = *pspt;
157  const stored_point_tab &y = *(o.pspt);
158  if (&x == &y) return false;
159  std::vector<base_node>::const_iterator it1 = x.begin(), it2 = y.begin();
160  base_node::const_iterator itn1, itn2, itne;
161  for ( ; it1 != x.end() && it2 != y.end() ; ++it1, ++it2) {
162  if ((*it1).size() < (*it2).size()) return true;
163  if ((*it1).size() > (*it2).size()) return false;
164  itn1 = (*it1).begin(); itne = (*it1).end(); itn2 = (*it2).begin();
165  for ( ; itn1 != itne ; ++itn1, ++itn2)
166  if (*itn1 < *itn2) return true;
167  else if (*itn1 > *itn2) return false;
168  }
169  if (it2 != y.end()) return true;
170  return false;
171  }
172  stored_point_tab_key(const stored_point_tab *p) : pspt(p) {}
173  };
174 
175 
176  pstored_point_tab store_point_tab(const stored_point_tab &spt) {
177  dal::pstatic_stored_object_key
178  pk = std::make_shared<stored_point_tab_key>(&spt);
179  dal::pstatic_stored_object o = dal::search_stored_object(pk);
180  if (o) return std::dynamic_pointer_cast<const stored_point_tab>(o);
181  pstored_point_tab p = std::make_shared<stored_point_tab>(spt);
182  DAL_STORED_OBJECT_DEBUG_CREATED(p.get(), "Stored point tab");
183  dal::pstatic_stored_object_key
184  psp = std::make_shared<stored_point_tab_key>(p.get());
185  dal::add_stored_object(psp, p, dal::AUTODELETE_STATIC_OBJECT);
186  return p;
187  }
188 
189  convex_of_reference::convex_of_reference
190  (pconvex_structure cvs_, bool auto_basic_) :
191  convex<base_node>(move(cvs_)), basic_convex_ref_(0),
192  auto_basic(auto_basic_) {
193  DAL_STORED_OBJECT_DEBUG_CREATED(this, "convex of refrence");
194  psimplexified_convex = std::make_shared<mesh_structure>();
195  // dal::singleton<cleanup_simplexified_convexes>::instance()
196  // .push_back(psimplexified_convex);
197  }
198 
199  bool convex_of_reference::is_basic() const {
200  return auto_basic;
201  }
202 
203  /* should be called on the basic_convex_ref */
205  GMM_ASSERT1(auto_basic,
206  "always use simplexified_convex on the basic_convex_ref() "
207  "[this=" << nb_points() << ", basic="
208  << basic_convex_ref_->nb_points());
209  return psimplexified_convex.get();
210  }
211 
212  // Key type for static storing
213  class convex_of_reference_key : virtual public dal::static_stored_object_key{
214  int type; // 0 = simplex structure degree K
215  // 1 = equilateral simplex of ref.
216  // 2 = dummy
217  dim_type N; short_type K; short_type nf;
218  public :
219  virtual bool compare(const static_stored_object_key &oo) const {
220  const convex_of_reference_key &o
221  = dynamic_cast<const convex_of_reference_key &>(oo);
222  if (type < o.type) return true;
223  if (type > o.type) return false;
224  if (N < o.N) return true;
225  if (N > o.N) return false;
226  if (K < o.K) return true;
227  if (K > o.K) return false;
228  if (nf < o.nf) return true;
229  return false;
230  }
231  convex_of_reference_key(int t, dim_type NN, short_type KK = 0,
232  short_type nnf = 0)
233  : type(t), N(NN), K(KK), nf(nnf) {}
234  };
235 
236 
237  /* simplexes. */
238 
239  class K_simplex_of_ref_ : public convex_of_reference {
240  public :
241  scalar_type is_in(const base_node &pt) const {
242  // return a negative number if pt is in the convex
243  GMM_ASSERT1(pt.size() == cvs->dim(),
244  "K_simplex_of_ref_::is_in: Dimensions mismatch");
245  scalar_type e = -1.0, r = (pt.size() > 0) ? -pt[0] : 0.0;
246  base_node::const_iterator it = pt.begin(), ite = pt.end();
247  for (; it != ite; e += *it, ++it) r = std::max(r, -(*it));
248  return std::max(r, e);
249  }
250  scalar_type is_in_face(short_type f, const base_node &pt) const {
251  // return zero if pt is in the face of the convex
252  // negative if the point is on the side of the face where the element is
253  GMM_ASSERT1(pt.size() == cvs->dim(),
254  "K_simplex_of_ref_::is_in_face: Dimensions mismatch");
255  if (f > 0) return -pt[f-1];
256  scalar_type e = -1.0;
257  base_node::const_iterator it = pt.begin(), ite = pt.end();
258  for (; it != ite; e += *it, ++it) {};
259  return e / sqrt(scalar_type(pt.size()));
260  }
261  K_simplex_of_ref_(dim_type NN, short_type KK) :
262  convex_of_reference(simplex_structure(NN, KK), (KK == 1) || (NN == 0))
263  {
264  if ((KK != 1) && (NN != 0)) basic_convex_ref_ = simplex_of_reference(NN, 1);
265  size_type R = cvs->nb_points();
266  convex<base_node>::points().resize(R);
267  normals_.resize(NN+1);
268  base_node null(NN); null.fill(0.0);
269  std::fill(normals_.begin(), normals_.end(), null);
270  std::fill(convex<base_node>::points().begin(),
271  convex<base_node>::points().end(), null);
272  for (size_type i = 1; i <= NN; ++i)
273  normals_[i][i-1] = -1.0;
274  if (NN > 0)
275  std::fill(normals_[0].begin(), normals_[0].end(),
276  scalar_type(1.0)/sqrt(scalar_type(NN)));
277  base_node c(NN); c.fill(0.0);
278 
279  if (KK == 0) {
280  c.fill(1.0/(NN+1));
281  convex<base_node>::points()[0] = c;
282  }
283  else {
284  size_type sum = 0, l;
285  for (size_type r = 0; r < R; ++r) {
286  convex<base_node>::points()[r] = c;
287  if (KK != 0 && NN > 0) {
288  l = 0; c[l] += 1.0 / scalar_type(KK); sum++;
289  while (sum > KK) {
290  sum -= int(floor(0.5+(c[l] * KK)));
291  c[l] = 0.0; l++; if (l == NN) break;
292  c[l] += 1.0 / scalar_type(KK); sum++;
293  }
294  }
295  }
296  }
297  ppoints = store_point_tab(convex<base_node>::points());
298  if (auto_basic) simplexify_convex(this, *psimplexified_convex);
299  }
300  };
301 
302  pconvex_ref simplex_of_reference(dim_type nc, short_type K) {
303  dal::pstatic_stored_object_key
304  pk = std::make_shared<convex_of_reference_key>(0, nc, K);
305  dal::pstatic_stored_object o = dal::search_stored_object(pk);
306  if (o) return std::dynamic_pointer_cast<const convex_of_reference>(o);
307  pconvex_ref p = std::make_shared<K_simplex_of_ref_>(nc, K);
308  dal::add_stored_object(pk, p, p->structure(), p->pspt(),
309  dal::PERMANENT_STATIC_OBJECT);
310  pconvex_ref p1 = basic_convex_ref(p);
311  if (p != p1) add_dependency(p, p1);
312  return p;
313  }
314 
315  /* ******************************************************************** */
316  /* Incomplete Q2 quadrilateral or hexahedral of reference. */
317  /* ******************************************************************** */
318  /* By Yao Koutsawa <yao.koutsawa@tudor.lu> 2012-12-10 */
319 
320  class Q2_incomplete_of_ref_ : public convex_of_reference {
321  public :
322  scalar_type is_in(const base_node& pt) const
323  { return basic_convex_ref_->is_in(pt); }
324  scalar_type is_in_face(short_type f, const base_node& pt) const
325  { return basic_convex_ref_->is_in_face(f, pt); }
326 
327  Q2_incomplete_of_ref_(dim_type nc) :
329  {
330  GMM_ASSERT1(nc == 2 || nc == 3, "Sorry exist only in dimension 2 or 3");
331  convex<base_node>::points().resize(cvs->nb_points());
332  normals_.resize(nc == 2 ? 4: 6);
333  basic_convex_ref_ = parallelepiped_of_reference(nc);
334 
335  if(nc==2) {
336  normals_[0] = { 1, 0};
337  normals_[1] = {-1, 0};
338  normals_[2] = { 0, 1};
339  normals_[3] = { 0,-1};
340 
341  convex<base_node>::points()[0] = base_node(0.0, 0.0);
342  convex<base_node>::points()[1] = base_node(0.5, 0.0);
343  convex<base_node>::points()[2] = base_node(1.0, 0.0);
344  convex<base_node>::points()[3] = base_node(0.0, 0.5);
345  convex<base_node>::points()[4] = base_node(1.0, 0.5);
346  convex<base_node>::points()[5] = base_node(0.0, 1.0);
347  convex<base_node>::points()[6] = base_node(0.5, 1.0);
348  convex<base_node>::points()[7] = base_node(1.0, 1.0);
349 
350  } else {
351  normals_[0] = { 1, 0, 0};
352  normals_[1] = {-1, 0, 0};
353  normals_[2] = { 0, 1, 0};
354  normals_[3] = { 0,-1, 0};
355  normals_[4] = { 0, 0, 1};
356  normals_[5] = { 0, 0,-1};
357 
358  convex<base_node>::points()[0] = base_node(0.0, 0.0, 0.0);
359  convex<base_node>::points()[1] = base_node(0.5, 0.0, 0.0);
360  convex<base_node>::points()[2] = base_node(1.0, 0.0, 0.0);
361  convex<base_node>::points()[3] = base_node(0.0, 0.5, 0.0);
362  convex<base_node>::points()[4] = base_node(1.0, 0.5, 0.0);
363  convex<base_node>::points()[5] = base_node(0.0, 1.0, 0.0);
364  convex<base_node>::points()[6] = base_node(0.5, 1.0, 0.0);
365  convex<base_node>::points()[7] = base_node(1.0, 1.0, 0.0);
366 
367  convex<base_node>::points()[8] = base_node(0.0, 0.0, 0.5);
368  convex<base_node>::points()[9] = base_node(1.0, 0.0, 0.5);
369  convex<base_node>::points()[10] = base_node(0.0, 1.0, 0.5);
370  convex<base_node>::points()[11] = base_node(1.0, 1.0, 0.5);
371 
372  convex<base_node>::points()[12] = base_node(0.0, 0.0, 1.0);
373  convex<base_node>::points()[13] = base_node(0.5, 0.0, 1.0);
374  convex<base_node>::points()[14] = base_node(1.0, 0.0, 1.0);
375  convex<base_node>::points()[15] = base_node(0.0, 0.5, 1.0);
376  convex<base_node>::points()[16] = base_node(1.0, 0.5, 1.0);
377  convex<base_node>::points()[17] = base_node(0.0, 1.0, 1.0);
378  convex<base_node>::points()[18] = base_node(0.5, 1.0, 1.0);
379  convex<base_node>::points()[19] = base_node(1.0, 1.0, 1.0);
380  }
381  ppoints = store_point_tab(convex<base_node>::points());
382  }
383  };
384 
385 
386  DAL_SIMPLE_KEY(Q2_incomplete_of_reference_key_, dim_type);
387 
388  pconvex_ref Q2_incomplete_of_reference(dim_type nc) {
389  dal::pstatic_stored_object_key
390  pk = std::make_shared<Q2_incomplete_of_reference_key_>(nc);
391  dal::pstatic_stored_object o = dal::search_stored_object(pk);
392  if (o) return std::dynamic_pointer_cast<const convex_of_reference>(o);
393  pconvex_ref p = std::make_shared<Q2_incomplete_of_ref_>(nc);
394  dal::add_stored_object(pk, p, p->structure(), p->pspt(),
395  dal::PERMANENT_STATIC_OBJECT);
396  pconvex_ref p1 = basic_convex_ref(p);
397  if (p != p1) add_dependency(p, p1);
398  return p;
399  }
400 
401  /* ******************************************************************** */
402  /* Pyramidal element of reference. */
403  /* ******************************************************************** */
404 
405  class pyramid_QK_of_ref_ : public convex_of_reference {
406  public :
407  scalar_type is_in_face(short_type f, const base_node& pt) const {
408  // return zero if pt is in the face of the convex
409  // negative if the point is on the side of the face where the element is
410  GMM_ASSERT1(pt.size() == 3, "Dimensions mismatch");
411  if (f == 0)
412  return -pt[2];
413  else
414  return gmm::vect_sp(normals_[f], pt) - sqrt(2.)/2.;
415  }
416  scalar_type is_in(const base_node& pt) const {
417  // return a negative number if pt is in the convex
418  scalar_type r = is_in_face(0, pt);
419  for (short_type i = 1; i < 5; ++i) r = std::max(r, is_in_face(i, pt));
420  return r;
421  }
422 
423  pyramid_QK_of_ref_(dim_type k) : convex_of_reference(pyramid_QK_structure(k), k == 1) {
424  GMM_ASSERT1(k == 1 || k == 2,
425  "Sorry exist only in degree 1 or 2, not " << k);
426 
427  convex<base_node>::points().resize(cvs->nb_points());
428  normals_.resize(cvs->nb_faces());
429  if (k != 1) basic_convex_ref_ = pyramid_QK_of_reference(1);
430 
431  normals_[0] = { 0., 0., -1.};
432  normals_[1] = { 0.,-1., 1.};
433  normals_[2] = { 1., 0., 1.};
434  normals_[3] = { 0., 1., 1.};
435  normals_[4] = {-1., 0., 1.};
436 
437  for (size_type i = 0; i < normals_.size(); ++i)
438  gmm::scale(normals_[i], 1. / gmm::vect_norm2(normals_[i]));
439 
440  if (k==1) {
441  convex<base_node>::points()[0] = base_node(-1.0, -1.0, 0.0);
442  convex<base_node>::points()[1] = base_node( 1.0, -1.0, 0.0);
443  convex<base_node>::points()[2] = base_node(-1.0, 1.0, 0.0);
444  convex<base_node>::points()[3] = base_node( 1.0, 1.0, 0.0);
445  convex<base_node>::points()[4] = base_node( 0.0, 0.0, 1.0);
446  } else if (k==2) {
447  convex<base_node>::points()[0] = base_node(-1.0, -1.0, 0.0);
448  convex<base_node>::points()[1] = base_node( 0.0, -1.0, 0.0);
449  convex<base_node>::points()[2] = base_node( 1.0, -1.0, 0.0);
450  convex<base_node>::points()[3] = base_node(-1.0, 0.0, 0.0);
451  convex<base_node>::points()[4] = base_node( 0.0, 0.0, 0.0);
452  convex<base_node>::points()[5] = base_node( 1.0, 0.0, 0.0);
453  convex<base_node>::points()[6] = base_node(-1.0, 1.0, 0.0);
454  convex<base_node>::points()[7] = base_node( 0.0, 1.0, 0.0);
455  convex<base_node>::points()[8] = base_node( 1.0, 1.0, 0.0);
456  convex<base_node>::points()[9] = base_node(-0.5, -0.5, 0.5);
457  convex<base_node>::points()[10] = base_node( 0.5, -0.5, 0.5);
458  convex<base_node>::points()[11] = base_node(-0.5, 0.5, 0.5);
459  convex<base_node>::points()[12] = base_node( 0.5, 0.5, 0.5);
460  convex<base_node>::points()[13] = base_node( 0.0, 0.0, 1.0);
461  }
462  ppoints = store_point_tab(convex<base_node>::points());
463  if (auto_basic) simplexify_convex(this, *psimplexified_convex);
464  }
465  };
466 
467 
468  DAL_SIMPLE_KEY(pyramid_QK_reference_key_, dim_type);
469 
470  pconvex_ref pyramid_QK_of_reference(dim_type k) {
471  dal::pstatic_stored_object_key
472  pk = std::make_shared<pyramid_QK_reference_key_>(k);
473  dal::pstatic_stored_object o = dal::search_stored_object(pk);
474  if (o) return std::dynamic_pointer_cast<const convex_of_reference>(o);
475  pconvex_ref p = std::make_shared<pyramid_QK_of_ref_>(k);
476  dal::add_stored_object(pk, p, p->structure(), p->pspt(),
477  dal::PERMANENT_STATIC_OBJECT);
478  pconvex_ref p1 = basic_convex_ref(p);
479  if (p != p1) add_dependency(p, p1);
480  return p;
481  }
482 
483 
484  /* ******************************************************************** */
485  /* Incomplete quadratic pyramidal element of reference. */
486  /* ******************************************************************** */
487 
488  class pyramid_Q2_incomplete_of_ref_ : public convex_of_reference {
489  public :
490  scalar_type is_in(const base_node& pt) const
491  { return basic_convex_ref_->is_in(pt); }
492  scalar_type is_in_face(short_type f, const base_node& pt) const
493  { return basic_convex_ref_->is_in_face(f, pt); }
494 
495  pyramid_Q2_incomplete_of_ref_() : convex_of_reference(pyramid_Q2_incomplete_structure(), false) {
496  convex<base_node>::points().resize(cvs->nb_points());
497  normals_.resize(cvs->nb_faces());
498  basic_convex_ref_ = pyramid_QK_of_reference(1);
499 
500  normals_ = basic_convex_ref_->normals();
501 
502  convex<base_node>::points()[0] = base_node(-1.0, -1.0, 0.0);
503  convex<base_node>::points()[1] = base_node( 0.0, -1.0, 0.0);
504  convex<base_node>::points()[2] = base_node( 1.0, -1.0, 0.0);
505  convex<base_node>::points()[3] = base_node(-1.0, 0.0, 0.0);
506  convex<base_node>::points()[4] = base_node( 1.0, 0.0, 0.0);
507  convex<base_node>::points()[5] = base_node(-1.0, 1.0, 0.0);
508  convex<base_node>::points()[6] = base_node( 0.0, 1.0, 0.0);
509  convex<base_node>::points()[7] = base_node( 1.0, 1.0, 0.0);
510  convex<base_node>::points()[8] = base_node(-0.5, -0.5, 0.5);
511  convex<base_node>::points()[9] = base_node( 0.5, -0.5, 0.5);
512  convex<base_node>::points()[10] = base_node(-0.5, 0.5, 0.5);
513  convex<base_node>::points()[11] = base_node( 0.5, 0.5, 0.5);
514  convex<base_node>::points()[12] = base_node( 0.0, 0.0, 1.0);
515 
516  ppoints = store_point_tab(convex<base_node>::points());
517  if (auto_basic) simplexify_convex(this, *psimplexified_convex);
518  }
519  };
520 
521 
522  DAL_SIMPLE_KEY(pyramid_Q2_incomplete_reference_key_, dim_type);
523 
525  dal::pstatic_stored_object_key
526  pk = std::make_shared<pyramid_Q2_incomplete_reference_key_>(0);
527  dal::pstatic_stored_object o = dal::search_stored_object(pk);
528  if (o)
529  return std::dynamic_pointer_cast<const convex_of_reference>(o);
530  else {
531  pconvex_ref p = std::make_shared<pyramid_Q2_incomplete_of_ref_>();
532  dal::add_stored_object(pk, p, p->structure(), p->pspt(),
533  dal::PERMANENT_STATIC_OBJECT);
534  pconvex_ref p1 = basic_convex_ref(p);
535  if (p != p1) add_dependency(p, p1);
536  return p;
537  }
538  }
539 
540 
541  /* ******************************************************************** */
542  /* Incomplete quadratic triangular prism element of reference. */
543  /* ******************************************************************** */
544 
545  class prism_incomplete_P2_of_ref_ : public convex_of_reference {
546  public :
547  scalar_type is_in(const base_node& pt) const
548  { return basic_convex_ref_->is_in(pt); }
549  scalar_type is_in_face(short_type f, const base_node& pt) const
550  { return basic_convex_ref_->is_in_face(f, pt); }
551 
552  prism_incomplete_P2_of_ref_() : convex_of_reference(prism_incomplete_P2_structure(), false) {
553  convex<base_node>::points().resize(cvs->nb_points());
554  normals_.resize(cvs->nb_faces());
555  basic_convex_ref_ = prism_of_reference(3);
556 
557  normals_ = basic_convex_ref_->normals();
558 
559  convex<base_node>::points()[0] = base_node(0.0, 0.0, 0.0);
560  convex<base_node>::points()[1] = base_node(0.5, 0.0, 0.0);
561  convex<base_node>::points()[2] = base_node(1.0, 0.0, 0.0);
562  convex<base_node>::points()[3] = base_node(0.0, 0.5, 0.0);
563  convex<base_node>::points()[4] = base_node(0.5, 0.5, 0.0);
564  convex<base_node>::points()[5] = base_node(0.0, 1.0, 0.0);
565  convex<base_node>::points()[6] = base_node(0.0, 0.0, 0.5);
566  convex<base_node>::points()[7] = base_node(1.0, 0.0, 0.5);
567  convex<base_node>::points()[8] = base_node(0.0, 1.0, 0.5);
568  convex<base_node>::points()[9] = base_node(0.0, 0.0, 1.0);
569  convex<base_node>::points()[10] = base_node(0.5, 0.0, 1.0);
570  convex<base_node>::points()[11] = base_node(1.0, 0.0, 1.0);
571  convex<base_node>::points()[12] = base_node(0.0, 0.5, 1.0);
572  convex<base_node>::points()[13] = base_node(0.5, 0.5, 1.0);
573  convex<base_node>::points()[14] = base_node(0.0, 1.0, 1.0);
574 
575  ppoints = store_point_tab(convex<base_node>::points());
576  if (auto_basic) simplexify_convex(this, *psimplexified_convex);
577  }
578  };
579 
580 
581  DAL_SIMPLE_KEY(prism_incomplete_P2_reference_key_, dim_type);
582 
584  dal::pstatic_stored_object_key
585  pk = std::make_shared<prism_incomplete_P2_reference_key_>(0);
586  dal::pstatic_stored_object o = dal::search_stored_object(pk);
587  if (o)
588  return std::dynamic_pointer_cast<const convex_of_reference>(o);
589  else {
590  pconvex_ref p = std::make_shared<prism_incomplete_P2_of_ref_>();
591  dal::add_stored_object(pk, p, p->structure(), p->pspt(),
592  dal::PERMANENT_STATIC_OBJECT);
593  pconvex_ref p1 = basic_convex_ref(p);
594  if (p != p1) add_dependency(p, p1);
595  return p;
596  }
597  }
598 
599 
600  /* ******************************************************************** */
601  /* Products. */
602  /* ******************************************************************** */
603 
604  DAL_DOUBLE_KEY(product_ref_key_, pconvex_ref, pconvex_ref);
605 
606  struct product_ref_ : public convex_of_reference {
607  pconvex_ref cvr1, cvr2;
608 
609  scalar_type is_in(const base_node &pt) const {
610  dim_type n1 = cvr1->structure()->dim(), n2 = cvr2->structure()->dim();
611  base_node pt1(n1), pt2(n2);
612  GMM_ASSERT1(pt.size() == cvs->dim(),
613  "product_ref_::is_in: Dimension does not match");
614  std::copy(pt.begin(), pt.begin()+n1, pt1.begin());
615  std::copy(pt.begin()+n1, pt.end(), pt2.begin());
616  return std::max(cvr1->is_in(pt1), cvr2->is_in(pt2));
617  }
618 
619  scalar_type is_in_face(short_type f, const base_node &pt) const {
620  // ne controle pas si le point est dans le convexe mais si un point
621  // suppos\E9 appartenir au convexe est dans une face donn\E9e
622  dim_type n1 = cvr1->structure()->dim(), n2 = cvr2->structure()->dim();
623  base_node pt1(n1), pt2(n2);
624  GMM_ASSERT1(pt.size() == cvs->dim(), "Dimensions mismatch");
625  std::copy(pt.begin(), pt.begin()+n1, pt1.begin());
626  std::copy(pt.begin()+n1, pt.end(), pt2.begin());
627  if (f < cvr1->structure()->nb_faces()) return cvr1->is_in_face(f, pt1);
628  else return cvr2->is_in_face(short_type(f - cvr1->structure()->nb_faces()), pt2);
629  }
630 
631  product_ref_(pconvex_ref a, pconvex_ref b) :
633  convex_direct_product(*a, *b).structure(),
634  basic_convex_ref(a) == a && basic_convex_ref(b) == b)
635  {
636  if (a->structure()->dim() < b->structure()->dim())
637  GMM_WARNING1("Illegal convex: swap your operands: dim(cv1)=" <<
638  int(a->structure()->dim()) << " < dim(cv2)=" <<
639  int(b->structure()->dim()));
640  cvr1 = a; cvr2 = b;
641  *((convex<base_node> *)(this)) = convex_direct_product(*a, *b);
642  normals_.resize(cvs->nb_faces());
643  base_small_vector null(cvs->dim()); null.fill(0.0);
644  std::fill(normals_.begin(), normals_.end(), null);
645  for (size_type r = 0; r < cvr1->structure()->nb_faces(); r++)
646  std::copy(cvr1->normals()[r].begin(), cvr1->normals()[r].end(),
647  normals_[r].begin());
648  for (size_type r = 0; r < cvr2->structure()->nb_faces(); r++)
649  std::copy(cvr2->normals()[r].begin(), cvr2->normals()[r].end(),
650  normals_[r+cvr1->structure()->nb_faces()].begin()
651  + cvr1->structure()->dim());
652  ppoints = store_point_tab(convex<base_node>::points());
653 
654  if (basic_convex_ref(a) != a || basic_convex_ref(b) != b)
655  basic_convex_ref_ = convex_ref_product(basic_convex_ref(a),
656  basic_convex_ref(b));
657  if (auto_basic) simplexify_convex(this, *psimplexified_convex);
658  }
659  };
660 
661 
662  pconvex_ref convex_ref_product(pconvex_ref a, pconvex_ref b) {
663  dal::pstatic_stored_object_key
664  pk = std::make_shared<product_ref_key_>(a, b);
665  dal::pstatic_stored_object o = dal::search_stored_object(pk);
666  if (o)
667  return std::dynamic_pointer_cast<const convex_of_reference>(o);
668  else {
669  pconvex_ref p = std::make_shared<product_ref_>(a, b);
670  dal::add_stored_object(pk, p, a, b,
671  convex_product_structure(a->structure(),
672  b->structure()),
673  p->pspt(), dal::PERMANENT_STATIC_OBJECT);
674  pconvex_ref p1 = basic_convex_ref(p);
675  if (p != p1) add_dependency(p, p1);
676  return p;
677  }
678  }
679 
680  pconvex_ref parallelepiped_of_reference(dim_type nc, dim_type k) {
681  if (nc <= 1) return simplex_of_reference(nc,k);
682  return convex_ref_product(parallelepiped_of_reference(dim_type(nc-1),k),
684  }
685 
686  pconvex_ref prism_of_reference(dim_type nc) {
687  if (nc <= 2) return parallelepiped_of_reference(nc);
688  else return convex_ref_product(simplex_of_reference(dim_type(nc-1)),
690  }
691 
692  /* equilateral ref convexes are used for estimation of convex quality */
693  class equilateral_simplex_of_ref_ : public convex_of_reference {
694  public:
695  scalar_type is_in(const base_node &pt) const {
696  scalar_type d(0);
697  for (size_type f = 0; f < normals().size(); ++f) {
698  const base_node &x0 = (f ? convex<base_node>::points()[f-1]
699  : convex<base_node>::points().back());
700  scalar_type v = gmm::vect_sp(pt-x0, normals()[f]);
701  if (f == 0) d = v; else d = std::max(d,v);
702  }
703  return d;
704  }
705  scalar_type is_in_face(short_type f, const base_node &pt) const {
706  const base_node &x0 = (f ? convex<base_node>::points()[f-1]
707  : convex<base_node>::points().back());
708  return gmm::vect_sp(pt-x0, normals()[f]);
709  }
710  equilateral_simplex_of_ref_(size_type N) :
711  convex_of_reference(simplex_structure(dim_type(N), 1), true)
712  {
713  pconvex_ref prev = equilateral_simplex_of_reference(dim_type(N-1));
714  convex<base_node>::points().resize(N+1);
715  normals_.resize(N+1);
716  base_node G(N); G.fill(0.);
717  for (short_type i=0; i < N+1; ++i) {
718  convex<base_node>::points()[i].resize(N);
719  if (i != N) {
720  std::copy(prev->convex<base_node>::points()[i].begin(),
721  prev->convex<base_node>::points()[i].end(),
722  convex<base_node>::points()[i].begin());
723  convex<base_node>::points()[i][N-1] = 0.;
724  } else {
725  convex<base_node>::points()[i] = scalar_type(1)/scalar_type(N) * G;
726  convex<base_node>::points()[i][N-1]
727  = sqrt(1. - gmm::vect_norm2_sqr(convex<base_node>::points()[i]));
728  }
729  G += convex<base_node>::points()[i];
730  }
731  gmm::scale(G, scalar_type(1)/scalar_type(N+1));
732  for (size_type f=0; f < N+1; ++f) {
733  normals_[f] = G - convex<base_node>::points()[f];
734  gmm::scale(normals_[f], 1/gmm::vect_norm2(normals_[f]));
735  }
736  ppoints = store_point_tab(convex<base_node>::points());
737  if (auto_basic) simplexify_convex(this, *psimplexified_convex);
738  }
739  };
740 
741  pconvex_ref equilateral_simplex_of_reference(dim_type nc) {
742  if (nc <= 1) return simplex_of_reference(nc);
743  dal::pstatic_stored_object_key
744  pk = std::make_shared<convex_of_reference_key>(1, nc);
745  dal::pstatic_stored_object o = dal::search_stored_object(pk);
746  if (o) return std::dynamic_pointer_cast<const convex_of_reference>(o);
747  pconvex_ref p = std::make_shared<equilateral_simplex_of_ref_>(nc);
748  dal::add_stored_object(pk, p, p->structure(), p->pspt(),
749  dal::PERMANENT_STATIC_OBJECT);
750  return p;
751  }
752 
753 
754  /* generic convex with n global nodes */
755 
756  class generic_dummy_ : public convex_of_reference {
757  public:
758  scalar_type is_in(const base_node &) const
759  { GMM_ASSERT1(false, "Information not available here"); }
760  scalar_type is_in_face(short_type, const base_node &) const
761  { GMM_ASSERT1(false, "Information not available here"); }
762 
763  generic_dummy_(dim_type d, size_type n, short_type nf) :
765  {
766  convex<base_node>::points().resize(n);
767  normals_.resize(0);
768  base_node P(d);
769  std::fill(P.begin(), P.end(), scalar_type(1)/scalar_type(20));
770  std::fill(convex<base_node>::points().begin(), convex<base_node>::points().end(), P);
771  ppoints = store_point_tab(convex<base_node>::points());
772  }
773  };
774 
775  pconvex_ref generic_dummy_convex_ref(dim_type nc, size_type n,
776  short_type nf) {
777  dal::pstatic_stored_object_key
778  pk = std::make_shared<convex_of_reference_key>(2, nc, short_type(n), nf);
779  dal::pstatic_stored_object o = dal::search_stored_object(pk);
780  if (o) return std::dynamic_pointer_cast<const convex_of_reference>(o);
781  pconvex_ref p = std::make_shared<generic_dummy_>(nc, n, nf);
782  dal::add_stored_object(pk, p, p->structure(), p->pspt(),
783  dal::PERMANENT_STATIC_OBJECT);
784  return p;
785  }
786 
787 
788 } /* end of namespace bgeot. */
pconvex_ref equilateral_simplex_of_reference(dim_type nc)
equilateral simplex (degree 1).
Reference convexes.
pconvex_ref basic_convex_ref(pconvex_ref cvr)
return the associated order 1 reference convex.
pconvex_ref pyramid_QK_of_reference(dim_type k)
pyramidal element of reference of degree k (k = 1 or 2 only)
Point tab storage.
pconvex_ref prism_of_reference(dim_type nc)
prism of reference of dimension nc (and degree 1)
pconvex_ref Q2_incomplete_of_reference(dim_type nc)
incomplete Q2 quadrilateral/hexahedral of reference of dimension d = 2 or 3
void clear()
erase the mesh
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
const stored_point_tab & points() const
return the vertices of the reference convex.
pconvex_ref convex_ref_product(pconvex_ref a, pconvex_ref b)
tensorial product of two convex ref.
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
pconvex_structure pyramid_QK_structure(dim_type k)
Give a pointer on the 3D pyramid structure for a degree k = 1 or 2.
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
pconvex_structure prism_incomplete_P2_structure()
Give a pointer on the 3D quadratic incomplete prism structure.
pconvex_structure convex_product_structure(pconvex_structure a, pconvex_structure b)
Give a pointer on the structures of a convex which is the direct product of the convexes represented ...
A simple singleton implementation.
pconvex_ref prism_incomplete_P2_of_reference()
incomplete quadratic prism element of reference (15-node)
Mesh structure definition.
Base class for reference convexes.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
pconvex_structure generic_dummy_structure(dim_type nc, size_type n, short_type nf)
Generic convex with n global nodes.
pconvex_structure Q2_incomplete_structure(dim_type nc)
Give a pointer on the structures of a incomplete Q2 quadrilateral/hexahedral of dimension d = 2 or 3...
convenient initialization of vectors via overload of "operator,".
const mesh_structure * simplexified_convex() const
return a mesh structure composed of simplexes whose union is the reference convex.
pconvex_ref pyramid_Q2_incomplete_of_reference()
incomplete quadratic pyramidal element of reference (13-node)
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
pconvex_ref parallelepiped_of_reference(dim_type nc, dim_type k)
parallelepiped of reference of dimension nc (and degree 1)
pconvex_structure basic_structure(pconvex_structure cv)
Original structure (if concerned)
Mesh structure definition.
Basic Geometric Tools.
pconvex_ref generic_dummy_convex_ref(dim_type nc, size_type n, short_type nf)
generic convex with n global nodes
virtual scalar_type is_in(const base_node &) const =0
return a negative or null number if the base_node is in the convex.
pconvex_ref simplex_of_reference(dim_type nc, short_type K)
returns a simplex of reference of dimension nc and degree k
pconvex_structure pyramid_Q2_incomplete_structure()
Give a pointer on the 3D quadratic incomplete pyramid structure.