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.");
43 # include <libqhull/qhull_a.h> 56 void qhull_delaunay(
const std::vector<base_node> &pts,
57 gmm::dense_matrix<size_type>& simplexes) {
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;
66 std::vector<coordT> Pts(dim * pts.size());
68 gmm::copy(pts[i], gmm::sub_vector(Pts, gmm::sub_interval(i*dim, dim)));
74 char flags[]=
"qhull QJ d Qbb Pp T0";
77 FILE *errfile= stderr;
81 vertexT *vertex, **vertexp;
82 exitcode = qh_new_qhull (
int(dim),
int(pts.size()), &Pts[0], ismalloc,
83 flags, outfile, errfile);
86 FORALLfacets {
if (!facet->upperdelaunay) nbf++; }
87 gmm::resize(simplexes, dim+1, nbf);
91 if (!facet->upperdelaunay) {
93 FOREACHvertex_(facet->vertices) {
94 assert(s < (
unsigned)(dim+1));
95 simplexes(s++,nbf) = qh_pointid(vertex->point);
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";
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());
128 size_type nb = simplexified_tab(basic_cvs, &tab);
131 for (
size_type i = 0; i <= n; ++i) ipts[i] = *tab++;
132 m.add_simplex(n, ipts.begin());
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());
151 struct stored_point_tab_key :
virtual public dal::static_stored_object_key {
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);
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;
169 if (it2 != y.end())
return true;
177 dal::pstatic_stored_object_key
178 pk = std::make_shared<stored_point_tab_key>(&spt);
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());
189 convex_of_reference::convex_of_reference
192 auto_basic(auto_basic_) {
193 DAL_STORED_OBJECT_DEBUG_CREATED(
this,
"convex of refrence");
194 psimplexified_convex = std::make_shared<mesh_structure>();
199 bool convex_of_reference::is_basic()
const {
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();
213 class convex_of_reference_key :
virtual public dal::static_stored_object_key{
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;
231 convex_of_reference_key(
int t, dim_type NN,
short_type KK = 0,
233 : type(t), N(NN), K(KK), nf(nnf) {}
241 scalar_type is_in(
const base_node &pt)
const {
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);
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()));
261 K_simplex_of_ref_(dim_type NN,
short_type KK) :
265 size_type R = cvs->nb_points();
267 normals_.resize(NN+1);
269 std::fill(normals_.begin(), normals_.end(), null);
272 for (size_type i = 1; i <= NN; ++i)
273 normals_[i][i-1] = -1.0;
275 std::fill(normals_[0].begin(), normals_[0].end(),
276 scalar_type(1.0)/sqrt(scalar_type(NN)));
284 size_type sum = 0, l;
285 for (size_type r = 0; r < R; ++r) {
287 if (KK != 0 && NN > 0) {
288 l = 0; c[l] += 1.0 / scalar_type(KK); sum++;
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++;
298 if (auto_basic) simplexify_convex(
this, *psimplexified_convex);
303 dal::pstatic_stored_object_key
304 pk = std::make_shared<convex_of_reference_key>(0, nc, K);
307 pconvex_ref p = std::make_shared<K_simplex_of_ref_>(nc, K);
309 dal::PERMANENT_STATIC_OBJECT);
311 if (p != p1) add_dependency(p, p1);
322 scalar_type is_in(
const base_node& pt)
const 323 {
return basic_convex_ref_->
is_in(pt); }
325 {
return basic_convex_ref_->is_in_face(f, pt); }
327 Q2_incomplete_of_ref_(dim_type nc) :
330 GMM_ASSERT1(nc == 2 || nc == 3,
"Sorry exist only in dimension 2 or 3");
332 normals_.resize(nc == 2 ? 4: 6);
336 normals_[0] = { 1, 0};
337 normals_[1] = {-1, 0};
338 normals_[2] = { 0, 1};
339 normals_[3] = { 0,-1};
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};
386 DAL_SIMPLE_KEY(Q2_incomplete_of_reference_key_, dim_type);
389 dal::pstatic_stored_object_key
390 pk = std::make_shared<Q2_incomplete_of_reference_key_>(nc);
393 pconvex_ref p = std::make_shared<Q2_incomplete_of_ref_>(nc);
395 dal::PERMANENT_STATIC_OBJECT);
397 if (p != p1) add_dependency(p, p1);
410 GMM_ASSERT1(pt.size() == 3,
"Dimensions mismatch");
414 return gmm::vect_sp(normals_[f], pt) - sqrt(2.)/2.;
416 scalar_type is_in(
const base_node& pt)
const {
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));
424 GMM_ASSERT1(k == 1 || k == 2,
425 "Sorry exist only in degree 1 or 2, not " << k);
428 normals_.resize(cvs->nb_faces());
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.};
437 for (
size_type i = 0; i < normals_.size(); ++i)
438 gmm::scale(normals_[i], 1. / gmm::vect_norm2(normals_[i]));
463 if (auto_basic) simplexify_convex(
this, *psimplexified_convex);
468 DAL_SIMPLE_KEY(pyramid_QK_reference_key_, dim_type);
471 dal::pstatic_stored_object_key
472 pk = std::make_shared<pyramid_QK_reference_key_>(k);
475 pconvex_ref p = std::make_shared<pyramid_QK_of_ref_>(k);
477 dal::PERMANENT_STATIC_OBJECT);
479 if (p != p1) add_dependency(p, p1);
490 scalar_type is_in(
const base_node& pt)
const 491 {
return basic_convex_ref_->
is_in(pt); }
493 {
return basic_convex_ref_->is_in_face(f, pt); }
497 normals_.resize(cvs->nb_faces());
500 normals_ = basic_convex_ref_->normals();
517 if (auto_basic) simplexify_convex(
this, *psimplexified_convex);
522 DAL_SIMPLE_KEY(pyramid_Q2_incomplete_reference_key_, dim_type);
525 dal::pstatic_stored_object_key
526 pk = std::make_shared<pyramid_Q2_incomplete_reference_key_>(0);
531 pconvex_ref p = std::make_shared<pyramid_Q2_incomplete_of_ref_>();
533 dal::PERMANENT_STATIC_OBJECT);
535 if (p != p1) add_dependency(p, p1);
547 scalar_type is_in(
const base_node& pt)
const 548 {
return basic_convex_ref_->
is_in(pt); }
550 {
return basic_convex_ref_->is_in_face(f, pt); }
554 normals_.resize(cvs->nb_faces());
557 normals_ = basic_convex_ref_->normals();
576 if (auto_basic) simplexify_convex(
this, *psimplexified_convex);
581 DAL_SIMPLE_KEY(prism_incomplete_P2_reference_key_, dim_type);
584 dal::pstatic_stored_object_key
585 pk = std::make_shared<prism_incomplete_P2_reference_key_>(0);
590 pconvex_ref p = std::make_shared<prism_incomplete_P2_of_ref_>();
592 dal::PERMANENT_STATIC_OBJECT);
594 if (p != p1) add_dependency(p, p1);
604 DAL_DOUBLE_KEY(product_ref_key_, pconvex_ref, pconvex_ref);
607 pconvex_ref cvr1, cvr2;
609 scalar_type is_in(
const base_node &pt)
const {
610 dim_type n1 = cvr1->structure()->dim(), n2 = cvr2->structure()->dim();
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));
622 dim_type n1 = cvr1->structure()->dim(), n2 = cvr2->structure()->dim();
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);
631 product_ref_(pconvex_ref a, pconvex_ref b) :
633 convex_direct_product(*a, *b).structure(),
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()));
642 normals_.resize(cvs->nb_faces());
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());
657 if (auto_basic) simplexify_convex(
this, *psimplexified_convex);
663 dal::pstatic_stored_object_key
664 pk = std::make_shared<product_ref_key_>(a, b);
669 pconvex_ref p = std::make_shared<product_ref_>(a, b);
673 p->pspt(), dal::PERMANENT_STATIC_OBJECT);
675 if (p != p1) add_dependency(p, p1);
695 scalar_type is_in(
const base_node &pt)
const {
697 for (
size_type f = 0; f < normals().size(); ++f) {
700 scalar_type v = gmm::vect_sp(pt-x0, normals()[f]);
701 if (f == 0) d = v;
else d = std::max(d,v);
708 return gmm::vect_sp(pt-x0, normals()[f]);
710 equilateral_simplex_of_ref_(
size_type N) :
715 normals_.resize(N+1);
720 std::copy(prev->convex<base_node>::points()[i].begin(),
721 prev->convex<base_node>::points()[i].end(),
731 gmm::scale(G, scalar_type(1)/scalar_type(N+1));
734 gmm::scale(normals_[f], 1/gmm::vect_norm2(normals_[f]));
737 if (auto_basic) simplexify_convex(
this, *psimplexified_convex);
743 dal::pstatic_stored_object_key
744 pk = std::make_shared<convex_of_reference_key>(1, nc);
747 pconvex_ref p = std::make_shared<equilateral_simplex_of_ref_>(nc);
749 dal::PERMANENT_STATIC_OBJECT);
758 scalar_type is_in(
const base_node &)
const 759 { GMM_ASSERT1(
false,
"Information not available here"); }
761 { GMM_ASSERT1(
false,
"Information not available here"); }
769 std::fill(P.begin(), P.end(), scalar_type(1)/scalar_type(20));
777 dal::pstatic_stored_object_key
778 pk = std::make_shared<convex_of_reference_key>(2, nc,
short_type(n), nf);
781 pconvex_ref p = std::make_shared<generic_dummy_>(nc, n, nf);
783 dal::PERMANENT_STATIC_OBJECT);
pconvex_ref equilateral_simplex_of_reference(dim_type nc)
equilateral simplex (degree 1).
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)
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
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
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.
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.