29 { is_adapted =
false; }
31 void mesh_im_level_set::clear_build_methods() {
32 for (
size_type i = 0; i < build_methods.size(); ++i)
33 del_stored_object(build_methods[i]);
34 build_methods.clear();
38 void mesh_im_level_set::clear(
void) {
40 clear_build_methods();
44 void mesh_im_level_set::init_with_mls(mesh_level_set &me,
46 pintegration_method reg,
47 pintegration_method sing) {
48 init_with_mesh(me.linked_mesh());
49 cut_im.init_with_mesh(me.linked_mesh());
51 integrate_where = integrate_where_;
53 this->add_dependency(*mls);
59 pintegration_method reg,
60 pintegration_method sing) {
62 init_with_mls(me, integrate_where_, reg, sing);
65 mesh_im_level_set::mesh_im_level_set(
void)
66 { mls = 0; is_adapted =
false; }
75 if (ignored_im.is_in(cv))
82 DAL_SIMPLE_KEY(special_imls_key, papprox_integration);
85 mesh_im_level_set::bool2 mesh_im_level_set::is_point_in_selected_area2
86 (
const std::vector<pmesher_signed_distance> &mesherls0,
87 const std::vector<pmesher_signed_distance> &mesherls1,
92 isin = isin && ((*(mesherls0[i]))(P) < 0);
93 if (gmm::abs((*(mesherls0[i]))(P)) < 1e-7)
95 if (mls->get_level_set(i)->has_secondary())
96 isin = isin && ((*(mesherls1[i]))(P) < 0);
99 b.in = ((integrate_where & INTEGRATE_OUTSIDE)) ? !isin : isin;
109 typedef mesh_im_level_set::bool2 bool2;
110 bool2 do_expr(
const char *&s) {
114 GMM_ASSERT1(*s++ ==
')',
115 "expecting ')' in csg expression at '" << s-1 <<
"'");
116 }
else if (*s ==
'!') {
117 r = do_expr(++s); r.in = !r.in;
118 }
else if (*s >=
'a' && *s <=
'z') {
119 unsigned idx = (*s) -
'a';
120 r.in = in.is_in(idx);
121 r.bin = bin.is_in(idx) ? idx+1 : 0;
124 GMM_ASSERT1(
false,
"parse error in csg expression at '" << s <<
"'");
127 bool2 a = r, b = do_expr(++s);
130 if (b.bin && !a.in) r.bin = b.bin;
131 else if (a.bin && !b.in) r.bin = a.bin;
133 }
else if (*s ==
'-') {
134 bool2 a = r, b = do_expr(++s);
135 r.in = a.in && !b.in;
136 if (a.bin && !b.in) r.bin = a.bin;
137 else if (a.in && b.bin) r.bin = b.bin;
139 }
else if (*s ==
'*') {
140 bool2 a = r, b = do_expr(++s);
142 if (a.bin && b.in) r.bin = a.bin;
143 else if (a.in && b.bin) r.bin = b.bin;
148 bool2 is_in(
const char*s) {
149 bool2 b = do_expr(s);
150 GMM_ASSERT1(!(*s),
"parse error in CSG expression at " << s);
154 const char *s[] = {
"a*b*c*d",
162 for (
const char **p = s; *p; ++p)
164 for (
unsigned c=0; c < 16; ++c) {
165 in[0] = (c&1); bin[0] = 1;
166 in[1] = (c&2); bin[1] = 1;
167 in[2] = (c&4); bin[2] = 1;
168 in[3] = (c&8); bin[3] = 1;
169 cerr << in[0] << in[1] << in[2] << in[3] <<
": ";
170 for (
const char **p = s; *p; ++p) {
172 cerr << b.in <<
"/" << b.bin <<
" ";
179 mesh_im_level_set::bool2
180 mesh_im_level_set::is_point_in_selected_area
181 (
const std::vector<pmesher_signed_distance> &mesherls0,
182 const std::vector<pmesher_signed_distance> &mesherls1,
183 const base_node& P) {
186 bool sec = mls->get_level_set(i)->has_secondary();
187 scalar_type d1 = (*(mesherls0[i]))(P);
188 scalar_type d2 = (sec ? (*(mesherls1[i]))(P) : -1);
189 if (d1 < 0 && d2 < 0) ev.in.add(i);
193 if (gmm::abs(d1) < 1e-7 && d2 < 1e-7)
199 if (ls_csg_description.size())
200 r = ev.is_in(ls_csg_description.c_str());
203 r.bin = (ev.bin.card() >= 1 && ev.in.card() >= mls->
nb_level_sets()-1);
206 if (integrate_where & INTEGRATE_OUTSIDE) r.in = !(r.in);
221 void mesh_im_level_set::build_method_of_convex(
size_type cv) {
222 const mesh &msh(mls->mesh_of_convex(cv));
223 GMM_ASSERT3(msh.convex_index().card() != 0,
"Internal error");
227 std::vector<pmesher_signed_distance> mesherls0(mls->
nb_level_sets());
228 std::vector<pmesher_signed_distance> mesherls1(mls->
nb_level_sets());
229 dal::bit_vector convexes_arein;
233 mesherls0[i] = mls->get_level_set(i)->mls_of_convex(cv, 0,
false);
234 if (mls->get_level_set(i)->has_secondary())
235 mesherls1[i] = mls->get_level_set(i)->mls_of_convex(cv, 1,
false);
238 if (integrate_where != (INTEGRATE_ALL)) {
239 for (dal::bv_visitor scv(msh.convex_index()); !scv.finished(); ++scv) {
240 B = gmm::mean_value(msh.points_of_convex(scv));
241 convexes_arein[scv] =
242 is_point_in_selected_area(mesherls0, mesherls1, B).in;
248 = msh.trans_of_convex(msh.convex_index().first_true());
249 dim_type n = pgt->dim();
251 if (base_singular_pim) GMM_ASSERT1
256 && (n >= 2) && (n <= 3),
257 "Base integration method for quasi polar integration not convenient");
259 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
260 new_approx->set_built_on_the_fly();
261 base_matrix KK(n,n), CS(n,n);
262 base_matrix pc(pgt2->nb_points(), n);
263 std::vector<size_type> ptsing;
267 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
268 papprox_integration pai = regular_simplex_pim->approx_method();
270 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");
272 if ((integrate_where != INTEGRATE_ALL) &&
273 !convexes_arein[i])
continue;
275 if (base_singular_pim && mls->crack_tip_convexes().is_in(cv)) {
277 unsigned sing_ls = unsigned(-1);
280 if (mls->get_level_set(ils)->has_secondary()) {
281 for (
unsigned ipt = 0; ipt <= n; ++ipt) {
282 if (gmm::abs((*(mesherls0[ils]))(msh.points_of_convex(i)[ipt]))
284 && gmm::abs((*(mesherls1[ils]))(msh.points_of_convex(i)[ipt]))
286 if (sing_ls ==
unsigned(-1)) sing_ls = ils;
287 GMM_ASSERT1(sing_ls == ils,
"Two singular point in one "
288 "sub element : " << sing_ls <<
", " << ils <<
290 ptsing.push_back(ipt);
294 assert(ptsing.size() < n);
296 if (ptsing.size() > 0) {
297 std::stringstream sts;
299 <<
", " << ptsing[0];
300 if (ptsing.size() > 1) sts <<
", " << ptsing[1];
307 vectors_to_base_matrix(G2,
linked_mesh().points_of_convex(cv));
309 cc(
linked_mesh().trans_of_convex(cv), pai->point(0), G2);
311 if (integrate_where & (INTEGRATE_INSIDE | INTEGRATE_OUTSIDE)) {
313 vectors_to_base_matrix(G, msh.points_of_convex(i));
317 for (
size_type j = 0; j < pai->nb_points_on_convex(); ++j) {
318 c.set_xref(pai->point(j));
319 pgt2->poly_vector_grad(pai->point(j), pc);
322 new_approx->add_point(c.xreal(), pai->coeff(j) * gmm::abs(J));
334 for (
short_type f = 0; f < pgt2->structure()->nb_faces(); ++f) {
336 unsigned isin = unsigned(-1);
338 if (integrate_where == INTEGRATE_BOUNDARY) {
340 for (
const base_node &pt : msh.points_of_face_of_convex(i, f)) {
341 isin = is_point_in_selected_area(mesherls0, mesherls1, pt).bin;
343 if (!isin) { lisin =
false;
break; }
345 if (!lisin)
continue;
348 B = gmm::mean_value(msh.points_of_face_of_convex(i, f));
349 if (pgt->convex_ref()->is_in(B) < -1E-7)
continue;
350 for (
short_type fi = 0; fi < pgt->structure()->nb_faces(); ++fi) {
351 if (gmm::abs(pgt->convex_ref()->is_in_face(fi, B)) < 2E-6) ff = fi;
355 cout <<
"Distance to the element : "
356 << pgt->convex_ref()->is_in(B) << endl;
357 for (
short_type fi = 0; fi < pgt->structure()->nb_faces(); ++fi) {
358 cout <<
"Distance to face " << fi <<
" : "
359 << gmm::abs(pgt->convex_ref()->is_in_face(fi, B)) << endl;
361 GMM_ASSERT3(
false,
"the point is neither in the interior nor "
362 "the boundary of the element");
366 vectors_to_base_matrix(G, msh.points_of_convex(i));
371 for (
size_type j = 0; j < pai->nb_points_on_face(f); ++j) {
372 if (gmm::abs(c.J()) > 1E-11) {
373 c.set_xref(pai->point_on_face(f, j));
374 base_small_vector un = pgt2->normals()[f], up(msh.dim());
379 if (integrate_where == INTEGRATE_BOUNDARY) {
380 cc.set_xref(c.xreal());
381 mesherls0[isin]->grad(c.xreal(), un);
386 new_approx->add_point(c.xreal(), pai->coeff_on_face(f, j)
387 * gmm::abs(c.J()) * nup * nnup, ff);
393 if (new_approx->nb_points()) {
394 new_approx->valid_method();
396 pim = std::make_shared<integration_method>(new_approx);
397 dal::pstatic_stored_object_key
398 pk = std::make_shared<special_imls_key>(new_approx);
400 new_approx->pintegration_points());
401 build_methods.push_back(pim);
407 GMM_ASSERT1(linked_mesh_ != 0,
"mesh level set uninitialized");
409 clear_build_methods();
412 !cv.finished(); ++cv) {
413 if (mls->is_convex_cut(cv)) build_method_of_convex(cv);
419 if (integrate_where == INTEGRATE_BOUNDARY) {
421 }
else if (integrate_where != (INTEGRATE_OUTSIDE|INTEGRATE_INSIDE)) {
423 std::vector<pmesher_signed_distance> mesherls0(mls->
nb_level_sets());
424 std::vector<pmesher_signed_distance> mesherls1(mls->
nb_level_sets());
426 mesherls0[i] = mls->get_level_set(i)->mls_of_convex(cv, 0,
false);
427 if (mls->get_level_set(i)->has_secondary())
428 mesherls1[i] = mls->get_level_set(i)->mls_of_convex(cv,1,
false);
431 base_node B(gmm::mean_value(
linked_mesh().trans_of_convex(cv)
432 ->convex_ref()->points()));
433 if (!is_point_in_selected_area(mesherls0, mesherls1, B).in)
438 is_adapted =
true; touch();
442 void mesh_im_level_set::compute_normal_vector
445 std::vector<pmesher_signed_distance> mesherls0(nb_ls);
447 base_small_vector un(ctx.pgt()->dim());
450 gmm::clear(vec);
return;
451 }
else if (nb_ls == 1) {
453 = mls->get_level_set(0)->mls_of_convex(ctx.
convex_num(), 0,
false);
455 scalar_type d_min(0);
456 for (
unsigned i = 0; i < nb_ls; ++i) {
458 = mls->get_level_set(i)->mls_of_convex(ctx.
convex_num(), 0,
false);
459 scalar_type d = gmm::abs((*(mesherls0[i]))(ctx.
xref()));
460 if (i == 0 || d < d_min) { d_min = d; j = i; }
463 mesherls0[j]->grad(ctx.
xref(), un);
466 if (no != scalar_type(0))
467 gmm::scale(vec, scalar_type(1) / gmm::vect_norm2(vec));
473 { is_adapted =
false; }
475 void mesh_im_cross_level_set::clear_build_methods() {
476 for (
size_type i = 0; i < build_methods.size(); ++i)
477 if (build_methods[i].get()) del_stored_object(build_methods[i]);
478 build_methods.clear();
482 void mesh_im_cross_level_set::clear(
void)
483 { mesh_im::clear(); clear_build_methods(); is_adapted =
false; }
485 void mesh_im_cross_level_set::init_with_mls(mesh_level_set &me,
487 pintegration_method pim) {
488 init_with_mesh(me.linked_mesh());
489 cut_im.init_with_mesh(me.linked_mesh());
491 ind_ls1 = ind_ls1_; ind_ls2 = ind_ls2_;
493 this->add_dependency(*mls);
497 mesh_im_cross_level_set::mesh_im_cross_level_set(mesh_level_set &me,
499 pintegration_method pim)
500 { mls = 0; init_with_mls(me, ind_ls1_, ind_ls2_, pim); }
502 mesh_im_cross_level_set::mesh_im_cross_level_set(
void)
503 { mls = 0; is_adapted =
false; }
518 static bool is_point_in_intersection
519 (
const std::vector<pmesher_signed_distance> &mesherls0,
520 const std::vector<pmesher_signed_distance> &mesherls1,
521 const base_node& P) {
524 for (
unsigned i = 0; i < mesherls0.size(); ++i) {
525 bool sec = (
dynamic_cast<const mesher_level_set *
>(mesherls1[i].get()))->is_initialized();
526 scalar_type d1 = (*(mesherls0[i]))(P);
527 scalar_type d2 = (sec ? (*(mesherls1[i]))(P) : -1);
528 if (!(gmm::abs(d1) < 1e-7 && d2 < 1e-7)) r =
false;
533 static bool is_edges_intersect(
const base_node &PP1,
const base_node &PP2,
534 const base_node &PR1,
const base_node &PR2) {
535 size_type n = gmm::vect_size(PP1), k1 = 0;
536 scalar_type c1 = scalar_type(0);
537 base_node V = PR2 - PR1;
539 if (gmm::abs(V[k]) > gmm::abs(c1)) { c1 = V[k]; k1 = k; }
541 scalar_type alpha1 = (PP1[k1] - PR1[k1]) / c1;
542 scalar_type alpha2 = (PP2[k1] - PR1[k1]) / c1;
543 base_node W1 = PP1 - PR1 - alpha1 * V;
544 base_node W2 = PP2 - PR1 - alpha2 * V;
547 if (alpha1 > 1.-1e-7 && alpha2 > 1.-1e-7)
return false;
548 if (alpha1 < 1e-7 && alpha2 < 1e-7)
return false;
553 void mesh_im_cross_level_set::build_method_of_convex
555 const mesh &msh(mls->mesh_of_convex(cv));
556 GMM_ASSERT3(msh.convex_index().card() != 0,
"Internal error");
560 std::vector<pmesher_signed_distance> mesherls0(2);
561 std::vector<pmesher_signed_distance> mesherls1(2);
562 dal::bit_vector convexes_arein;
564 mesherls0[0] = mls->get_level_set(ind_ls1)->mls_of_convex(cv, 0,
false);
565 mesherls0[1] = mls->get_level_set(ind_ls2)->mls_of_convex(cv, 0,
false);
566 if (mls->get_level_set(ind_ls1)->has_secondary())
567 mesherls1[0] = mls->get_level_set(ind_ls1)->mls_of_convex(cv, 1,
false);
568 if (mls->get_level_set(ind_ls2)->has_secondary())
569 mesherls1[1] = mls->get_level_set(ind_ls2)->mls_of_convex(cv, 1,
false);
573 = msh.trans_of_convex(msh.convex_index().first_true());
574 dim_type n = pgt->dim();
576 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
577 new_approx->set_built_on_the_fly();
578 base_matrix KK(n,n), CS(n,n);
579 base_matrix pc(pgt2->nb_points(), n);
580 std::vector<size_type> ptsing;
582 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
583 papprox_integration pai = segment_pim->approx_method();
584 GMM_ASSERT1(gmm::vect_size(pai->point(0)) == 1,
585 "A segment integration method is needed");
588 vectors_to_base_matrix(G2,
linked_mesh().points_of_convex(cv));
590 cc(
linked_mesh().trans_of_convex(cv), base_node(n), G2);
592 mesh::ref_mesh_pt_ct cvpts = msh.points_of_convex(i);
594 dal::bit_vector ptinter;
596 size_type ipt = msh.structure_of_convex(i)->ind_dir_points()[k];
597 const base_node &P = cvpts[ipt];
598 if (is_point_in_intersection(mesherls0, mesherls1, P))
605 size_type ipt = msh.structure_of_convex(i)->ind_dir_points()[k];
606 if (ptinter.is_in(ipt)) {
608 const base_node &P = cvpts[ipt];
611 if (global_intersection.search_point(cc.xreal())
613 global_intersection.add_point(cc.xreal());
614 new_approx->add_point(msh.points_of_convex(i)[ipt],
624 size_type ipt1 = msh.structure_of_convex(i)->ind_dir_points()[k1];
626 size_type ipt2=msh.structure_of_convex(i)->ind_dir_points()[k2];
627 if (ptinter.is_in(ipt1) && ptinter.is_in(ipt2)) {
629 const base_node &P1 = cvpts[ipt1];
630 const base_node &P2 = cvpts[ipt2];
632 base_node PR1 = cc.xreal();
634 base_node PR2 = cc.xreal();
636 size_type i1 = global_intersection.search_point(PR1);
637 size_type i2 = global_intersection.search_point(PR2);
640 !global_intersection.nb_convex_with_edge(i1, i2)) {
642 base_node min(n), max(n);
644 min[k] = std::min(PR1[k], PR2[k]);
645 max[k] = std::max(PR1[k], PR2[k]);
647 bgeot::rtree::pbox_set boxlst;
648 rtree_seg.find_intersecting_boxes(min, max, boxlst);
650 bool found_intersect =
false;
652 for (bgeot::rtree::pbox_set::const_iterator
653 it=boxlst.begin(); it != boxlst.end(); ++it) {
654 mesh::ref_mesh_pt_ct intersect_cvpts
655 = global_intersection.points_of_convex((*it)->id);
656 const base_node &PP1 = intersect_cvpts[0];
657 const base_node &PP2 = intersect_cvpts[1];
658 if (is_edges_intersect(PP1, PP2, PR1, PR2))
659 { found_intersect =
true;
break; }
662 if (!found_intersect) {
664 i1 = global_intersection.add_point(PR1);
665 i2 = global_intersection.add_point(PR2);
667 size_type is = global_intersection.add_segment(i1, i2);
669 rtree_seg.add_box(min, max, is);
670 rtree_seg.build_tree();
674 = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
676 = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
677 base_node V = PE2 - PE1, W1(n), W2(n);
680 vectors_to_base_matrix(G3, msh.points_of_convex(i));
682 ccc(msh.trans_of_convex(i), base_node(n), G3);
684 for (
size_type j=0; j < pai->nb_points_on_convex(); ++j) {
685 base_node PE = pai->point(j)[0] * PE2
686 + (scalar_type(1) - pai->point(j)[0]) * PE1;
688 cc.set_xref(ccc.xreal());
691 new_approx->add_point(ccc.xreal(),
692 pai->coeff(j) * gmm::vect_norm2(W2));
701 default: GMM_ASSERT1(
false,
"internal error");
706 if (new_approx->nb_points()) {
707 new_approx->valid_method();
709 pim = std::make_shared<integration_method>(new_approx);
710 dal::pstatic_stored_object_key
711 pk = std::make_shared<special_imls_key>(new_approx);
713 new_approx->pintegration_points());
714 build_methods.push_back(pim);
720 GMM_ASSERT1(linked_mesh_ != 0,
"mesh level set uninitialized");
721 GMM_ASSERT1(linked_mesh_->dim() > 1 && linked_mesh_->dim() <= 3,
722 "Sorry, works only in dimension 2 or 3");
725 clear_build_methods();
727 mesh global_intersection;
730 std::vector<size_type> icv;
731 std::vector<dal::bit_vector> ils;
732 mls->find_level_set_potential_intersections(icv, ils);
734 for (
size_type i = 0; i < icv.size(); ++i) {
735 if (ils[i].is_in(ind_ls1) && ils[i].is_in(ind_ls2)) {
736 build_method_of_convex(icv[i], global_intersection, rtree_seg);
741 !cv.finished(); ++cv)
742 if (!cut_im.
convex_index().is_in(cv)) ignored_im.add(cv);
744 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