27 std::ostream &
operator<<(std::ostream &os,
const mesh_level_set::zone &z) {
29 for (mesh_level_set::zone::const_iterator it = z.begin();
30 it != z.end(); ++it) {
31 if (it != z.begin()) os <<
", ";
38 std::ostream &
operator<<(std::ostream &os,
const mesh_level_set::zoneset &zs) {
40 for (mesh_level_set::zoneset::const_iterator it = zs.begin();
41 it != zs.end(); ++it) {
42 if (it != zs.begin()) os <<
"; ";
53 unsigned long long tprev;
54 unsigned long long acc;
55 unsigned long long tmax;
56 bool running;
unsigned cnt;
57 Chrono() : acc(0), tmax(0), running(false), cnt(0) {}
58 void tic() { rdtscll(tprev); running =
true; ++cnt; }
60 if (!running)
return 0.; running =
false;
61 unsigned long long t; rdtscll(t);
63 acc += t; tmax = std::max(tmax, t);
64 return double(t)/2.8e9;
66 double total() {
return double(acc) / 2.8e9; }
67 double max() {
return double(tmax) / 2.8e9; }
68 double mean() {
return cnt ? total() / cnt : 0.; }
69 unsigned count() {
return cnt; }
72 Chrono interpolate_face_chrono;
75 static bool noisy =
false;
76 void getfem_mesh_level_set_noisy(
void) { noisy =
true; }
78 void mesh_level_set::clear(
void) {
80 is_adapted_ =
false; touch();
83 const dal::bit_vector &mesh_level_set::crack_tip_convexes()
const {
84 return crack_tip_convexes_;
87 void mesh_level_set::init_with_mesh(mesh &me) {
88 GMM_ASSERT1(linked_mesh_ == 0,
"mesh_level_set already initialized");
94 mesh_level_set::mesh_level_set(mesh &me)
95 { linked_mesh_ = 0; init_with_mesh(me); }
97 mesh_level_set::mesh_level_set(
void)
98 { linked_mesh_ = 0; is_adapted_ =
false; }
101 mesh_level_set::~mesh_level_set() {}
104 mesh &m, dal::bit_vector& ptdone,
105 const std::vector<size_type>& ipts,
108 const std::vector<dal::bit_vector> &constraints,
109 const std::vector<
const 110 mesher_signed_distance *> &list_constraints) {
111 if (cvs->dim() == 0)
return;
112 else if (cvs->dim() > 1) {
113 std::vector<size_type> fpts;
114 for (
short_type f=0; f < cvs->nb_faces(); ++f) {
115 fpts.resize(cvs->nb_points_of_face(f));
116 for (
size_type k=0; k < fpts.size(); ++k)
117 fpts[k] = ipts[cvs->ind_points_of_face(f)[k]];
118 interpolate_face(pgt, m,ptdone,fpts,cvs->faces_structure()[f],
119 nb_vertices, constraints, list_constraints);
124 cout <<
"ipts.size() = " << ipts.size() << endl;
125 cout <<
" nb_vertices = " << nb_vertices << endl;
129 for (
size_type i=0; i < ipts.size(); ++i) {
131 if (ipts[i] < nb_vertices) {
133 cout <<
"point " << i <<
" coordinates " 134 << m.points()[ipts[i]] <<
" constraints[ipts[i]] = " 135 << constraints[ipts[i]] << endl;
136 if (cnt == 0) cts = constraints[ipts[i]];
137 else cts &= constraints[ipts[i]];
142 if (noisy) cout <<
"cts = " << cts << endl;
146 for (
size_type i=0; i < ipts.size(); ++i) {
147 if (ipts[i] >= nb_vertices && !ptdone[ipts[i]]) {
148 base_node P = m.points()[ipts[i]];
151 if (!pure_multi_constraint_projection(list_constraints, P, cts)) {
152 GMM_WARNING1(
"Pure multi has failed in interpolate_face !! " 153 "Original point " << m.points()[ipts[i]]
154 <<
" projection " << P);
156 if (pgt->convex_ref()->is_in(P) > 1E-8) {
157 GMM_WARNING1(
"Projected point outside the reference convex ! " 158 "Projection canceled. P = " << P);
159 }
else m.points()[ipts[i]] = P;
161 ptdone[ipts[i]] =
true;
172 std::vector<dal::bit_vector> constraints_;
173 std::vector<scalar_type> radius_;
174 const std::vector<const mesher_signed_distance*> &list_constraints;
175 scalar_type radius_cv;
177 void clear(
void) { points.
clear(); constraints_.clear();radius_.clear(); }
178 scalar_type radius(
size_type i)
const {
return radius_[i]; }
179 const dal::bit_vector &constraints(
size_type i)
const 180 {
return constraints_[i]; }
181 size_type size(
void)
const {
return points.size(); }
182 const base_node &operator[](
size_type i)
const {
return points[i]; }
184 size_type add(
const base_node &pt,
const dal::bit_vector &bv,
189 constraints_.push_back(bv);
190 radius_.push_back(r);
198 for (
size_type i = 0; i < list_constraints.size(); ++i)
199 if (gmm::abs((*(list_constraints[i]))(pt)) < 1E-8*radius_cv)
202 constraints_.push_back(bv);
203 radius_.push_back(r);
211 for (
size_type i = 0; i < list_constraints.size(); ++i)
212 if (gmm::abs((*(list_constraints[i]))(pt)) < 1E-8*radius_cv)
215 constraints_.push_back(bv);
216 scalar_type r = min_curvature_radius_estimate(list_constraints,pt,bv);
217 radius_.push_back(r);
222 dal::bit_vector decimate(
const mesher_signed_distance &ref_element,
223 scalar_type dmin)
const {
224 dal::bit_vector retained_points;
229 points_tree.reserve(size());
235 if (!(retained_points.is_in(i)) &&
236 (constraints(i).card() == nb_co ||
237 (nb_co == n && constraints(i).card() > n)) &&
238 ref_element(points[i]) < 1E-8) {
240 scalar_type d = (nb_co == 0) ? (dmin * 1.5)
241 : std::min(radius(i)*0.25, dmin);
242 base_node min = points[i], max = min;
243 for (
size_type m = 0; m < n; ++m) { min[m]-=d; max[m]+=d; }
245 points_tree.points_in_box(inpts, min, max);
246 for (
size_type j = 0; j < inpts.size(); ++j)
247 if (retained_points.is_in(inpts[j].i) &&
248 constraints(inpts[j].i).contains(constraints(i))
250 { kept =
false;
break; }
252 if (noisy) cout <<
"kept point : " << points[i] <<
" co = " 253 << constraints(i) << endl;
254 retained_points.add(i);
260 return retained_points;
263 point_stock(
const std::vector<const mesher_signed_distance*> &ls,
265 : points(scalar_type(10000000)), list_constraints(ls),
271 dim_type n = pgt->structure()->dim();
272 size_type nbp = pgt->basic_structure()->nb_points();
276 return new_mesher_simplex_ref(n);
282 base_node rmin(n), rmax(n);
283 std::fill(rmax.begin(), rmax.end(), scalar_type(1));
284 return new_mesher_rectangle(rmin, rmax);
290 return new_mesher_prism_ref(n);
293 GMM_ASSERT1(
false,
"This element is not taken into account. Contact us");
297 struct global_mesh_for_mesh_level_set :
public mesh {};
298 static mesh& global_mesh() {
302 void mesh_level_set::run_delaunay(std::vector<base_node> &fixed_points,
303 gmm::dense_matrix<size_type> &simplexes,
304 std::vector<dal::bit_vector> &
306 double t0=gmm::uclock_sec();
307 if (noisy) cout <<
"running delaunay with " << fixed_points.size()
308 <<
" points.." << std::flush;
309 bgeot::qhull_delaunay(fixed_points, simplexes);
310 if (noisy) cout <<
" -> " << gmm::mat_ncols(simplexes)
311 <<
" simplexes [" << gmm::uclock_sec()-t0 <<
"sec]\n";
314 static bool intersects(
const mesh_level_set::zone &z1,
315 const mesh_level_set::zone &z2) {
316 for (std::set<const std::string *>::const_iterator it = z1.begin(); it != z1.end();
318 if (z2.find(*it) != z2.end())
return true;
322 void mesh_level_set::merge_zoneset(zoneset &zones1,
323 const zoneset &zones2)
const {
324 for (std::set<const zone *>::const_iterator it2 = zones2.begin();
325 it2 != zones2.end(); ++it2) {
327 for (std::set<const zone *>::iterator it1 = zones1.begin();
328 it1 != zones1.end(); ) {
329 if (intersects(z, *(*it1))) {
330 z.insert((*it1)->begin(), (*it1)->end());
335 zones1.insert(&(*(allzones.insert(z).first)));
340 static void add_sub_zones_no_zero(std::string &s,
341 mesh_level_set::zone &z,
342 std::set<std::string> &allsubzones) {
343 size_t i = s.find(
'0');
344 if (i !=
size_t(-1)) {
345 s[i] =
'+'; add_sub_zones_no_zero(s, z, allsubzones);
346 s[i] =
'-'; add_sub_zones_no_zero(s, z, allsubzones);
348 z.insert(&(*(allsubzones.insert(s).first)));
352 void mesh_level_set::merge_zoneset(zoneset &zones1,
353 const std::string &subz)
const {
355 zone z; std::string s(subz);
356 add_sub_zones_no_zero(s, z, allsubzones);
358 zs.insert(&(*(allzones.insert(z).first)));
359 merge_zoneset(zones1, zs);
365 void mesh_level_set::find_zones_of_element(
size_type cv,
366 std::string &prezone,
367 scalar_type radius) {
368 convex_info &cvi = cut_cv[cv];
370 for (dal::bv_visitor i(cvi.pmsh->convex_index()); !i.finished();++i) {
372 if (cvi.pmsh->convex_area_estimate(i) > 1e-8) {
373 std::string subz = prezone;
375 for (
size_type j = 0; j < level_sets.size(); ++j) {
376 if (subz[j] ==
'*' || subz[j] ==
'0') {
377 int s = sub_simplex_is_not_crossed_by(cv, level_sets[j], i,radius);
379 subz[j] = (s < 0) ?
'-' : ((s > 0) ?
'+' :
'0');
382 merge_zoneset(cvi.zones, subz);
385 if (noisy) cout <<
"Number of zones for convex " << cv <<
" : " 386 << cvi.zones.size() << endl;
390 void mesh_level_set::cut_element(
size_type cv,
391 const dal::bit_vector &primary,
392 const dal::bit_vector &secondary,
393 scalar_type radius_cv) {
395 cut_cv[cv] = convex_info();
396 cut_cv[cv].pmsh = std::make_shared<mesh>();
397 if (noisy) cout <<
"cutting element " << cv << endl;
399 pmesher_signed_distance ref_element = new_ref_element(pgt);
400 std::vector<pmesher_signed_distance> mesher_level_sets;
403 size_type nbtotls = primary.card() + secondary.card();
405 GMM_ASSERT1(nbtotls <= 16,
406 "An element is cut by more than 16 level_set, aborting");
413 scalar_type r0 = 1E+10;
414 std::vector<const mesher_signed_distance*> list_constraints;
415 point_stock mesh_points(list_constraints, radius_cv);
417 ref_element->register_constraints(list_constraints);
418 size_type nbeltconstraints = list_constraints.size();
419 mesher_level_sets.reserve(nbtotls);
420 for (
size_type ll = 0; ll < level_sets.size(); ++ll) {
423 K = std::max(K, (level_sets[ll])->degree());
424 mesher_level_sets.push_back(level_sets[ll]->mls_of_convex(cv, 0));
425 pmesher_signed_distance mls(mesher_level_sets.back());
426 list_constraints.push_back(mesher_level_sets.back().get());
427 r0 = std::min(r0, curvature_radius_estimate(*mls, X,
true));
428 GMM_ASSERT1(gmm::abs(r0) >= 1e-13,
"Something wrong in your level " 429 "set ... curvature radius = " << r0);
431 mesher_level_sets.push_back(level_sets[ll]->mls_of_convex(cv, 1));
432 pmesher_signed_distance mls2(mesher_level_sets.back());
433 list_constraints.push_back(mesher_level_sets.back().get());
434 r0 = std::min(r0, curvature_radius_estimate(*mls2, X,
true));
442 scalar_type h0 = std::min(1./(K+1), 0.2 * r0), dmin = 0.55;
443 bool h0_is_ok =
true;
449 scalar_type geps = .001*h0;
451 std::vector<size_type> gridnx(n);
453 { gridnx[i]=1+(
size_type)(1./h0); nbpt *= gridnx[i]; }
454 base_node P(n), Q(n), V(n);
456 std::vector<size_type> co_v;
460 unsigned p = unsigned(r % gridnx[k]);
461 P[k] = p * scalar_type(1) / scalar_type(gridnx[k]-1);
464 co.clear(); co_v.resize(0);
465 if ((*ref_element)(P) < geps) {
471 scalar_type d = list_constraints[k]->grad(P, V);
472 if (gmm::vect_norm2(V)*h0*7 > gmm::abs(d))
473 if (try_projection(*(list_constraints[k]), Q,
true)) {
474 if (k >= nbeltconstraints
475 && gmm::vect_dist2(P, Q) < h0 * 3.5) kept =
true;
476 if (gmm::vect_dist2(P, Q) < h0 / 1.5) {
477 co.add(k); co_v.push_back(k);
478 if ((*ref_element)(Q) < 1E-8) {
480 curvature_radius_estimate(*(list_constraints[k]), Q);
481 r0 = std::min(r0, r);
482 if (r0 < 4.*h0) { h0 = 0.2 * r0; h0_is_ok =
false;
break; }
483 if (k >= nbeltconstraints || kept) mesh_points.add(Q, r);
488 if (kept) mesh_points.add(P, 1.E10);
496 if (count & (
size_type(1) << j)) nn.add(co_v[j]);
497 if (nn.card() > 1 && nn.card() <= n) {
498 if (noisy) cout <<
"trying set of constraints" << nn << endl;
500 bool ok=pure_multi_constraint_projection(list_constraints,Q,nn);
501 if (ok && (*ref_element)(Q) < 1E-9) {
502 if (noisy) cout <<
"Intersection point found " << Q <<
" with " 510 if (!h0_is_ok)
continue;
518 if (noisy) cout <<
"dmin = " << dmin <<
" h0 = " << h0 << endl;
519 if (noisy) cout <<
"convex " << cv << endl;
521 dal::bit_vector retained_points
522 = mesh_points.decimate(*ref_element, dmin);
524 bool delaunay_again =
true;
526 std::vector<base_node> fixed_points;
527 std::vector<dal::bit_vector> fixed_points_constraints;
528 mesh &msh(*(cut_cv[cv].pmsh));
530 mesh_region &ls_border_faces(cut_cv[cv].ls_border_faces);
531 std::vector<base_node> cvpts;
535 while (delaunay_again) {
536 if (++nb_delaunay > 15)
537 { h0_is_ok =
false; h0 /= 2.0; dmin = 2.*h0;
break; }
539 fixed_points.resize(0);
540 fixed_points_constraints.resize(0);
543 fixed_points.reserve(retained_points.card());
544 fixed_points_constraints.reserve(retained_points.card());
545 for (dal::bv_visitor i(retained_points); !i.finished(); ++i) {
546 fixed_points.push_back(mesh_points[i]);
547 fixed_points_constraints.push_back(mesh_points.constraints(i));
550 gmm::dense_matrix<size_type> simplexes;
551 run_delaunay(fixed_points, simplexes, fixed_points_constraints);
552 delaunay_again =
false;
556 for (
size_type i = 0; i < fixed_points.size(); ++i) {
557 size_type j = msh.add_point(fixed_points[i]);
562 for (
size_type i = 0; i < gmm::mat_ncols(simplexes); ++i) {
563 size_type j = msh.add_convex(bgeot::simplex_geotrans(n,1),
564 gmm::vect_const_begin(gmm::mat_col(simplexes, i)));
566 if (msh.convex_quality_estimate(j) < 1E-10) msh.sup_convex(j);
568 std::vector<scalar_type> signs(list_constraints.size());
569 std::vector<size_type> prev_point(list_constraints.size());
571 for (
size_type jj = 0; jj < list_constraints.size(); ++jj) {
573 (*(list_constraints[jj]))(msh.points_of_convex(j)[ii]);
574 if (gmm::abs(dd) > radius_cv * 1E-7) {
575 if (dd * signs[jj] < 0.0) {
576 if (noisy) cout <<
"Intersection found ... " << jj
577 <<
" dd = " << dd <<
" convex quality = " 578 << msh.convex_quality_estimate(j) <<
"\n";
580 base_node X = msh.points_of_convex(j)[ii], G;
581 base_node VV = msh.points_of_convex(j)[prev_point[jj]] - X;
582 if (dd > 0.) gmm::scale(VV, -1.);
583 dd = (*(list_constraints[jj])).grad(X, G);
585 while (gmm::abs(dd) > 1e-16*radius_cv && (++nbit < 20)) {
586 scalar_type nG = gmm::vect_sp(G, VV);
587 if (gmm::abs(nG) < 1E-8) nG = 1E-8;
588 if (nG < 0) nG = 1.0;
589 gmm::add(gmm::scaled(VV, -dd / nG), X);
590 dd = (*(list_constraints[jj])).grad(X, G);
592 if (gmm::abs(dd) > 1e-16*radius_cv) {
593 base_node X1 = msh.points_of_convex(j)[ii];
594 base_node X2 = msh.points_of_convex(j)[prev_point[jj]], X3;
595 scalar_type dd1 = (*(list_constraints[jj]))(X1);
596 scalar_type dd2 = (*(list_constraints[jj]))(X2);
597 if (dd1 > dd2) { std::swap(dd1, dd2); std::swap(X1, X2); }
598 while (gmm::abs(dd1) > 1e-15*radius_cv) {
599 X3 = (X1 + X2) / 2.0;
600 scalar_type dd3 = (*(list_constraints[jj]))(X3);
601 if (dd3 == dd1 || dd3 == dd2)
break;
602 if (dd3 > 0) { dd2 = dd3; X2 = X3; }
603 else { dd1 = dd3; X1 = X3; }
609 if (!(retained_points[kk])) {
610 retained_points.add(kk);
611 delaunay_again =
true;
616 if (signs[jj] == 0.0) { signs[jj] = dd; prev_point[jj] = ii; }
626 if (!h0_is_ok)
continue;
630 for (dal::bv_visitor_c j(msh.convex_index()); !j.finished(); ++j) {
632 cvpts.resize(pgt2->nb_points());
633 for (
size_type k=0; k < pgt2->nb_points(); ++k) {
634 cvpts[k] = bgeot::simplex_geotrans(n,1)->transform
635 (pgt2->convex_ref()->points()[k], msh.points_of_convex(j));
640 size_type jj = msh.add_convex_by_points(pgt2, cvpts.begin());
648 char s[512]; sprintf(s,
"totobefore%d.dx",
int(cv));
651 exp.exporting_mesh_edges();
657 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
659 const mesh::ind_pt_face_ct &fpts
660 = msh.ind_points_of_face_of_convex(i, f);
662 dal::bit_vector cts;
bool first =
true;
663 for (
unsigned k=0; k < fpts.size(); ++k) {
664 if (fpts[k] >= fixed_points_constraints.size()) {
668 if (first) { cts = fixed_points_constraints[fpts[k]]; first=
false; }
669 else cts &= fixed_points_constraints[fpts[k]];
671 for (dal::bv_visitor ii(cts); !ii.finished(); ++ii) {
672 if (ii >= nbeltconstraints)
673 ls_border_faces.add(i, f);
680 dal::bit_vector ptdone;
681 std::vector<size_type> ipts;
685 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
687 const mesh::ind_pt_face_ct &fpts
688 = msh.ind_points_of_face_of_convex(i, f);
689 ipts.assign(fpts.begin(), fpts.end());
691 interpolate_face_chrono.tic();
694 interpolate_face(pgt, msh, ptdone, ipts,
695 msh.trans_of_convex(i)->structure()
696 ->faces_structure()[f], fixed_points.size(),
697 fixed_points_constraints, list_constraints);
699 interpolate_face_chrono.toc();
708 char s[512]; sprintf(s,
"toto%d.dx",
int(cv));
711 exp.exporting_mesh_edges();
722 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
723 base_matrix KK(n,n), CS(n,n);
724 base_matrix pc(pgt2->nb_points(), n);
725 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
726 vectors_to_base_matrix(G, msh.points_of_convex(i));
729 scalar_type sign = 0.0;
730 for (
size_type j = 0; j < pai->nb_points_on_convex(); ++j) {
731 c.set_xref(pai->point(j));
732 pgt2->poly_vector_grad(pai->point(j), pc);
734 scalar_type J = gmm::lu_det(KK);
735 if (noisy && J * sign < 0) {
736 cout <<
"CAUTION reversal situation in convex " << i
737 <<
"sign = " << sign <<
" J = " << J << endl;
738 for (
size_type nip = 0; nip < msh.nb_points_of_convex(i); ++nip)
739 cout <<
"Point " << nip <<
"=" << msh.points_of_convex(i)[nip]
743 if (sign == 0 && gmm::abs(J) > 1E-14) sign = J;
744 new_approx->add_point(c.xreal(), pai->coeff(j) * gmm::abs(J));
751 vectors_to_base_matrix(G, msh.points_of_convex(it.cv()));
754 for (
size_type j = 0; j < pai->nb_points_on_face(it.f()); ++j) {
755 c.
set_xref(pai->point_on_face(it.f(), j));
756 new_approx->add_point(c.xreal(), pai->coeff_on_face(it.f(), j)
757 * gmm::abs(c.J()), it.f() );
760 new_approx->valid_method();
766 scalar_type error = test_integration_error(new_approx, 1);
767 if (noisy) cout <<
" max monomial integration err: " << error <<
"\n";
769 if (noisy) cout <<
"Not Good ! Let us make a finer cut.\n";
770 if (dmin > 3*h0) { dmin /= 2.; }
771 else { h0 /= 2.0; dmin = 2.*h0; }
776 if (h0_is_ok && noisy) {
777 vectors_to_base_matrix(G, linked_mesh().points_of_convex(cv));
778 std::vector<size_type> pts(msh.nb_points());
779 for (
size_type i = 0; i < msh.nb_points(); ++i)
780 pts[i] = global_mesh().add_point(pgt->transform(msh.points()[i], G));
782 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i)
783 global_mesh().
add_convex(msh.trans_of_convex(i),
785 msh.ind_points_of_convex(i).begin()));
791 cout <<
"Interpolate face: " << interpolate_face_chrono.total()
792 <<
" moyenne: " << interpolate_face_chrono.mean() <<
"\n";
800 for (dal::bv_visitor cv(linked_mesh().convex_index());
801 !cv.finished(); ++cv) {
802 if (is_convex_cut(cv)) {
803 const convex_info &ci = (cut_cv.find(cv))->second;
804 mesh &msh = *(ci.pmsh);
806 vectors_to_base_matrix(G, linked_mesh().points_of_convex(cv));
807 std::vector<size_type> pts(msh.
nb_points());
809 pts[i] = m.add_point(pgt->transform(msh.points()[i], G));
813 for (dal::bv_visitor i(msh.
convex_index()); !i.finished(); ++i) {
815 gmm::index_ref_iterator(pts.begin(),
819 for (
mr_visitor i(ci.ls_border_faces); !i.finished(); ++i) {
820 m.
region(0).add(ic2[i.cv()], i.f());
825 linked_mesh().points_of_convex(cv).begin());
832 void mesh_level_set::update_crack_tip_convexes() {
833 crack_tip_convexes_.clear();
835 for (std::map<size_type, convex_info>::const_iterator it = cut_cv.begin();
836 it != cut_cv.end(); ++it) {
838 mesh &msh = *(it->second.pmsh);
839 for (
unsigned ils = 0; ils < nb_level_sets(); ++ils) {
840 if (get_level_set(ils)->has_secondary()) {
841 pmesher_signed_distance
842 mesherls0 = get_level_set(ils)->mls_of_convex(cv, 0,
false);
843 pmesher_signed_distance
844 mesherls1 = get_level_set(ils)->mls_of_convex(cv, 1,
false);
845 for (dal::bv_visitor ii(msh.
convex_index()); !ii.finished(); ++ii) {
847 if (gmm::abs((*mesherls0)(msh.points_of_convex(ii)[ipt])) < 1E-10
848 && gmm::abs((*mesherls1)(msh.points_of_convex(ii)[ipt])) < 1E-10) {
849 crack_tip_convexes_.add(cv);
866 GMM_ASSERT1(linked_mesh_ != 0,
"Uninitialized mesh_level_set");
869 zones_of_convexes.clear();
875 for (dal::bv_visitor cv(linked_mesh().convex_index());
876 !cv.finished(); ++cv) {
877 scalar_type radius = linked_mesh().convex_radius_estimate(cv);
878 dal::bit_vector prim, sec;
879 find_crossing_level_set(cv, prim, sec, z, radius);
880 zones_of_convexes[cv] = &(*(allsubzones.insert(z).first));
881 if (noisy) cout <<
"element " << cv <<
" cut level sets : " 882 << prim <<
" zone : " << z << endl;
884 cut_element(cv, prim, sec, radius);
885 find_zones_of_element(cv, z, radius);
897 update_crack_tip_convexes();
903 void mesh_level_set::find_level_set_potential_intersections
904 (std::vector<size_type> &icv, std::vector<dal::bit_vector> &ils) {
906 GMM_ASSERT1(linked_mesh_ != 0,
"Uninitialized mesh_level_set");
908 for (dal::bv_visitor cv(linked_mesh().convex_index());
909 !cv.finished(); ++cv)
910 if (is_convex_cut(cv)) {
911 scalar_type radius = linked_mesh().convex_radius_estimate(cv);
912 dal::bit_vector prim, sec;
913 find_crossing_level_set(cv, prim, sec, z, radius);
914 if (prim.card() > 1) {
925 int mesh_level_set::sub_simplex_is_not_crossed_by(
size_type cv,
928 scalar_type radius) {
929 scalar_type EPS = 1e-7 * radius;
931 convex_info &cvi = cut_cv[cv];
936 pmesher_signed_distance mls0 = ls->mls_of_convex(cv, 0), mls1(mls0);
937 if (ls->has_secondary()) mls1 = ls->mls_of_convex(cv, 1);
940 scalar_type d2 = 0, d1 = 1, d0 = 0, d0min = 0;
941 for (
size_type i = 0; i < pgt2->nb_points(); ++i) {
942 d0 = (*mls0)(cvi.pmsh->points_of_convex(sub_cv)[i]);
943 if (i == 0) d0min = gmm::abs(d0);
944 else d0min = std::min(d0min, gmm::abs(d0));
945 if (ls->has_secondary())
946 d1 = std::min(d1, (*mls1)(cvi.pmsh->points_of_convex(sub_cv)[i]));
948 int p2 = ( (d0 < -EPS) ? -1 : ((d0 > EPS) ? +1 : 0));
950 if (gmm::abs(d0) > gmm::abs(d2)) d2 = d0;
951 if (!p2 || p*p2 < 0) is_cut =
true;
955 if (is_cut && ls->has_secondary() && d1 >= -radius*0.0001)
return 0;
957 return (d2 < 0.) ? -1 : 1;
961 unsigned lsnum, scalar_type radius) {
962 const mesh_fem &mf = ls->get_mesh_fem();
963 GMM_ASSERT1(!mf.
is_reduced(),
"Internal error");
967 scalar_type EPS = 1e-8 * radius;
974 for (mesh_fem::ind_dof_ct::const_iterator it=dofs.begin();
975 it != dofs.end(); ++it) {
976 scalar_type v = ls->values(lsnum)[*it];
977 int p2 = ( (v < -EPS) ? -1 : ((v > EPS) ? +1 : 0));
979 if (!p2 || p*p2 < 0)
return 0;
982 pmesher_signed_distance mls1 = ls->mls_of_convex(cv, lsnum,
false);
983 base_node X(pf->dim()), G(pf->dim());
984 gmm::fill_random(X); X *= 1E-2;
985 scalar_type d = mls1->grad(X, G);
986 if (gmm::vect_norm2(G)*2.5 < gmm::abs(d))
return p;
989 pmesher_signed_distance ref_element = new_ref_element(pgt);
991 gmm::fill_random(X); X *= 1E-2;
992 mesher_intersection mi1(ref_element, mls1);
993 if (!try_projection(mi1, X))
return p;
994 if ((*ref_element)(X) > 1E-8)
return p;
996 gmm::fill_random(X); X *= 1E-2;
997 pmesher_signed_distance mls2 = ls->mls_of_convex(cv, lsnum,
true);
998 mesher_intersection mi2(ref_element, mls2);
999 if (!try_projection(mi2, X))
return p;
1000 if ((*ref_element)(X) > 1E-8)
return p;
1005 void mesh_level_set::find_crossing_level_set(
size_type cv,
1006 dal::bit_vector &prim,
1007 dal::bit_vector &sec,
1009 scalar_type radius) {
1010 prim.clear(); sec.clear();
1011 z = std::string(level_sets.size(),
'*');
1013 for (
size_type k = 0; k < level_sets.size(); ++k, ++lsnum) {
1014 if (noisy) cout <<
"testing cv " << cv <<
" with level set " 1016 int s = is_not_crossed_by(cv, level_sets[k], 0, radius);
1018 if (noisy) cout <<
"is cut \n";
1019 if (level_sets[k]->has_secondary()) {
1020 s = is_not_crossed_by(cv, level_sets[k], 1, radius);
1021 if (!s) { sec.add(lsnum); prim.add(lsnum); }
1022 else if (s < 0) prim.add(lsnum);
else z[k] =
'0';
1024 else prim.add(lsnum);
1026 else z[k] = (s < 0) ?
'-' :
'+';
structure used to hold a set of convexes and/or convex faces.
short_type nb_points_of_convex(size_type ic) const
Return the number of points of convex ic.
Keep informations about a mesh crossed by level-sets.
std::ostream & operator<<(std::ostream &o, const convex_structure &cv)
Print the details of the convex structure cvs to the output stream o.
void clear(void)
reset the array, remove all points
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.
virtual pfem fem_of_element(size_type cv) const
Return the basic fem associated with an element (if no fem is associated, the function will crash! us...
pconvex_structure prism_P1_structure(dim_type nc)
Give a pointer on the structures of a prism of dimension d.
Describe a mesh (collection of convexes (elements) and points).
size_type add_convex(bgeot::pgeometric_trans pgt, ITER ipts)
Add a convex to the mesh.
the geotrans_interpolation_context structure is passed as the argument of geometric transformation in...
void adapt(void)
do all the work (cut the convexes wrt the levelsets)
void clear()
Erase the mesh.
void fill_random(L &l, double cfill)
*/
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2(const V1 &v1, const V2 &v2)
Euclidean distance between two vectors.
Balanced tree over a set of points.
static T & instance()
Instance from the current thread.
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
size_type search_node(const base_node &pt, const scalar_type radius=0) const
Search a node in the array.
void global_cut_mesh(mesh &m) const
fill m with the (non-conformal) "cut" mesh.
"iterator" class for regions.
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
The output of a getfem::mesh_slicer which has been recorded.
A (quite large) class for exportation of data to IBM OpenDX.
bool is_reduced() const
Return true if a reduction matrix is applied to the dofs.
GEneric Tool for Finite Element Methods.
pintegration_method classical_exact_im(bgeot::pgeometric_trans pgt)
return an exact integration method for convex type handled by pgt.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Describe a finite element method linked to a mesh.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
gmm::uint16_type short_type
used as the common short type integer in the library
pconvex_structure parallelepiped_structure(dim_type nc, dim_type k)
Give a pointer on the structures of a parallelepiped of dimension d.
void add_point_with_id(const base_node &n, size_type i)
insert a new point, with an associated number.
This slicer does nothing.
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 build(const getfem::mesh &m, const slicer_action &a, size_type nrefine=1)
Build the slice, by applying a slicer_action operation.
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
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...
void set_xref(const base_node &P)
change the current point (coordinates given in the reference convex)
tab_ref_index_ref_iterator_< ITER, ITER_INDEX > index_ref_iterator(ITER it, ITER_INDEX it_i)
convenience template function for quick obtention of a indexed iterator without having to specify its...
const ind_cv_ct & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
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_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.
virtual ind_dof_ct ind_basic_dof_of_element(size_type cv) const
Give an array of the dof numbers a of convex.
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
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 identify it with a very close existing point.
void add(const L1 &l1, L2 &l2)
*/
std::vector< index_node_pair > kdtree_tab_type
store a set of points with associated indexes.
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.