28 { is_adapted =
false; }
30 void mesh_im_level_set::clear_build_methods() {
31 for (
size_type i = 0; i < build_methods.size(); ++i)
32 del_stored_object(build_methods[i]);
33 build_methods.clear();
37 void mesh_im_level_set::clear(
void) {
39 clear_build_methods();
43 void mesh_im_level_set::init_with_mls(mesh_level_set &me,
45 pintegration_method reg,
46 pintegration_method sing) {
47 init_with_mesh(me.linked_mesh());
48 cut_im.init_with_mesh(me.linked_mesh());
50 integrate_where = integrate_where_;
52 this->add_dependency(*mls);
58 pintegration_method reg,
59 pintegration_method sing) {
61 init_with_mls(me, integrate_where_, reg, sing);
64 mesh_im_level_set::mesh_im_level_set(
void)
65 { mls = 0; is_adapted =
false; }
74 if (ignored_im.is_in(cv))
81 DAL_SIMPLE_KEY(special_imls_key, papprox_integration);
84 mesh_im_level_set::bool2 mesh_im_level_set::is_point_in_selected_area2
85 (
const std::vector<pmesher_signed_distance> &mesherls0,
86 const std::vector<pmesher_signed_distance> &mesherls1,
91 isin = isin && ((*(mesherls0[i]))(P) < 0);
92 if (gmm::abs((*(mesherls0[i]))(P)) < 1e-7)
94 if (mls->get_level_set(i)->has_secondary())
95 isin = isin && ((*(mesherls1[i]))(P) < 0);
98 b.in = ((integrate_where & INTEGRATE_OUTSIDE)) ? !isin : isin;
108 typedef mesh_im_level_set::bool2 bool2;
109 bool2 do_expr(
const char *&s) {
113 GMM_ASSERT1(*s++ ==
')',
114 "expecting ')' in csg expression at '" << s-1 <<
"'");
115 }
else if (*s ==
'!') {
116 r = do_expr(++s); r.in = !r.in;
117 }
else if (*s >=
'a' && *s <=
'z') {
118 unsigned idx = (*s) -
'a';
119 r.in = in.is_in(idx);
120 r.bin = bin.is_in(idx) ? idx+1 : 0;
123 GMM_ASSERT1(
false,
"parse error in csg expression at '" << s <<
"'");
126 bool2 a = r, b = do_expr(++s);
129 if (b.bin && !a.in) r.bin = b.bin;
130 else if (a.bin && !b.in) r.bin = a.bin;
132 }
else if (*s ==
'-') {
133 bool2 a = r, b = do_expr(++s);
134 r.in = a.in && !b.in;
135 if (a.bin && !b.in) r.bin = a.bin;
136 else if (a.in && b.bin) r.bin = b.bin;
138 }
else if (*s ==
'*') {
139 bool2 a = r, b = do_expr(++s);
141 if (a.bin && b.in) r.bin = a.bin;
142 else if (a.in && b.bin) r.bin = b.bin;
147 bool2 is_in(
const char*s) {
148 bool2 b = do_expr(s);
149 GMM_ASSERT1(!(*s),
"parse error in CSG expression at " << s);
153 const char *s[] = {
"a*b*c*d",
161 for (
const char **p = s; *p; ++p)
163 for (
unsigned c=0; c < 16; ++c) {
164 in[0] = (c&1); bin[0] = 1;
165 in[1] = (c&2); bin[1] = 1;
166 in[2] = (c&4); bin[2] = 1;
167 in[3] = (c&8); bin[3] = 1;
168 cerr << in[0] << in[1] << in[2] << in[3] <<
": ";
169 for (
const char **p = s; *p; ++p) {
171 cerr << b.in <<
"/" << b.bin <<
" ";
178 mesh_im_level_set::bool2
179 mesh_im_level_set::is_point_in_selected_area
180 (
const std::vector<pmesher_signed_distance> &mesherls0,
181 const std::vector<pmesher_signed_distance> &mesherls1,
182 const base_node& P) {
185 bool sec = mls->get_level_set(i)->has_secondary();
186 scalar_type d1 = (*(mesherls0[i]))(P);
187 scalar_type d2 = (sec ? (*(mesherls1[i]))(P) : -1);
188 if (d1 < 0 && d2 < 0) ev.in.add(i);
192 if (gmm::abs(d1) < 1e-7 && d2 < 1e-7)
198 if (ls_csg_description.size())
199 r = ev.is_in(ls_csg_description.c_str());
202 r.bin = (ev.bin.card() >= 1 && ev.in.card() >= mls->
nb_level_sets()-1);
205 if (integrate_where & INTEGRATE_OUTSIDE) r.in = !(r.in);
220 void mesh_im_level_set::build_method_of_convex(
size_type cv) {
221 const mesh &msh(mls->mesh_of_convex(cv));
222 GMM_ASSERT3(msh.convex_index().card() != 0,
"Internal error");
226 std::vector<pmesher_signed_distance> mesherls0(mls->
nb_level_sets());
227 std::vector<pmesher_signed_distance> mesherls1(mls->
nb_level_sets());
228 dal::bit_vector convexes_arein;
232 mesherls0[i] = mls->get_level_set(i)->mls_of_convex(cv, 0,
false);
233 if (mls->get_level_set(i)->has_secondary())
234 mesherls1[i] = mls->get_level_set(i)->mls_of_convex(cv, 1,
false);
237 if (integrate_where != (INTEGRATE_ALL)) {
238 for (dal::bv_visitor scv(msh.convex_index()); !scv.finished(); ++scv) {
239 B = gmm::mean_value(msh.points_of_convex(scv));
240 convexes_arein[scv] =
241 is_point_in_selected_area(mesherls0, mesherls1, B).in;
247 = msh.trans_of_convex(msh.convex_index().first_true());
248 dim_type n = pgt->dim();
250 if (base_singular_pim) GMM_ASSERT1
255 && (n >= 2) && (n <= 3),
256 "Base integration method for quasi polar integration not convenient");
258 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
259 new_approx->set_built_on_the_fly();
260 base_matrix KK(n,n), CS(n,n);
261 base_matrix pc(pgt2->nb_points(), n);
262 std::vector<size_type> ptsing;
266 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
267 papprox_integration pai = regular_simplex_pim->approx_method();
269 GMM_ASSERT1(regular_simplex_pim->structure() ==
bgeot::simplex_structure(n),
"Base integration method should be defined on a simplex of same dimension than the mesh");
271 if ((integrate_where != INTEGRATE_ALL) &&
272 !convexes_arein[i])
continue;
274 if (base_singular_pim && mls->crack_tip_convexes().is_in(cv)) {
276 unsigned sing_ls = unsigned(-1);
279 if (mls->get_level_set(ils)->has_secondary()) {
280 for (
unsigned ipt = 0; ipt <= n; ++ipt) {
281 if (gmm::abs((*(mesherls0[ils]))(msh.points_of_convex(i)[ipt]))
283 && gmm::abs((*(mesherls1[ils]))(msh.points_of_convex(i)[ipt]))
285 if (sing_ls ==
unsigned(-1)) sing_ls = ils;
286 GMM_ASSERT1(sing_ls == ils,
"Two singular point in one "
287 "sub element : " << sing_ls <<
", " << ils <<
289 ptsing.push_back(ipt);
293 assert(ptsing.size() < n);
295 if (ptsing.size() > 0) {
296 std::stringstream sts;
298 <<
", " << ptsing[0];
299 if (ptsing.size() > 1) sts <<
", " << ptsing[1];
306 vectors_to_base_matrix(G2,
linked_mesh().points_of_convex(cv));
308 cc(
linked_mesh().trans_of_convex(cv), pai->point(0), G2);
310 if (integrate_where & (INTEGRATE_INSIDE | INTEGRATE_OUTSIDE)) {
312 vectors_to_base_matrix(G, msh.points_of_convex(i));
316 for (
size_type j = 0; j < pai->nb_points_on_convex(); ++j) {
317 c.set_xref(pai->point(j));
318 pgt2->poly_vector_grad(pai->point(j), pc);
321 new_approx->add_point(c.xreal(), pai->coeff(j) * gmm::abs(J));
333 for (
short_type f = 0; f < pgt2->structure()->nb_faces(); ++f) {
335 unsigned isin = unsigned(-1);
337 if (integrate_where == INTEGRATE_BOUNDARY) {
339 for (
const base_node &pt : msh.points_of_face_of_convex(i, f)) {
340 isin = is_point_in_selected_area(mesherls0, mesherls1, pt).bin;
342 if (!isin) { lisin =
false;
break; }
344 if (!lisin)
continue;
347 B = gmm::mean_value(msh.points_of_face_of_convex(i, f));
348 if (pgt->convex_ref()->is_in(B) < -1E-7)
continue;
349 for (
short_type fi = 0; fi < pgt->structure()->nb_faces(); ++fi) {
350 if (gmm::abs(pgt->convex_ref()->is_in_face(fi, B)) < 2E-6) ff = fi;
354 cout <<
"Distance to the element : "
355 << pgt->convex_ref()->is_in(B) << endl;
356 for (
short_type fi = 0; fi < pgt->structure()->nb_faces(); ++fi) {
357 cout <<
"Distance to face " << fi <<
" : "
358 << gmm::abs(pgt->convex_ref()->is_in_face(fi, B)) << endl;
360 GMM_ASSERT3(
false,
"the point is neither in the interior nor "
361 "the boundary of the element");
365 vectors_to_base_matrix(G, msh.points_of_convex(i));
370 for (
size_type j = 0; j < pai->nb_points_on_face(f); ++j) {
371 if (gmm::abs(c.J()) > 1E-11) {
372 c.set_xref(pai->point_on_face(f, j));
373 base_small_vector un = pgt2->normals()[f], up(msh.dim());
378 if (integrate_where == INTEGRATE_BOUNDARY) {
379 cc.set_xref(c.xreal());
380 mesherls0[isin]->grad(c.xreal(), un);
385 new_approx->add_point(c.xreal(), pai->coeff_on_face(f, j)
386 * gmm::abs(c.J()) * nup * nnup, ff);
392 if (new_approx->nb_points()) {
393 new_approx->valid_method();
395 pim = std::make_shared<integration_method>(new_approx);
396 dal::pstatic_stored_object_key
397 pk = std::make_shared<special_imls_key>(new_approx);
399 new_approx->pintegration_points());
400 build_methods.push_back(pim);
406 GMM_ASSERT1(linked_mesh_ != 0,
"mesh level set uninitialized");
408 clear_build_methods();
411 !cv.finished(); ++cv) {
412 if (mls->is_convex_cut(cv)) build_method_of_convex(cv);
418 if (integrate_where == INTEGRATE_BOUNDARY) {
420 }
else if (integrate_where != (INTEGRATE_OUTSIDE|INTEGRATE_INSIDE)) {
422 std::vector<pmesher_signed_distance> mesherls0(mls->
nb_level_sets());
423 std::vector<pmesher_signed_distance> mesherls1(mls->
nb_level_sets());
425 mesherls0[i] = mls->get_level_set(i)->mls_of_convex(cv, 0,
false);
426 if (mls->get_level_set(i)->has_secondary())
427 mesherls1[i] = mls->get_level_set(i)->mls_of_convex(cv,1,
false);
430 base_node B(gmm::mean_value(
linked_mesh().trans_of_convex(cv)
431 ->convex_ref()->points()));
432 if (!is_point_in_selected_area(mesherls0, mesherls1, B).in)
437 is_adapted =
true; touch();
441 void mesh_im_level_set::compute_normal_vector
444 std::vector<pmesher_signed_distance> mesherls0(nb_ls);
446 base_small_vector un(ctx.pgt()->dim());
449 gmm::clear(vec);
return;
450 }
else if (nb_ls == 1) {
452 = mls->get_level_set(0)->mls_of_convex(ctx.
convex_num(), 0,
false);
454 scalar_type d_min(0);
455 for (
unsigned i = 0; i < nb_ls; ++i) {
457 = mls->get_level_set(i)->mls_of_convex(ctx.
convex_num(), 0,
false);
458 scalar_type d = gmm::abs((*(mesherls0[i]))(ctx.
xref()));
459 if (i == 0 || d < d_min) { d_min = d; j = i; }
462 mesherls0[j]->grad(ctx.
xref(), un);
465 if (no != scalar_type(0))
466 gmm::scale(vec, scalar_type(1) / gmm::vect_norm2(vec));
472 { is_adapted =
false; }
474 void mesh_im_cross_level_set::clear_build_methods() {
475 for (
size_type i = 0; i < build_methods.size(); ++i)
476 if (build_methods[i].get()) del_stored_object(build_methods[i]);
477 build_methods.clear();
481 void mesh_im_cross_level_set::clear(
void)
482 { mesh_im::clear(); clear_build_methods(); is_adapted =
false; }
484 void mesh_im_cross_level_set::init_with_mls(mesh_level_set &me,
486 pintegration_method pim) {
487 init_with_mesh(me.linked_mesh());
488 cut_im.init_with_mesh(me.linked_mesh());
490 ind_ls1 = ind_ls1_; ind_ls2 = ind_ls2_;
492 this->add_dependency(*mls);
496 mesh_im_cross_level_set::mesh_im_cross_level_set(mesh_level_set &me,
498 pintegration_method pim)
499 { mls = 0; init_with_mls(me, ind_ls1_, ind_ls2_, pim); }
501 mesh_im_cross_level_set::mesh_im_cross_level_set(
void)
502 { mls = 0; is_adapted =
false; }
517 static bool is_point_in_intersection
518 (
const std::vector<pmesher_signed_distance> &mesherls0,
519 const std::vector<pmesher_signed_distance> &mesherls1,
520 const base_node& P) {
523 for (
unsigned i = 0; i < mesherls0.size(); ++i) {
524 bool sec = (
dynamic_cast<const mesher_level_set *
>(mesherls1[i].get()))->is_initialized();
525 scalar_type d1 = (*(mesherls0[i]))(P);
526 scalar_type d2 = (sec ? (*(mesherls1[i]))(P) : -1);
527 if (!(gmm::abs(d1) < 1e-7 && d2 < 1e-7)) r =
false;
532 static bool is_edges_intersect(
const base_node &PP1,
const base_node &PP2,
533 const base_node &PR1,
const base_node &PR2) {
534 size_type n = gmm::vect_size(PP1), k1 = 0;
535 scalar_type c1 = scalar_type(0);
536 base_node V = PR2 - PR1;
538 if (gmm::abs(V[k]) > gmm::abs(c1)) { c1 = V[k]; k1 = k; }
540 scalar_type alpha1 = (PP1[k1] - PR1[k1]) / c1;
541 scalar_type alpha2 = (PP2[k1] - PR1[k1]) / c1;
542 base_node W1 = PP1 - PR1 - alpha1 * V;
543 base_node W2 = PP2 - PR1 - alpha2 * V;
546 if (alpha1 > 1.-1e-7 && alpha2 > 1.-1e-7)
return false;
547 if (alpha1 < 1e-7 && alpha2 < 1e-7)
return false;
552 void mesh_im_cross_level_set::build_method_of_convex
554 const mesh &msh(mls->mesh_of_convex(cv));
555 GMM_ASSERT3(msh.convex_index().card() != 0,
"Internal error");
559 std::vector<pmesher_signed_distance> mesherls0(2);
560 std::vector<pmesher_signed_distance> mesherls1(2);
561 dal::bit_vector convexes_arein;
563 mesherls0[0] = mls->get_level_set(ind_ls1)->mls_of_convex(cv, 0,
false);
564 mesherls0[1] = mls->get_level_set(ind_ls2)->mls_of_convex(cv, 0,
false);
565 if (mls->get_level_set(ind_ls1)->has_secondary())
566 mesherls1[0] = mls->get_level_set(ind_ls1)->mls_of_convex(cv, 1,
false);
567 if (mls->get_level_set(ind_ls2)->has_secondary())
568 mesherls1[1] = mls->get_level_set(ind_ls2)->mls_of_convex(cv, 1,
false);
572 = msh.trans_of_convex(msh.convex_index().first_true());
573 dim_type n = pgt->dim();
575 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
576 new_approx->set_built_on_the_fly();
577 base_matrix KK(n,n), CS(n,n);
578 base_matrix pc(pgt2->nb_points(), n);
579 std::vector<size_type> ptsing;
581 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
582 papprox_integration pai = segment_pim->approx_method();
583 GMM_ASSERT1(gmm::vect_size(pai->point(0)) == 1,
584 "A segment integration method is needed");
587 vectors_to_base_matrix(G2,
linked_mesh().points_of_convex(cv));
589 cc(
linked_mesh().trans_of_convex(cv), base_node(n), G2);
591 mesh::ref_mesh_pt_ct cvpts = msh.points_of_convex(i);
593 dal::bit_vector ptinter;
595 size_type ipt = msh.structure_of_convex(i)->ind_dir_points()[k];
596 const base_node &P = cvpts[ipt];
597 if (is_point_in_intersection(mesherls0, mesherls1, P))
604 size_type ipt = msh.structure_of_convex(i)->ind_dir_points()[k];
605 if (ptinter.is_in(ipt)) {
607 const base_node &P = cvpts[ipt];
610 if (global_intersection.search_point(cc.xreal())
612 global_intersection.add_point(cc.xreal());
613 new_approx->add_point(msh.points_of_convex(i)[ipt],
623 size_type ipt1 = msh.structure_of_convex(i)->ind_dir_points()[k1];
625 size_type ipt2=msh.structure_of_convex(i)->ind_dir_points()[k2];
626 if (ptinter.is_in(ipt1) && ptinter.is_in(ipt2)) {
628 const base_node &P1 = cvpts[ipt1];
629 const base_node &P2 = cvpts[ipt2];
631 base_node PR1 = cc.xreal();
633 base_node PR2 = cc.xreal();
635 size_type i1 = global_intersection.search_point(PR1);
636 size_type i2 = global_intersection.search_point(PR2);
639 !global_intersection.nb_convex_with_edge(i1, i2)) {
641 base_node min(n), max(n);
643 min[k] = std::min(PR1[k], PR2[k]);
644 max[k] = std::max(PR1[k], PR2[k]);
646 bgeot::rtree::pbox_set boxlst;
647 rtree_seg.find_intersecting_boxes(min, max, boxlst);
649 bool found_intersect =
false;
651 for (bgeot::rtree::pbox_set::const_iterator
652 it=boxlst.begin(); it != boxlst.end(); ++it) {
653 mesh::ref_mesh_pt_ct intersect_cvpts
654 = global_intersection.points_of_convex((*it)->id);
655 const base_node &PP1 = intersect_cvpts[0];
656 const base_node &PP2 = intersect_cvpts[1];
657 if (is_edges_intersect(PP1, PP2, PR1, PR2))
658 { found_intersect =
true;
break; }
661 if (!found_intersect) {
663 i1 = global_intersection.add_point(PR1);
664 i2 = global_intersection.add_point(PR2);
666 size_type is = global_intersection.add_segment(i1, i2);
668 rtree_seg.add_box(min, max, is);
669 rtree_seg.build_tree();
673 = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
675 = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
676 base_node V = PE2 - PE1, W1(n), W2(n);
679 vectors_to_base_matrix(G3, msh.points_of_convex(i));
681 ccc(msh.trans_of_convex(i), base_node(n), G3);
683 for (
size_type j=0; j < pai->nb_points_on_convex(); ++j) {
684 base_node PE = pai->point(j)[0] * PE2
685 + (scalar_type(1) - pai->point(j)[0]) * PE1;
687 cc.set_xref(ccc.xreal());
690 new_approx->add_point(ccc.xreal(),
691 pai->coeff(j) * gmm::vect_norm2(W2));
700 default: GMM_ASSERT1(
false,
"internal error");
705 if (new_approx->nb_points()) {
706 new_approx->valid_method();
708 pim = std::make_shared<integration_method>(new_approx);
709 dal::pstatic_stored_object_key
710 pk = std::make_shared<special_imls_key>(new_approx);
712 new_approx->pintegration_points());
713 build_methods.push_back(pim);
719 GMM_ASSERT1(linked_mesh_ != 0,
"mesh level set uninitialized");
720 GMM_ASSERT1(linked_mesh_->dim() > 1 && linked_mesh_->dim() <= 3,
721 "Sorry, works only in dimension 2 or 3");
724 clear_build_methods();
726 mesh global_intersection;
729 std::vector<size_type> icv;
730 std::vector<dal::bit_vector> ils;
731 mls->find_level_set_potential_intersections(icv, ils);
733 for (
size_type i = 0; i < icv.size(); ++i) {
734 if (ils[i].is_in(ind_ls1) && ils[i].is_in(ind_ls2)) {
735 build_method_of_convex(icv[i], global_intersection, rtree_seg);
740 !cv.finished(); ++cv)
741 if (!cut_im.
convex_index().is_in(cv)) ignored_im.add(cv);
743 is_adapted =
true; touch();
Simple implementation of a KD-tree.
the geotrans_interpolation_context structure is passed as the argument of geometric transformation in...
const base_node & xref() const
coordinates of the current point, in the reference convex.
Balanced tree of n-dimensional rectangles.
bool context_check() const
return true if update_from_context was called
structure passed as the argument of fem interpolation functions.
Describe an adaptable integration method linked to a mesh cut by at least two level sets on the inter...
virtual pintegration_method int_method_of_element(size_type cv) const
return the integration method associated with an element (in no integration is associated,...
void update_from_context(void) const
this function has to be defined and should update the object when the context is modified.
void set_segment_im(pintegration_method pim)
Set the specific integration methods.
void adapt(void)
Apply the adequate integration methods.
Describe an adaptable integration method linked to a mesh cut by a level set.
void adapt(void)
Apply the adequate integration methods.
void set_simplex_im(pintegration_method reg, pintegration_method sing=0)
Set the specific integration methods.
virtual pintegration_method int_method_of_element(size_type cv) const
return the integration method associated with an element (in no integration is associated,...
void update_from_context(void) const
this function has to be defined and should update the object when the context is modified.
virtual pintegration_method int_method_of_element(size_type cv) const
return the integration method associated with an element (in no integration is associated,...
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
const dal::bit_vector & convex_index(void) const
Get the set of convexes where an integration method has been assigned.
void set_integration_method(size_type cv, pintegration_method pim)
Set the integration method of a convex.
Keep informations about a mesh crossed by level-sets.
size_type nb_level_sets(void) const
Get number of level-sets referenced in this object.
Describe a mesh (collection of convexes (elements) and points).
a subclass of mesh_im which is conformal to a number of level sets.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
linalg_traits< DenseMatrixLU >::value_type lu_det(const DenseMatrixLU &LU, const Pvector &pvector)
Compute the matrix determinant (via a LU factorization)
size_type convex_num() const
get the current convex number
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.
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
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
GEneric Tool for Finite Element Methods.
std::string name_of_int_method(pintegration_method p)
Get the string name of an integration method .
pintegration_method int_method_descriptor(std::string name, bool throw_if_not_found=true)
Get an integration method from its name .
pintegration_method im_none(void)
return IM_NONE