26 std::ostream &
operator<<(std::ostream &os,
const mesh_level_set::zone &z) {
28 for (mesh_level_set::zone::const_iterator it = z.begin();
29 it != z.end(); ++it) {
30 if (it != z.begin()) os <<
", ";
37 std::ostream &
operator<<(std::ostream &os,
const mesh_level_set::zoneset &zs) {
39 for (mesh_level_set::zoneset::const_iterator it = zs.begin();
40 it != zs.end(); ++it) {
41 if (it != zs.begin()) os <<
"; ";
52 unsigned long long tprev;
53 unsigned long long acc;
54 unsigned long long tmax;
55 bool running;
unsigned cnt;
56 Chrono() : acc(0), tmax(0), running(false), cnt(0) {}
57 void tic() { rdtscll(tprev); running =
true; ++cnt; }
59 if (!running)
return 0.; running =
false;
60 unsigned long long t; rdtscll(t);
62 acc += t; tmax = std::max(tmax, t);
63 return double(t)/2.8e9;
65 double total() {
return double(acc) / 2.8e9; }
66 double max() {
return double(tmax) / 2.8e9; }
67 double mean() {
return cnt ? total() / cnt : 0.; }
68 unsigned count() {
return cnt; }
71 Chrono interpolate_face_chrono;
74 static bool noisy =
false;
75 void getfem_mesh_level_set_noisy(
void) { noisy =
true; }
77 void mesh_level_set::clear(
void) {
79 is_adapted_ =
false; touch();
82 const dal::bit_vector &mesh_level_set::crack_tip_convexes()
const {
83 return crack_tip_convexes_;
86 void mesh_level_set::init_with_mesh(mesh &me) {
87 GMM_ASSERT1(linked_mesh_ == 0,
"mesh_level_set already initialized");
89 this->add_dependency(me);
93 mesh_level_set::mesh_level_set(mesh &me)
94 { linked_mesh_ = 0; init_with_mesh(me); }
96 mesh_level_set::mesh_level_set(
void)
97 { linked_mesh_ = 0; is_adapted_ =
false; }
100 mesh_level_set::~mesh_level_set() {}
103 mesh &m, dal::bit_vector& ptdone,
104 const std::vector<size_type>& ipts,
107 const std::vector<dal::bit_vector> &constraints,
108 const std::vector<
const
109 mesher_signed_distance *> &list_constraints) {
110 if (cvs->dim() == 0)
return;
111 else if (cvs->dim() > 1) {
112 std::vector<size_type> fpts;
113 for (
short_type f=0; f < cvs->nb_faces(); ++f) {
114 fpts.resize(cvs->nb_points_of_face(f));
115 for (
size_type k=0; k < fpts.size(); ++k)
116 fpts[k] = ipts[cvs->ind_points_of_face(f)[k]];
117 interpolate_face(pgt, m,ptdone,fpts,cvs->faces_structure()[f],
118 nb_vertices, constraints, list_constraints);
123 cout <<
"ipts.size() = " << ipts.size() << endl;
124 cout <<
" nb_vertices = " << nb_vertices << endl;
128 for (
size_type i=0; i < ipts.size(); ++i) {
130 if (ipts[i] < nb_vertices) {
132 cout <<
"point " << i <<
" coordinates "
133 << m.points()[ipts[i]] <<
" constraints[ipts[i]] = "
134 << constraints[ipts[i]] << endl;
135 if (cnt == 0) cts = constraints[ipts[i]];
136 else cts &= constraints[ipts[i]];
141 if (noisy) cout <<
"cts = " << cts << endl;
145 for (
size_type i=0; i < ipts.size(); ++i) {
146 if (ipts[i] >= nb_vertices && !ptdone[ipts[i]]) {
147 base_node P = m.points()[ipts[i]];
150 if (!pure_multi_constraint_projection(list_constraints, P, cts)) {
151 GMM_WARNING1(
"Pure multi has failed in interpolate_face !! "
152 "Original point " << m.points()[ipts[i]]
153 <<
" projection " << P);
155 if (pgt->convex_ref()->is_in(P) > 1E-8) {
156 GMM_WARNING1(
"Projected point outside the reference convex ! "
157 "Projection canceled. P = " << P);
158 }
else m.points()[ipts[i]] = P;
160 ptdone[ipts[i]] =
true;
171 std::vector<dal::bit_vector> constraints_;
172 std::vector<scalar_type> radius_;
173 const std::vector<const mesher_signed_distance*> &list_constraints;
174 scalar_type radius_cv;
176 void clear(
void) { points.
clear(); constraints_.clear();radius_.clear(); }
177 scalar_type radius(
size_type i)
const {
return radius_[i]; }
178 const dal::bit_vector &constraints(
size_type i)
const
179 {
return constraints_[i]; }
180 size_type size(
void)
const {
return points.size(); }
181 const base_node &operator[](
size_type i)
const {
return points[i]; }
183 size_type add(
const base_node &pt,
const dal::bit_vector &bv,
188 constraints_.push_back(bv);
189 radius_.push_back(r);
197 for (
size_type i = 0; i < list_constraints.size(); ++i)
198 if (gmm::abs((*(list_constraints[i]))(pt)) < 1E-8*radius_cv)
201 constraints_.push_back(bv);
202 radius_.push_back(r);
210 for (
size_type i = 0; i < list_constraints.size(); ++i)
211 if (gmm::abs((*(list_constraints[i]))(pt)) < 1E-8*radius_cv)
214 constraints_.push_back(bv);
215 scalar_type r = min_curvature_radius_estimate(list_constraints,pt,bv);
216 radius_.push_back(r);
221 dal::bit_vector decimate(
const mesher_signed_distance &ref_element,
222 scalar_type dmin)
const {
223 dal::bit_vector retained_points;
228 points_tree.reserve(size());
234 if (!(retained_points.is_in(i)) &&
235 (constraints(i).card() == nb_co ||
236 (nb_co == n && constraints(i).card() > n)) &&
237 ref_element(points[i]) < 1E-8) {
239 scalar_type d = (nb_co == 0) ? (dmin * 1.5)
240 : std::min(radius(i)*0.25, dmin);
241 base_node min = points[i], max = min;
242 for (
size_type m = 0; m < n; ++m) { min[m]-=d; max[m]+=d; }
244 points_tree.points_in_box(inpts, min, max);
245 for (
size_type j = 0; j < inpts.size(); ++j)
246 if (retained_points.is_in(inpts[j].i) &&
247 constraints(inpts[j].i).contains(constraints(i))
248 && gmm::vect_dist2(points[i], points[inpts[j].i]) < d)
249 { kept =
false;
break; }
251 if (noisy) cout <<
"kept point : " << points[i] <<
" co = "
252 << constraints(i) << endl;
253 retained_points.add(i);
259 return retained_points;
262 point_stock(
const std::vector<const mesher_signed_distance*> &ls,
264 : points(scalar_type(10000000)), list_constraints(ls),
270 dim_type n = pgt->structure()->dim();
271 size_type nbp = pgt->basic_structure()->nb_points();
275 return new_mesher_simplex_ref(n);
281 base_node rmin(n), rmax(n);
282 std::fill(rmax.begin(), rmax.end(), scalar_type(1));
283 return new_mesher_rectangle(rmin, rmax);
289 return new_mesher_prism_ref(n);
292 GMM_ASSERT1(
false,
"This element is not taken into account. Contact us");
296 struct global_mesh_for_mesh_level_set :
public mesh {};
297 static mesh& global_mesh() {
301 void mesh_level_set::run_delaunay(std::vector<base_node> &fixed_points,
302 gmm::dense_matrix<size_type> &simplexes,
303 std::vector<dal::bit_vector> &
305 double t0=gmm::uclock_sec();
306 if (noisy) cout <<
"running delaunay with " << fixed_points.size()
307 <<
" points.." << std::flush;
308 bgeot::qhull_delaunay(fixed_points, simplexes);
309 if (noisy) cout <<
" -> " << gmm::mat_ncols(simplexes)
310 <<
" simplexes [" << gmm::uclock_sec()-t0 <<
"sec]\n";
313 static bool intersects(
const mesh_level_set::zone &z1,
314 const mesh_level_set::zone &z2) {
315 for (std::set<const std::string *>::const_iterator it = z1.begin(); it != z1.end();
317 if (z2.find(*it) != z2.end())
return true;
321 void mesh_level_set::merge_zoneset(zoneset &zones1,
322 const zoneset &zones2)
const {
323 for (std::set<const zone *>::const_iterator it2 = zones2.begin();
324 it2 != zones2.end(); ++it2) {
326 for (std::set<const zone *>::iterator it1 = zones1.begin();
327 it1 != zones1.end(); ) {
328 if (intersects(z, *(*it1))) {
329 z.insert((*it1)->begin(), (*it1)->end());
334 zones1.insert(&(*(allzones.insert(z).first)));
339 static void add_sub_zones_no_zero(std::string &s,
340 mesh_level_set::zone &z,
341 std::set<std::string> &allsubzones) {
342 size_t i = s.find(
'0');
343 if (i !=
size_t(-1)) {
344 s[i] =
'+'; add_sub_zones_no_zero(s, z, allsubzones);
345 s[i] =
'-'; add_sub_zones_no_zero(s, z, allsubzones);
347 z.insert(&(*(allsubzones.insert(s).first)));
351 void mesh_level_set::merge_zoneset(zoneset &zones1,
352 const std::string &subz)
const {
354 zone z; std::string s(subz);
355 add_sub_zones_no_zero(s, z, allsubzones);
357 zs.insert(&(*(allzones.insert(z).first)));
358 merge_zoneset(zones1, zs);
364 void mesh_level_set::find_zones_of_element(
size_type cv,
365 std::string &prezone,
366 scalar_type radius) {
367 convex_info &cvi = cut_cv[cv];
369 for (dal::bv_visitor i(cvi.pmsh->convex_index()); !i.finished();++i) {
371 if (cvi.pmsh->convex_area_estimate(i) > 1e-8) {
372 std::string subz = prezone;
374 for (
size_type j = 0; j < level_sets.size(); ++j) {
375 if (subz[j] ==
'*' || subz[j] ==
'0') {
376 int s = sub_simplex_is_not_crossed_by(cv, level_sets[j], i,radius);
378 subz[j] = (s < 0) ?
'-' : ((s > 0) ?
'+' :
'0');
381 merge_zoneset(cvi.zones, subz);
384 if (noisy) cout <<
"Number of zones for convex " << cv <<
" : "
385 << cvi.zones.size() << endl;
389 void mesh_level_set::cut_element(
size_type cv,
390 const dal::bit_vector &primary,
391 const dal::bit_vector &secondary,
392 scalar_type radius_cv) {
394 cut_cv[cv] = convex_info();
395 cut_cv[cv].pmsh = std::make_shared<mesh>();
396 if (noisy) cout <<
"cutting element " << cv << endl;
398 pmesher_signed_distance ref_element = new_ref_element(pgt);
399 std::vector<pmesher_signed_distance> mesher_level_sets;
402 size_type nbtotls = primary.card() + secondary.card();
404 GMM_ASSERT1(nbtotls <= 16,
405 "An element is cut by more than 16 level_set, aborting");
412 scalar_type r0 = 1E+10;
413 std::vector<const mesher_signed_distance*> list_constraints;
414 point_stock mesh_points(list_constraints, radius_cv);
416 ref_element->register_constraints(list_constraints);
417 size_type nbeltconstraints = list_constraints.size();
418 mesher_level_sets.reserve(nbtotls);
419 for (
size_type ll = 0; ll < level_sets.size(); ++ll) {
422 K = std::max(K, (level_sets[ll])->degree());
423 mesher_level_sets.push_back(level_sets[ll]->mls_of_convex(cv, 0));
424 pmesher_signed_distance mls(mesher_level_sets.back());
425 list_constraints.push_back(mesher_level_sets.back().get());
426 r0 = std::min(r0, curvature_radius_estimate(*mls, X,
true));
427 GMM_ASSERT1(gmm::abs(r0) >= 1e-13,
"Something wrong in your level "
428 "set ... curvature radius = " << r0);
430 mesher_level_sets.push_back(level_sets[ll]->mls_of_convex(cv, 1));
431 pmesher_signed_distance mls2(mesher_level_sets.back());
432 list_constraints.push_back(mesher_level_sets.back().get());
433 r0 = std::min(r0, curvature_radius_estimate(*mls2, X,
true));
441 scalar_type h0 = std::min(1./(K+1), 0.2 * r0), dmin = 0.55;
442 bool h0_is_ok =
true;
448 scalar_type geps = .001*h0;
450 std::vector<size_type> gridnx(n);
452 { gridnx[i]=1+(
size_type)(1./h0); nbpt *= gridnx[i]; }
453 base_node P(n), Q(n), V(n);
455 std::vector<size_type> co_v;
459 unsigned p = unsigned(r % gridnx[k]);
460 P[k] = p * scalar_type(1) / scalar_type(gridnx[k]-1);
463 co.clear(); co_v.resize(0);
464 if ((*ref_element)(P) < geps) {
470 scalar_type d = list_constraints[k]->grad(P, V);
471 if (gmm::vect_norm2(V)*h0*7 > gmm::abs(d))
472 if (try_projection(*(list_constraints[k]), Q,
true)) {
473 if (k >= nbeltconstraints
474 && gmm::vect_dist2(P, Q) < h0 * 3.5) kept =
true;
475 if (gmm::vect_dist2(P, Q) < h0 / 1.5) {
476 co.add(k); co_v.push_back(k);
477 if ((*ref_element)(Q) < 1E-8) {
479 curvature_radius_estimate(*(list_constraints[k]), Q);
480 r0 = std::min(r0, r);
481 if (r0 < 4.*h0) { h0 = 0.2 * r0; h0_is_ok =
false;
break; }
482 if (k >= nbeltconstraints || kept) mesh_points.add(Q, r);
487 if (kept) mesh_points.add(P, 1.E10);
495 if (count & (
size_type(1) << j)) nn.add(co_v[j]);
496 if (nn.card() > 1 && nn.card() <= n) {
497 if (noisy) cout <<
"trying set of constraints" << nn << endl;
499 bool ok=pure_multi_constraint_projection(list_constraints,Q,nn);
500 if (ok && (*ref_element)(Q) < 1E-9) {
501 if (noisy) cout <<
"Intersection point found " << Q <<
" with "
509 if (!h0_is_ok)
continue;
517 if (noisy) cout <<
"dmin = " << dmin <<
" h0 = " << h0 << endl;
518 if (noisy) cout <<
"convex " << cv << endl;
520 dal::bit_vector retained_points
521 = mesh_points.decimate(*ref_element, dmin);
523 bool delaunay_again =
true;
525 std::vector<base_node> fixed_points;
526 std::vector<dal::bit_vector> fixed_points_constraints;
527 mesh &msh(*(cut_cv[cv].pmsh));
529 mesh_region &ls_border_faces(cut_cv[cv].ls_border_faces);
530 std::vector<base_node> cvpts;
534 while (delaunay_again) {
535 if (++nb_delaunay > 15)
536 { h0_is_ok =
false; h0 /= 2.0; dmin = 2.*h0;
break; }
538 fixed_points.resize(0);
539 fixed_points_constraints.resize(0);
542 fixed_points.reserve(retained_points.card());
543 fixed_points_constraints.reserve(retained_points.card());
544 for (dal::bv_visitor i(retained_points); !i.finished(); ++i) {
545 fixed_points.push_back(mesh_points[i]);
546 fixed_points_constraints.push_back(mesh_points.constraints(i));
549 gmm::dense_matrix<size_type> simplexes;
550 run_delaunay(fixed_points, simplexes, fixed_points_constraints);
551 delaunay_again =
false;
555 for (
size_type i = 0; i < fixed_points.size(); ++i) {
556 size_type j = msh.add_point(fixed_points[i]);
561 for (
size_type i = 0; i < gmm::mat_ncols(simplexes); ++i) {
562 size_type j = msh.add_convex(bgeot::simplex_geotrans(n,1),
563 gmm::vect_const_begin(gmm::mat_col(simplexes, i)));
565 if (msh.convex_quality_estimate(j) < 1E-10) msh.sup_convex(j);
567 std::vector<scalar_type> signs(list_constraints.size());
568 std::vector<size_type> prev_point(list_constraints.size());
570 for (
size_type jj = 0; jj < list_constraints.size(); ++jj) {
572 (*(list_constraints[jj]))(msh.points_of_convex(j)[ii]);
573 if (gmm::abs(dd) > radius_cv * 1E-7) {
574 if (dd * signs[jj] < 0.0) {
575 if (noisy) cout <<
"Intersection found ... " << jj
576 <<
" dd = " << dd <<
" convex quality = "
577 << msh.convex_quality_estimate(j) <<
"\n";
579 base_node X = msh.points_of_convex(j)[ii], G;
580 base_node VV = msh.points_of_convex(j)[prev_point[jj]] - X;
581 if (dd > 0.) gmm::scale(VV, -1.);
582 dd = (*(list_constraints[jj])).grad(X, G);
584 while (gmm::abs(dd) > 1e-16*radius_cv && (++nbit < 20)) {
586 if (gmm::abs(nG) < 1E-8) nG = 1E-8;
587 if (nG < 0) nG = 1.0;
588 gmm::add(gmm::scaled(VV, -dd / nG), X);
589 dd = (*(list_constraints[jj])).grad(X, G);
591 if (gmm::abs(dd) > 1e-16*radius_cv) {
592 base_node X1 = msh.points_of_convex(j)[ii];
593 base_node X2 = msh.points_of_convex(j)[prev_point[jj]], X3;
594 scalar_type dd1 = (*(list_constraints[jj]))(X1);
595 scalar_type dd2 = (*(list_constraints[jj]))(X2);
596 if (dd1 > dd2) { std::swap(dd1, dd2); std::swap(X1, X2); }
597 while (gmm::abs(dd1) > 1e-15*radius_cv) {
598 X3 = (X1 + X2) / 2.0;
599 scalar_type dd3 = (*(list_constraints[jj]))(X3);
600 if (dd3 == dd1 || dd3 == dd2)
break;
601 if (dd3 > 0) { dd2 = dd3; X2 = X3; }
602 else { dd1 = dd3; X1 = X3; }
608 if (!(retained_points[kk])) {
609 retained_points.add(kk);
610 delaunay_again =
true;
615 if (signs[jj] == 0.0) { signs[jj] = dd; prev_point[jj] = ii; }
625 if (!h0_is_ok)
continue;
629 for (dal::bv_visitor_c j(msh.convex_index()); !j.finished(); ++j) {
631 cvpts.resize(pgt2->nb_points());
632 for (
size_type k=0; k < pgt2->nb_points(); ++k) {
633 cvpts[k] = bgeot::simplex_geotrans(n,1)->transform
634 (pgt2->convex_ref()->points()[k], msh.points_of_convex(j));
639 size_type jj = msh.add_convex_by_points(pgt2, cvpts.begin());
647 char s[512]; snprintf(s, 511,
"totobefore%d.dx",
int(cv));
650 exp.exporting_mesh_edges();
656 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
658 const mesh::ind_pt_face_ct &fpts
659 = msh.ind_points_of_face_of_convex(i, f);
661 dal::bit_vector cts;
bool first =
true;
662 for (
unsigned k=0; k < fpts.size(); ++k) {
663 if (fpts[k] >= fixed_points_constraints.size()) {
667 if (first) { cts = fixed_points_constraints[fpts[k]]; first=
false; }
668 else cts &= fixed_points_constraints[fpts[k]];
670 for (dal::bv_visitor ii(cts); !ii.finished(); ++ii) {
671 if (ii >= nbeltconstraints)
672 ls_border_faces.add(i, f);
679 dal::bit_vector ptdone;
680 std::vector<size_type> ipts;
684 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
686 const mesh::ind_pt_face_ct &fpts
687 = msh.ind_points_of_face_of_convex(i, f);
688 ipts.assign(fpts.begin(), fpts.end());
690 interpolate_face_chrono.tic();
693 interpolate_face(pgt, msh, ptdone, ipts,
694 msh.trans_of_convex(i)->structure()
695 ->faces_structure()[f], fixed_points.size(),
696 fixed_points_constraints, list_constraints);
698 interpolate_face_chrono.toc();
707 char s[512]; snprintf(s, 511,
"toto%d.dx",
int(cv));
710 exp.exporting_mesh_edges();
721 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
722 base_matrix KK(n,n), CS(n,n);
723 base_matrix pc(pgt2->nb_points(), n);
724 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
725 vectors_to_base_matrix(G, msh.points_of_convex(i));
728 scalar_type sign = 0.0;
729 for (
size_type j = 0; j < pai->nb_points_on_convex(); ++j) {
730 c.set_xref(pai->point(j));
731 pgt2->poly_vector_grad(pai->point(j), pc);
734 if (noisy && J * sign < 0) {
735 cout <<
"CAUTION reversal situation in convex " << i
736 <<
"sign = " << sign <<
" J = " << J << endl;
737 for (
size_type nip = 0; nip < msh.nb_points_of_convex(i); ++nip)
738 cout <<
"Point " << nip <<
"=" << msh.points_of_convex(i)[nip]
742 if (sign == 0 && gmm::abs(J) > 1E-14) sign = J;
743 new_approx->add_point(c.xreal(), pai->coeff(j) * gmm::abs(J));
750 vectors_to_base_matrix(G, msh.points_of_convex(it.cv()));
753 for (
size_type j = 0; j < pai->nb_points_on_face(it.f()); ++j) {
754 c.set_xref(pai->point_on_face(it.f(), j));
755 new_approx->add_point(c.xreal(), pai->coeff_on_face(it.f(), j)
756 * gmm::abs(c.J()), it.f() );
759 new_approx->valid_method();
765 scalar_type error = test_integration_error(new_approx, 1);
766 if (noisy) cout <<
" max monomial integration err: " << error <<
"\n";
768 if (noisy) cout <<
"Not Good ! Let us make a finer cut.\n";
769 if (dmin > 3*h0) { dmin /= 2.; }
770 else { h0 /= 2.0; dmin = 2.*h0; }
775 if (h0_is_ok && noisy) {
776 vectors_to_base_matrix(G,
linked_mesh().points_of_convex(cv));
777 std::vector<size_type> pts(msh.nb_points());
778 for (
size_type i = 0; i < msh.nb_points(); ++i)
779 pts[i] = global_mesh().add_point(pgt->transform(msh.points()[i], G));
781 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i)
782 global_mesh().
add_convex(msh.trans_of_convex(i),
783 gmm::index_ref_iterator(pts.begin(),
784 msh.ind_points_of_convex(i).begin()));
790 cout <<
"Interpolate face: " << interpolate_face_chrono.total()
791 <<
" moyenne: " << interpolate_face_chrono.mean() <<
"\n";
799 for (dal::bv_visitor cv(
linked_mesh().convex_index());
800 !cv.finished(); ++cv) {
801 if (is_convex_cut(cv)) {
802 const convex_info &ci = (cut_cv.find(cv))->second;
803 mesh &msh = *(ci.pmsh);
805 vectors_to_base_matrix(G,
linked_mesh().points_of_convex(cv));
806 std::vector<size_type> pts(msh.
nb_points());
808 pts[i] = m.add_point(pgt->transform(msh.points()[i], G));
812 for (dal::bv_visitor i(msh.
convex_index()); !i.finished(); ++i) {
814 gmm::index_ref_iterator(pts.begin(),
818 for (
mr_visitor i(ci.ls_border_faces); !i.finished(); ++i) {
819 m.
region(0).add(ic2[i.cv()], i.f());
831 void mesh_level_set::update_crack_tip_convexes() {
832 crack_tip_convexes_.clear();
834 for (std::map<size_type, convex_info>::const_iterator it = cut_cv.begin();
835 it != cut_cv.end(); ++it) {
837 mesh &msh = *(it->second.pmsh);
839 if (get_level_set(ils)->has_secondary()) {
840 pmesher_signed_distance
841 mesherls0 = get_level_set(ils)->mls_of_convex(cv, 0,
false);
842 pmesher_signed_distance
843 mesherls1 = get_level_set(ils)->mls_of_convex(cv, 1,
false);
844 for (dal::bv_visitor ii(msh.
convex_index()); !ii.finished(); ++ii) {
846 if (gmm::abs((*mesherls0)(msh.points_of_convex(ii)[ipt])) < 1E-10
847 && gmm::abs((*mesherls1)(msh.points_of_convex(ii)[ipt])) < 1E-10) {
848 crack_tip_convexes_.add(cv);
865 GMM_ASSERT1(linked_mesh_ != 0,
"Uninitialized mesh_level_set");
868 zones_of_convexes.
clear();
874 for (dal::bv_visitor cv(
linked_mesh().convex_index());
875 !cv.finished(); ++cv) {
877 dal::bit_vector prim, sec;
878 find_crossing_level_set(cv, prim, sec, z, radius);
879 zones_of_convexes[cv] = &(*(allsubzones.insert(z).first));
880 if (noisy) cout <<
"element " << cv <<
" cut level sets : "
881 << prim <<
" zone : " << z << endl;
883 cut_element(cv, prim, sec, radius);
884 find_zones_of_element(cv, z, radius);
896 update_crack_tip_convexes();
902 void mesh_level_set::find_level_set_potential_intersections
903 (std::vector<size_type> &icv, std::vector<dal::bit_vector> &ils) {
905 GMM_ASSERT1(linked_mesh_ != 0,
"Uninitialized mesh_level_set");
907 for (dal::bv_visitor cv(
linked_mesh().convex_index());
908 !cv.finished(); ++cv)
909 if (is_convex_cut(cv)) {
911 dal::bit_vector prim, sec;
912 find_crossing_level_set(cv, prim, sec, z, radius);
913 if (prim.card() > 1) {
924 int mesh_level_set::sub_simplex_is_not_crossed_by(
size_type cv,
927 scalar_type radius) {
928 scalar_type EPS = 1e-7 * radius;
930 convex_info &cvi = cut_cv[cv];
935 pmesher_signed_distance mls0 = ls->mls_of_convex(cv, 0), mls1(mls0);
936 if (ls->has_secondary()) mls1 = ls->mls_of_convex(cv, 1);
939 scalar_type d2 = 0, d1 = 1, d0 = 0, d0min = 0;
940 for (
size_type i = 0; i < pgt2->nb_points(); ++i) {
941 d0 = (*mls0)(cvi.pmsh->points_of_convex(sub_cv)[i]);
942 if (i == 0) d0min = gmm::abs(d0);
943 else d0min = std::min(d0min, gmm::abs(d0));
944 if (ls->has_secondary())
945 d1 = std::min(d1, (*mls1)(cvi.pmsh->points_of_convex(sub_cv)[i]));
947 int p2 = ( (d0 < -EPS) ? -1 : ((d0 > EPS) ? +1 : 0));
949 if (gmm::abs(d0) > gmm::abs(d2)) d2 = d0;
950 if (!p2 || p*p2 < 0) is_cut =
true;
954 if (is_cut && ls->has_secondary() && d1 >= -radius*0.0001)
return 0;
956 return (d2 < 0.) ? -1 : 1;
959 int mesh_level_set::is_not_crossed_by(
size_type cv, plevel_set ls,
960 unsigned lsnum, scalar_type radius) {
961 const mesh_fem &mf = ls->get_mesh_fem();
962 GMM_ASSERT1(!mf.is_reduced(),
"Internal error");
963 const mesh_fem::ind_dof_ct &dofs = mf.ind_basic_dof_of_element(cv);
964 pfem pf = mf.fem_of_element(cv);
966 scalar_type EPS = 1e-8 * radius;
973 for (mesh_fem::ind_dof_ct::const_iterator it=dofs.begin();
974 it != dofs.end(); ++it) {
975 scalar_type v = ls->values(lsnum)[*it];
976 int p2 = ( (v < -EPS) ? -1 : ((v > EPS) ? +1 : 0));
978 if (!p2 || p*p2 < 0)
return 0;
981 pmesher_signed_distance mls1 = ls->mls_of_convex(cv, lsnum,
false);
982 base_node X(pf->dim()), G(pf->dim());
984 scalar_type d = mls1->grad(X, G);
985 if (gmm::vect_norm2(G)*2.5 < gmm::abs(d))
return p;
988 pmesher_signed_distance ref_element = new_ref_element(pgt);
991 mesher_intersection mi1(ref_element, mls1);
992 if (!try_projection(mi1, X))
return p;
993 if ((*ref_element)(X) > 1E-8)
return p;
996 pmesher_signed_distance mls2 = ls->mls_of_convex(cv, lsnum,
true);
997 mesher_intersection mi2(ref_element, mls2);
998 if (!try_projection(mi2, X))
return p;
999 if ((*ref_element)(X) > 1E-8)
return p;
1004 void mesh_level_set::find_crossing_level_set(
size_type cv,
1005 dal::bit_vector &prim,
1006 dal::bit_vector &sec,
1008 scalar_type radius) {
1009 prim.clear(); sec.clear();
1010 z = std::string(level_sets.size(),
'*');
1012 for (
size_type k = 0; k < level_sets.size(); ++k, ++lsnum) {
1013 if (noisy) cout <<
"testing cv " << cv <<
" with level set "
1015 int s = is_not_crossed_by(cv, level_sets[k], 0, radius);
1017 if (noisy) cout <<
"is cut \n";
1018 if (level_sets[k]->has_secondary()) {
1019 s = is_not_crossed_by(cv, level_sets[k], 1, radius);
1020 if (!s) { sec.add(lsnum); prim.add(lsnum); }
1021 else if (s < 0) prim.add(lsnum);
else z[k] =
'0';
1023 else prim.add(lsnum);
1025 else z[k] = (s < 0) ?
'-' :
'+';
the geotrans_interpolation_context structure is passed as the argument of geometric transformation in...
Balanced tree over a set of points.
void add_point_with_id(const base_node &n, size_type i)
insert a new point, with an associated number.
short_type nb_points_of_convex(size_type ic) const
Return the number of points of convex ic.
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
const ind_set & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
size_type nb_allocated_convex() const
The number of convex indexes from 0 to the index of the last convex.
Store a set of points, identifying points that are nearer than a certain very small distance.
void clear()
reset the array, remove all points
size_type search_node(const base_node &pt, const scalar_type radius=0) const
Search a node in the array.
size_type add_node(const base_node &pt, const scalar_type radius=0, bool remove_duplicated_nodes=true)
Add a point to the array or use an existing point, located within a distance smaller than radius.
void clear(void)
Clear and desallocate all the elements.
static T & instance()
Instance from the current thread.
A (quite large) class for exportation of data to IBM OpenDX.
void exporting_mesh_edges(bool with_slice_edge=true)
append edges information (if you want to draw the mesh and are using a refined slice.
void global_cut_mesh(mesh &m) const
fill m with the (non-conformal) "cut" mesh.
size_type nb_level_sets(void) const
Get number of level-sets referenced in this object.
void adapt(void)
do all the work (cut the convexes wrt the levelsets)
mesh & linked_mesh(void) const
Gives a reference to the linked mesh of type mesh.
"iterator" class for regions.
structure used to hold a set of convexes and/or convex faces.
Describe a mesh (collection of convexes (elements) and points).
virtual scalar_type convex_radius_estimate(size_type ic) const
Return an estimate of the convex largest dimension.
size_type nb_points() const
Give the number of geometrical nodes in the mesh.
const mesh_region region(size_type id) const
Return the region of index 'id'.
size_type add_convex(bgeot::pgeometric_trans pgt, ITER ipts)
Add a convex to the mesh.
void clear()
Erase the mesh.
This slicer does nothing.
The output of a getfem::mesh_slicer which has been recorded.
void build(const getfem::mesh &m, const slicer_action &a, size_type nrefine=1)
Build the slice, by applying a slicer_action operation.
Keep informations about a mesh crossed by level-sets.
void copy(const L1 &l1, L2 &l2)
*/
void fill_random(L &l)
fill a vector or matrix with random value (uniform [-1,1]).
void clear(L &l)
clear (fill with zeros) a vector or matrix.
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
strongest_value_type< V1, V2 >::value_type vect_sp(const V1 &v1, const V2 &v2)
*/
void add(const L1 &l1, L2 &l2)
*/
linalg_traits< DenseMatrixLU >::value_type lu_det(const DenseMatrixLU &LU, const Pvector &pvector)
Compute the matrix determinant (via a LU factorization)
size_type add_convex_by_points(bgeot::pgeometric_trans pgt, ITER ipts, const scalar_type tol=scalar_type(0))
Add a convex to the mesh, given a geometric transformation and a list of point coordinates.
void APIDECL outer_faces_of_mesh(const mesh &m, const dal::bit_vector &cvlst, convex_face_ct &flist)
returns a list of "exterior" faces of a mesh (i.e.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
std::vector< index_node_pair > kdtree_tab_type
store a set of points with associated indexes.
gmm::uint16_type short_type
used as the common short type integer in the library
std::ostream & operator<<(std::ostream &o, const convex_structure &cv)
Print the details of the convex structure cvs to the output stream o.
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
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.
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
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
GEneric Tool for Finite Element Methods.
pintegration_method classical_approx_im(bgeot::pgeometric_trans pgt, dim_type degree)
try to find an approximate integration method for the geometric transformation pgt which is able to i...
pintegration_method classical_exact_im(bgeot::pgeometric_trans pgt)
return an exact integration method for convex type handled by pgt.