28 inline scalar_type sfloor(scalar_type x)
29 {
return (x >= 0) ? floor(x) : -floor(-x); }
35 scalar_type c1 = c_max, c2 = c_max * scalar_type(base);
36 GMM_ASSERT2(y.size() == s,
"dimension error");
38 base_node::const_iterator itx=x.begin(), itex=x.end(), ity=y.begin();
40 for (; itx != itex; ++itx, ++ity) {
41 long a = long(sfloor((*itx) * c1)), b = long(sfloor((*ity) * c1));
42 if ((scalar_type(gmm::abs(a)) > scalar_type(base))
43 || (scalar_type(gmm::abs(b)) > scalar_type(base))) {
44 exp_max++; c_max /= scalar_type(base);
47 if (ret == 0) {
if (a < b) ret = -1;
else if (a > b) ret = 1; }
51 for (
int e = exp_max; e >= exp_min; --e, c1 *= scalar_type(base),
52 c2 *= scalar_type(base)) {
53 itx = x.begin(), itex = x.end(), ity = y.begin();
54 for (; itx != itex; ++itx, ++ity) {
55 int a = int(sfloor(((*itx) * c2) - sfloor((*itx) * c1)
56 * scalar_type(base)));
57 int b = int(sfloor(((*ity) * c2) - sfloor((*ity) * c1)
58 * scalar_type(base)));
59 if (a < b)
return -1;
else if (a > b)
return 1;
65 mesh_precomposite::mesh_precomposite(
const basic_mesh &m) : box_tree{1e-13} {
69 void mesh_precomposite::initialise(
const basic_mesh &m) {
71 det.resize(m.nb_convex()); orgs.resize(m.nb_convex());
72 gtrans.resize(m.nb_convex()); gtransinv.resize(m.nb_convex());
73 for (
size_type i = 0; i <= m.points().index().last_true(); ++i)
74 vertices.add(m.points()[i]);
77 for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
82 GMM_ASSERT1(pgt->is_linear(),
"Bad geometric transformation");
84 base_matrix G(P, pgt->nb_points());
87 m.points_of_convex(cv, G);
90 gtransinv[cv] = ctx.B();
93 auto points_of_convex = m.points_of_convex(cv);
94 orgs[cv] = pgt->transform(X, G);
95 bounding_box(min, max, points_of_convex);
96 box_to_convexes_map[box_tree.add_box(min, max)].push_back(cv);
99 box_tree.build_tree();
103 std::vector<opt_long_scalar_type>);
105 polynomial_composite::polynomial_composite(
const mesh_precomposite &m,
107 : mp(&m), local_coordinate(lc), faces_first(ff),
108 default_polys(mp->dim()+1) {
109 for (dim_type i = 0; i <= mp->dim(); ++i)
110 default_polys[i] = base_poly(i, 0.);
113 static void mult_diff_transposed(
const base_matrix &M,
const base_node &p,
114 const base_node &p1, base_node &p2) {
115 for (dim_type d = 0; d < p2.size(); ++d) {
117 auto col = mat_col(M, d);
118 for (dim_type i = 0; i < p1.size(); ++i)
119 p2[d] += col[i] * (p[i] - p1[i]);
123 scalar_type polynomial_composite::eval(
const base_node &p,
126 if (!local_coordinate)
return poly_of_subelt(l).eval(p.begin());
127 base_node p1(gmm::mat_ncols(mp->gtransinv[l]));
128 mult_diff_transposed(mp->gtransinv[l], p, mp->orgs[l], p1);
129 return poly_of_subelt(l).eval(p1.begin());
132 auto dim = mp->dim();
133 base_node p1_stored, p1, p2(dim);
136 auto &box_tree = mp->box_tree;
137 rtree::pbox_set box_list;
138 box_tree.find_boxes_at_point(p, box_list);
140 while (box_list.size()) {
141 auto pmax_box = *box_list.begin();
143 if (box_list.size() > 1) {
144 auto max_rate = -1.0;
145 for (
auto &&pbox : box_list) {
148 auto h = pbox->max->at(i) - pbox->min->at(i);
150 auto rate = std::min(pbox->max->at(i) - p[i],
151 p[i] - pbox->min->at(i)) / h;
152 box_rate = std::min(rate, box_rate);
155 if (box_rate > max_rate) { pmax_box = pbox; max_rate = box_rate; }
159 for (
auto cv : mp->box_to_convexes_map.at(pmax_box->id)) {
160 dim_type elt_dim = dim_type(gmm::mat_ncols(mp->gtransinv[cv]));
162 mult_diff_transposed(mp->gtransinv[cv], p, mp->orgs[cv], p1);
163 scalar_type ddist(0);
169 if (mp->trans_of_convex(cv)->convex_ref()->is_in(p1) < 1E-9
171 if (!faces_first || elt_dim < dim) {
172 scalar_type res = to_scalar(poly_of_subelt(cv).eval(local_coordinate
173 ? p1.begin() : p.begin()));
176 p1_stored = p1; cv_stored = cv;
180 if (box_list.size() == 1)
break;
181 box_list.erase(pmax_box);
185 to_scalar(poly_of_subelt(cv_stored).eval(local_coordinate
186 ? p1_stored.begin(): p.begin()));
189 GMM_ASSERT1(
false,
"Element not found in composite polynomial: " << p);
193 void polynomial_composite::derivative(
short_type k) {
194 if (local_coordinate) {
195 dim_type P = mp->dim();
196 base_vector e(P), f(P); e[k] = 1.0;
197 for (
size_type ic = 0; ic < mp->nb_convex(); ++ic) {
198 dim_type N = dim_type(gmm::mat_ncols(mp->gtransinv[ic]));
200 gmm::mult(gmm::transposed(mp->gtransinv[ic]), e, f);
201 base_poly Der(N, 0), Q;
202 if (polytab.find(ic) != polytab.end()) {
203 auto &poly = poly_of_subelt(ic);
204 for (dim_type n = 0; n < N; ++n) {
209 if (Der.is_zero()) polytab.erase(ic);
else set_poly_of_subelt(ic,Der);
214 for (
size_type ic = 0; ic < mp->nb_convex(); ++ic) {
215 auto poly = poly_of_subelt(ic);
217 if (polytab.find(ic) != polytab.end()) set_poly_of_subelt(ic, poly);
221 void polynomial_composite::set_poly_of_subelt(
size_type l,
222 const base_poly &poly) {
224 std::make_shared<base_poly_key>(poly.degree(), poly.dim(), poly);
225 pstored_base_poly o(std::dynamic_pointer_cast<const stored_base_poly>
228 o = std::make_shared<stored_base_poly>(poly);
234 const base_poly &polynomial_composite::poly_of_subelt(
size_type l)
const {
235 auto it = polytab.find(l);
236 if (it == polytab.end()) {
237 if (local_coordinate)
238 return default_polys[gmm::mat_ncols(mp->gtransinv[l])];
240 return default_polys[mp->dim()];
242 return *(it->second);
252 const std::vector<base_node> *opt_gt_pts,
254 scalar_type h = 1./k;
255 switch (cvs->dim()) {
258 base_node a(1), b(1);
260 a[0] = i * h; b[0] = (i+1) * h;
261 if (opt_gt) a = opt_gt->transform(a, *opt_gt_pts);
262 if (opt_gt) b = opt_gt->transform(b, *opt_gt_pts);
265 pm->add_segment(na, nb);
271 base_node A(2),B(2),C(2),D(2);
273 scalar_type a = i * h, b = (i+1) * h;
275 scalar_type c = l * h, d = (l+1) * h;
281 A = opt_gt->transform(A, *opt_gt_pts);
282 B = opt_gt->transform(B, *opt_gt_pts);
283 C = opt_gt->transform(C, *opt_gt_pts);
284 D = opt_gt->transform(D, *opt_gt_pts);
291 pm->add_triangle(nA,nB,nC);
293 pm->add_triangle(nC,nB,nD);
303 base_node A,B,C,D,E,F,G,H;
305 scalar_type x = ci*h;
320 A = opt_gt->transform(A, *opt_gt_pts);
321 B = opt_gt->transform(B, *opt_gt_pts);
322 C = opt_gt->transform(C, *opt_gt_pts);
323 D = opt_gt->transform(D, *opt_gt_pts);
324 E = opt_gt->transform(E, *opt_gt_pts);
325 F = opt_gt->transform(F, *opt_gt_pts);
326 G = opt_gt->transform(G, *opt_gt_pts);
327 H = opt_gt->transform(H, *opt_gt_pts);
330 t[0] = pm->add_point(A);
331 t[1] = pm->add_point(B);
332 t[2] = pm->add_point(C);
333 t[4] = pm->add_point(E);
334 t[3] = t[5] = t[6] = t[7] =
size_type(-1);
335 if (k > 1 && ci+cj+ck < k-1) {
336 t[3] = pm->add_point(D);
337 t[5] = pm->add_point(F);
338 t[6] = pm->add_point(G);
340 if (k > 2 && ci+cj+ck < k-2) {
341 t[7] = pm->add_point(H);
347 pm->add_tetrahedron(t[0], t[1], t[2], t[4]);
348 if (k > 1 && ci+cj+ck < k-1) {
349 pm->add_tetrahedron(t[1], t[2], t[4], t[5]);
350 pm->add_tetrahedron(t[6], t[4], t[2], t[5]);
351 pm->add_tetrahedron(t[2], t[3], t[5], t[1]);
352 pm->add_tetrahedron(t[2], t[5], t[3], t[6]);
354 if (k > 2 && ci+cj+ck < k-2) {
355 pm->add_tetrahedron(t[3], t[5], t[7], t[6]);
363 GMM_ASSERT1(
false,
"Sorry, not implemented for simplices of "
364 "dimension " <<
int(cvs->dim()));
368 static void structured_mesh_for_parallelepiped_
370 const std::vector<base_node> *opt_gt_pts,
short_type k, pbasic_mesh pm) {
371 scalar_type h = 1./k;
375 std::vector<size_type> strides(n);
377 for (
size_type i=0; i < n; ++i) { strides[i] = nbpts; nbpts *= (k+1); }
378 std::vector<short_type> kcnt; kcnt.resize(n+1,0);
379 std::vector<size_type> pids; pids.reserve(nbpts);
383 while (kcnt[n] == 0) {
386 if (opt_gt) pt = opt_gt->transform(pt, *opt_gt_pts);
387 pids.push_back(pm->add_point(pt));
390 { kcnt[kk]++;
if (kcnt[kk] == k+1) { kcnt[kk] = 0; kk++; }
else break; }
396 std::vector<size_type> ppts(pow2n);
398 while (kcnt[n] == 0) {
399 for (kk = 0; kk < pow2n; ++kk) {
402 pos += kcnt[z]*strides[z];
403 if ((kk & (
size_type(1) << z))) pos += strides[z];
405 ppts[kk] = pids.at(pos);
407 pm->add_convex(parallelepiped_linear_geotrans(n), ppts.begin());
409 while (kk < n && kcnt[kk] == k) { kcnt[kk] = 0; kcnt[++kk]++; }
416 const std::vector<base_node> *opt_gt_pts,
419 dim_type n = cvs->dim();
425 structured_mesh_for_simplex_(cvs,opt_gt,opt_gt_pts,k,pm);
430 structured_mesh_for_parallelepiped_(cvs,opt_gt,opt_gt_pts,k,pm);
434 GMM_ASSERT1(
false,
"Sorry, structured_mesh not implemented for prisms.");
436 GMM_ASSERT1(
false,
"This element is not taken into account. Contact us");
441 static void structured_mesh_of_faces_(pconvex_ref cvr, dim_type f,
443 mesh_structure &facem) {
445 dal::bit_vector on_face;
446 for (
size_type i = 0; i < m.nb_max_points(); ++i) {
447 if (m.is_point_valid(i)) {
448 if (gmm::abs(cvr->is_in_face(f, m.points()[i])) < 1e-12)
453 for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
454 for (
short_type ff=0; ff < m.structure_of_convex(cv)->nb_faces(); ++ff) {
455 mesh_structure::ind_pt_face_ct
456 ipts=m.ind_points_of_face_of_convex(cv,ff);
458 for (
size_type i=0; i < ipts.size(); ++i)
if (!on_face[ipts[i]])
459 { allin =
false;
break; }
466 facem.add_convex(m.structure_of_convex(cv)->faces_structure()[ff],
480 std::unique_ptr<basic_mesh> pm;
481 std::vector<std::unique_ptr<mesh_structure>> pfacem;
482 dal::bit_vector nodes_on_edges;
483 std::unique_ptr<mesh_precomposite> pmp;
485 cvs(c), n(k), simplex_mesh(smesh_)
486 { DAL_STORED_OBJECT_DEBUG_CREATED(
this,
"cv mesh"); }
487 ~str_mesh_cv__() { DAL_STORED_OBJECT_DEBUG_DESTROYED(
this,
"cv mesh"); }
490 typedef std::shared_ptr<const str_mesh_cv__> pstr_mesh_cv__;
500 pbasic_mesh &pm, pmesh_precomposite &pmp,
501 bool force_simplexification) {
505 force_simplexification = force_simplexification || (nbp == n+1);
506 dal::pstatic_stored_object_key
508 k, force_simplexification);
510 dal::pstatic_stored_object o = dal::search_stored_object_on_all_threads(pk);
513 psmc = std::dynamic_pointer_cast<const str_mesh_cv__>(o);
516 auto ppsmc = std::make_shared<str_mesh_cv__>
518 str_mesh_cv__ &smc(*ppsmc);
521 smc.pm = std::make_unique<basic_mesh>();
523 if (force_simplexification) {
532 = simplex_geotrans(cvr->structure()->dim(), 1);
533 for (
size_type j=0; j < cvpts.size(); ++j) {
539 sgt, &cvpts, k, smc.pm.get());
542 structured_mesh_for_convex_(cvr->structure(), 0, 0, k, smc.pm.get());
544 smc.pfacem.resize(cvr->structure()->nb_faces());
545 for (dim_type f=0; f < cvr->structure()->nb_faces(); ++f) {
546 smc.pfacem[f] = std::make_unique<mesh_structure>();
547 structured_mesh_of_faces_(cvr, f, *(smc.pm), *(smc.pfacem[f]));
550 smc.pmp = std::make_unique<mesh_precomposite>(*(smc.pm));
554 pmp = psmc->pmp.get();
559 pbasic_mesh pm; pmesh_precomposite pmp;
564 const std::vector<std::unique_ptr<mesh_structure>>&
566 dal::pstatic_stored_object_key
571 pstr_mesh_cv__ psmc = std::dynamic_pointer_cast<const str_mesh_cv__>(o);
574 else GMM_ASSERT1(
false,
575 "call refined_simplex_mesh_for_convex first (or fix me)");