27 inline scalar_type sfloor(scalar_type x)
28 {
return (x >= 0) ? floor(x) : -floor(-x); }
34 scalar_type c1 = c_max, c2 = c_max * scalar_type(base);
35 GMM_ASSERT2(y.size() == s,
"dimension error");
37 base_node::const_iterator itx=x.begin(), itex=x.end(), ity=y.begin();
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);
46 if (ret == 0) {
if (a < b) ret = -1;
else if (a > b) ret = 1; }
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;
64 mesh_precomposite::mesh_precomposite(
const basic_mesh &m) : box_tree{1e-13} {
68 void mesh_precomposite::initialise(
const basic_mesh &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]);
76 for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
81 GMM_ASSERT1(pgt->is_linear(),
"Bad geometric transformation");
83 base_matrix G(P, pgt->nb_points());
86 m.points_of_convex(cv, G);
89 gtransinv[cv] = ctx.B();
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);
98 box_tree.build_tree();
102 std::vector<opt_long_scalar_type>);
104 polynomial_composite::polynomial_composite(
const mesh_precomposite &m,
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.);
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) {
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]);
122 scalar_type polynomial_composite::eval(
const base_node &p,
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());
131 auto dim = mp->dim();
132 base_node p1_stored, p1, p2(dim);
135 auto &box_tree = mp->box_tree;
136 rtree::pbox_set box_list;
137 box_tree.find_boxes_at_point(p, box_list);
139 while (box_list.size()) {
140 auto pmax_box = *box_list.begin();
142 if (box_list.size() > 1) {
143 auto max_rate = -1.0;
144 for (
auto &&pbox : box_list) {
147 auto h = pbox->max->at(i) - pbox->min->at(i);
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);
154 if (box_rate > max_rate) { pmax_box = pbox; max_rate = box_rate; }
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]));
161 mult_diff_transposed(mp->gtransinv[cv], p, mp->orgs[cv], p1);
162 scalar_type ddist(0);
168 if (mp->trans_of_convex(cv)->convex_ref()->is_in(p1) < 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()));
175 p1_stored = p1; cv_stored = cv;
179 if (box_list.size() == 1)
break;
180 box_list.erase(pmax_box);
184 to_scalar(poly_of_subelt(cv_stored).eval(local_coordinate
185 ? p1_stored.begin(): p.begin()));
188 GMM_ASSERT1(
false,
"Element not found in composite polynomial: " << p);
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]));
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) {
208 if (Der.is_zero()) polytab.erase(ic);
else set_poly_of_subelt(ic,Der);
213 for (
size_type ic = 0; ic < mp->nb_convex(); ++ic) {
214 auto poly = poly_of_subelt(ic);
216 if (polytab.find(ic) != polytab.end()) set_poly_of_subelt(ic, poly);
220 void polynomial_composite::set_poly_of_subelt(
size_type l,
221 const base_poly &poly) {
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>
227 o = std::make_shared<stored_base_poly>(poly);
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])];
239 return default_polys[mp->dim()];
241 return *(it->second);
251 const std::vector<base_node> *opt_gt_pts,
253 scalar_type h = 1./k;
254 switch (cvs->dim()) {
257 base_node a(1), b(1);
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);
264 pm->add_segment(na, nb);
270 base_node A(2),B(2),C(2),D(2);
272 scalar_type a = i * h, b = (i+1) * h;
274 scalar_type c = l * h, d = (l+1) * h;
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);
290 pm->add_triangle(nA,nB,nC);
292 pm->add_triangle(nC,nB,nD);
302 base_node A,B,C,D,E,F,G,H;
304 scalar_type x = ci*h;
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);
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);
339 if (k > 2 && ci+cj+ck < k-2) {
340 t[7] = pm->add_point(H);
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]);
353 if (k > 2 && ci+cj+ck < k-2) {
354 pm->add_tetrahedron(t[3], t[5], t[7], t[6]);
362 GMM_ASSERT1(
false,
"Sorry, not implemented for simplices of "
363 "dimension " <<
int(cvs->dim()));
367 static void structured_mesh_for_parallelepiped_
369 const std::vector<base_node> *opt_gt_pts,
short_type k, pbasic_mesh pm) {
370 scalar_type h = 1./k;
374 std::vector<size_type> strides(n);
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);
382 while (kcnt[n] == 0) {
385 if (opt_gt) pt = opt_gt->transform(pt, *opt_gt_pts);
386 pids.push_back(pm->add_point(pt));
389 { kcnt[kk]++;
if (kcnt[kk] == k+1) { kcnt[kk] = 0; kk++; }
else break; }
395 std::vector<size_type> ppts(pow2n);
397 while (kcnt[n] == 0) {
398 for (kk = 0; kk < pow2n; ++kk) {
401 pos += kcnt[z]*strides[z];
402 if ((kk & (
size_type(1) << z))) pos += strides[z];
404 ppts[kk] = pids.at(pos);
406 pm->add_convex(parallelepiped_linear_geotrans(n), ppts.begin());
408 while (kk < n && kcnt[kk] == k) { kcnt[kk] = 0; kcnt[++kk]++; }
415 const std::vector<base_node> *opt_gt_pts,
418 dim_type n = cvs->dim();
424 structured_mesh_for_simplex_(cvs,opt_gt,opt_gt_pts,k,pm);
429 structured_mesh_for_parallelepiped_(cvs,opt_gt,opt_gt_pts,k,pm);
433 GMM_ASSERT1(
false,
"Sorry, structured_mesh not implemented for prisms.");
435 GMM_ASSERT1(
false,
"This element is not taken into account. Contact us");
440 static void structured_mesh_of_faces_(pconvex_ref cvr, dim_type f,
442 mesh_structure &facem) {
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)
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);
457 for (
size_type i=0; i < ipts.size(); ++i)
if (!on_face[ipts[i]])
458 { allin =
false;
break; }
465 facem.add_convex(m.structure_of_convex(cv)->faces_structure()[ff],
479 std::unique_ptr<basic_mesh> pm;
480 std::vector<std::unique_ptr<mesh_structure>> pfacem;
481 dal::bit_vector nodes_on_edges;
482 std::unique_ptr<mesh_precomposite> pmp;
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"); }
489 typedef std::shared_ptr<const str_mesh_cv__> pstr_mesh_cv__;
499 pbasic_mesh &pm, pmesh_precomposite &pmp,
500 bool force_simplexification) {
504 force_simplexification = force_simplexification || (nbp == n+1);
505 dal::pstatic_stored_object_key
507 k, force_simplexification);
509 dal::pstatic_stored_object o = dal::search_stored_object_on_all_threads(pk);
512 psmc = std::dynamic_pointer_cast<const str_mesh_cv__>(o);
515 auto ppsmc = std::make_shared<str_mesh_cv__>
517 str_mesh_cv__ &smc(*ppsmc);
520 smc.pm = std::make_unique<basic_mesh>();
522 if (force_simplexification) {
531 = simplex_geotrans(cvr->structure()->dim(), 1);
532 for (
size_type j=0; j < cvpts.size(); ++j) {
538 sgt, &cvpts, k, smc.pm.get());
541 structured_mesh_for_convex_(cvr->structure(), 0, 0, k, smc.pm.get());
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]));
549 smc.pmp = std::make_unique<mesh_precomposite>(*(smc.pm));
553 pmp = psmc->pmp.get();
558 pbasic_mesh pm; pmesh_precomposite pmp;
563 const std::vector<std::unique_ptr<mesh_structure>>&
565 dal::pstatic_stored_object_key
570 pstr_mesh_cv__ psmc = std::dynamic_pointer_cast<const str_mesh_cv__>(o);
573 else GMM_ASSERT1(
false,
574 "call refined_simplex_mesh_for_convex first (or fix me)");
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)
*/
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2(const V1 &v1, const V2 &v2)
Euclidean distance between two vectors.
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
gmm::uint16_type short_type
used as the common short type integer in the library
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
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