GetFEM  5.5
getfem_mesh_im_level_set.cc
1 /*===========================================================================
2 
3  Copyright (C) 2005-2026 Yves Renard
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
22 #include "getfem/getfem_mesher.h"
23 #include "getfem/bgeot_kdtree.h"
24 
25 namespace getfem {
26 
28  { is_adapted = false; }
29 
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();
34  cut_im.clear();
35  }
36 
37  void mesh_im_level_set::clear(void) {
38  mesh_im::clear();
39  clear_build_methods();
40  is_adapted = false;
41  }
42 
43  void mesh_im_level_set::init_with_mls(mesh_level_set &me,
44  int integrate_where_,
45  pintegration_method reg,
46  pintegration_method sing) {
47  init_with_mesh(me.linked_mesh());
48  cut_im.init_with_mesh(me.linked_mesh());
49  mls = &me;
50  integrate_where = integrate_where_;
51  set_simplex_im(reg, sing);
52  this->add_dependency(*mls);
53  is_adapted = false;
54  }
55 
56  mesh_im_level_set::mesh_im_level_set(mesh_level_set &me,
57  int integrate_where_,
58  pintegration_method reg,
59  pintegration_method sing) {
60  mls = 0;
61  init_with_mls(me, integrate_where_, reg, sing);
62  }
63 
64  mesh_im_level_set::mesh_im_level_set(void)
65  { mls = 0; is_adapted = false; }
66 
67 
68  pintegration_method
70  if (!is_adapted) const_cast<mesh_im_level_set *>(this)->adapt();
71  if (cut_im.convex_index().is_in(cv))
72  return cut_im.int_method_of_element(cv);
73  else {
74  if (ignored_im.is_in(cv)) //integrate_where == INTEGRATE_BOUNDARY)
75  return getfem::im_none();
76 
78  }
79  }
80 
81  DAL_SIMPLE_KEY(special_imls_key, papprox_integration);
82 
83  /* only for INTEGRATE_INSIDE or INTEGRATE_OUTSIDE */
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,
87  const base_node& P) {
88  bool isin = true;
89  int isbin = 0;
90  for (unsigned i = 0; i < mls->nb_level_sets(); ++i) {
91  isin = isin && ((*(mesherls0[i]))(P) < 0);
92  if (gmm::abs((*(mesherls0[i]))(P)) < 1e-7)
93  isbin = i+1;
94  if (mls->get_level_set(i)->has_secondary())
95  isin = isin && ((*(mesherls1[i]))(P) < 0);
96  }
97  bool2 b;
98  b.in = ((integrate_where & INTEGRATE_OUTSIDE)) ? !isin : isin;
99  b.bin = isbin;
100  return b;
101  }
102 
103 
104  /* very rustic set operations evaluator */
105  struct is_in_eval {
106  dal::bit_vector in; // levelsets for which the point is "inside"
107  dal::bit_vector bin; // levelsets for which the point is on the boundary
108  typedef mesh_im_level_set::bool2 bool2;
109  bool2 do_expr(const char *&s) {
110  bool2 r;
111  if (*s == '(') {
112  r = do_expr(++s);
113  GMM_ASSERT1(*s++ == ')',
114  "expecting ')' in csg expression at '" << s-1 << "'");
115  } else if (*s == '!') { // complementary
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;
121  ++s;
122  } else
123  GMM_ASSERT1(false, "parse error in csg expression at '" << s << "'");
124  if (*s == '+') { // Union
125  //cerr << "s = " << s << ", r = " << r << "\n";
126  bool2 a = r, b = do_expr(++s);
127  //cerr << "->b = " << b << "\n";
128  r.in = b.in || a.in;
129  if (b.bin && !a.in) r.bin = b.bin;
130  else if (a.bin && !b.in) r.bin = a.bin;
131  else r.bin = 0;
132  } else if (*s == '-') { // Set difference
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;
137  else r.bin = 0;
138  } else if (*s == '*') { // Intersection
139  bool2 a = r, b = do_expr(++s);
140  r.in = a.in && b.in;
141  if (a.bin && b.in) r.bin = a.bin;
142  else if (a.in && b.bin) r.bin = b.bin;
143  else r.bin = 0;
144  }
145  return r;
146  }
147  bool2 is_in(const char*s) {
148  bool2 b = do_expr(s);
149  GMM_ASSERT1(!(*s), "parse error in CSG expression at " << s);
150  return b;
151  }
152  void check() {
153  const char *s[] = { "a*b*c*d",
154  "a+b+c+d",
155  "(a+b+c+d)",
156  "d*(a+b+c)",
157  "(a+b)-(c+d)",
158  "((a+b)-(c+d))",
159  "!a",
160  0 };
161  for (const char **p = s; *p; ++p)
162  cerr << *p << "\n";
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) {
170  bool2 b = is_in(*p);
171  cerr << b.in << "/" << b.bin << " ";
172  }
173  cerr << "\n";
174  }
175  }
176  };
177 
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) {
183  is_in_eval ev;
184  for (unsigned i = 0; i < mls->nb_level_sets(); ++i) {
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);
189  // if ((integrate_where & INTEGRATE_OUTSIDE) /*&& !sec*/)
190  // ev.in[i].flip();
191 
192  if (gmm::abs(d1) < 1e-7 && d2 < 1e-7)
193  ev.bin.add(i);
194  }
195 
196 
197  bool2 r;
198  if (ls_csg_description.size())
199  r = ev.is_in(ls_csg_description.c_str());
200  else {
201  r.in = (ev.in.card() == mls->nb_level_sets());
202  r.bin = (ev.bin.card() >= 1 && ev.in.card() >= mls->nb_level_sets()-1);
203  }
204 
205  if (integrate_where & INTEGRATE_OUTSIDE) r.in = !(r.in);
206 
207 
208 
209  /*bool2 r2 = is_point_in_selected_area2(mesherls0,mesherls1,P);
210  if (r2.in != r.in || r2.bin != r.bin) {
211  cerr << "ev.in = " << ev.in << ", bin=" << ev.bin<<"\n";
212  cerr << "is_point_in_selected_area2("<<P <<"): r="<<r.in<<"/"<<r.bin
213  << ", r2=" << r2.in<<"/"<<r2.bin <<"\n";
214  assert(0);
215  }*/
216 
217  return r;
218  }
219 
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");
223  base_matrix G;
224  base_node B;
225 
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;
229 
230  //std::fstream totof("totof", std::ios::out | std::ios::app);
231  for (unsigned i = 0; i < mls->nb_level_sets(); ++i) {
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);
235  }
236 
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;
242  }
243  }
244 
245  bgeot::pgeometric_trans pgt = linked_mesh().trans_of_convex(cv);
247  = msh.trans_of_convex(msh.convex_index().first_true());
248  dim_type n = pgt->dim();
249 
250  if (base_singular_pim) GMM_ASSERT1
251  ((n != 2 ||
252  base_singular_pim->structure()== bgeot::parallelepiped_structure(2))
253  && (n != 3
254  || base_singular_pim->structure() == bgeot::prism_P1_structure(3))
255  && (n >= 2) && (n <= 3),
256  "Base integration method for quasi polar integration not convenient");
257 
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;
263 
264  // cout << "testing convex " << cv << ", " << msh.convex_index().card() << " subconvexes\n";
265 
266  for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
267  papprox_integration pai = regular_simplex_pim->approx_method();
268 
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");
270 
271  if ((integrate_where != INTEGRATE_ALL) &&
272  !convexes_arein[i]) continue;
273 
274  if (base_singular_pim && mls->crack_tip_convexes().is_in(cv)) {
275  ptsing.resize(0);
276  unsigned sing_ls = unsigned(-1);
277 
278  for (unsigned ils = 0; ils < mls->nb_level_sets(); ++ils)
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]))
282  < 1E-10
283  && gmm::abs((*(mesherls1[ils]))(msh.points_of_convex(i)[ipt]))
284  < 1E-10) {
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 <<
288  ". To be done.");
289  ptsing.push_back(ipt);
290  }
291  }
292  }
293  assert(ptsing.size() < n);
294 
295  if (ptsing.size() > 0) {
296  std::stringstream sts;
297  sts << "IM_QUASI_POLAR(" << name_of_int_method(base_singular_pim)
298  << ", " << ptsing[0];
299  if (ptsing.size() > 1) sts << ", " << ptsing[1];
300  sts << ")";
301  pai = int_method_descriptor(sts.str())->approx_method();
302  }
303  }
304 
305  base_matrix G2;
306  vectors_to_base_matrix(G2, linked_mesh().points_of_convex(cv));
308  cc(linked_mesh().trans_of_convex(cv), pai->point(0), G2);
309 
310  if (integrate_where & (INTEGRATE_INSIDE | INTEGRATE_OUTSIDE)) {
311 
312  vectors_to_base_matrix(G, msh.points_of_convex(i));
313  bgeot::geotrans_interpolation_context c(msh.trans_of_convex(i),
314  pai->point(0), G);
315 
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);
319  gmm::mult(G,pc,KK);
320  scalar_type J = gmm::lu_det(KK);
321  new_approx->add_point(c.xreal(), pai->coeff(j) * gmm::abs(J));
322 
323  /*if (integrate_where == INTEGRATE_INSIDE) {
324  cc.set_xref(c.xreal());
325  totof << cc.xreal()[0] << "\t" << cc.xreal()[1] << "\t"
326  << pai->coeff(j) * gmm::abs(J) << "\n";
327  }*/
328  }
329  }
330 
331  // pgt2 = msh.trans_of_convex(i);
332 
333  for (short_type f = 0; f < pgt2->structure()->nb_faces(); ++f) {
334  short_type ff = short_type(-1);
335  unsigned isin = unsigned(-1);
336 
337  if (integrate_where == INTEGRATE_BOUNDARY) {
338  bool lisin = true;
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;
341  //cerr << pt << ":" << isin << " ";
342  if (!isin) { lisin = false; break; }
343  }
344  if (!lisin) continue;
345  else isin--;
346  } else {
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;
351  }
352 
353  if (ff == short_type(-1)) {
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;
359  }
360  GMM_ASSERT3(false, "the point is neither in the interior nor "
361  "the boundary of the element");
362  }
363  }
364 
365  vectors_to_base_matrix(G, msh.points_of_convex(i));
366  bgeot::geotrans_interpolation_context c(msh.trans_of_convex(i),
367  pai->point(0), G);
368 
369 
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());
374  gmm::mult(c.B(), un, up);
375  scalar_type nup = gmm::vect_norm2(up);
376 
377  scalar_type nnup(1);
378  if (integrate_where == INTEGRATE_BOUNDARY) {
379  cc.set_xref(c.xreal());
380  mesherls0[isin]->grad(c.xreal(), un);
381  un /= gmm::vect_norm2(un);
382  gmm::mult(cc.B(), un, up);
383  nnup = gmm::vect_norm2(up);
384  }
385  new_approx->add_point(c.xreal(), pai->coeff_on_face(f, j)
386  * gmm::abs(c.J()) * nup * nnup, ff);
387  }
388  }
389  }
390  }
391 
392  if (new_approx->nb_points()) {
393  new_approx->valid_method();
394  pintegration_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);
398  dal::add_stored_object(pk, pim, new_approx->ref_convex(),
399  new_approx->pintegration_points());
400  build_methods.push_back(pim);
401  cut_im.set_integration_method(cv, pim);
402  }
403  }
404 
406  GMM_ASSERT1(linked_mesh_ != 0, "mesh level set uninitialized");
407  context_check();
408  clear_build_methods();
409  ignored_im.clear();
410  for (dal::bv_visitor cv(linked_mesh().convex_index());
411  !cv.finished(); ++cv) {
412  if (mls->is_convex_cut(cv)) build_method_of_convex(cv);
413 
414  if (!cut_im.convex_index().is_in(cv)) {
415  /* not exclusive with mls->is_convex_cut ... sometimes, cut cv
416  contains no integration points.. */
417 
418  if (integrate_where == INTEGRATE_BOUNDARY) {
419  ignored_im.add(cv);
420  } else if (integrate_where != (INTEGRATE_OUTSIDE|INTEGRATE_INSIDE)) {
421  /* remove convexes that are not in the integration area */
422  std::vector<pmesher_signed_distance> mesherls0(mls->nb_level_sets());
423  std::vector<pmesher_signed_distance> mesherls1(mls->nb_level_sets());
424  for (unsigned i = 0; i < mls->nb_level_sets(); ++i) {
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);
428  }
429 
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)
433  ignored_im.add(cv);
434  }
435  }
436  }
437  is_adapted = true; touch();
438  // cout << "Number of built methods : " << build_methods.size() << endl;
439  }
440 
441  void mesh_im_level_set::compute_normal_vector
442  (const fem_interpolation_context &ctx, base_small_vector &vec) const {
443  size_type nb_ls = mls->nb_level_sets(), j = 0;
444  std::vector<pmesher_signed_distance> mesherls0(nb_ls);
445  if (vec.size() != linked_mesh().dim()) vec.resize(linked_mesh().dim());
446  base_small_vector un(ctx.pgt()->dim());
447 
448  if (nb_ls == 0) {
449  gmm::clear(vec); return;
450  } else if (nb_ls == 1) {
451  mesherls0[0]
452  = mls->get_level_set(0)->mls_of_convex(ctx.convex_num(), 0, false);
453  } else {
454  scalar_type d_min(0);
455  for (unsigned i = 0; i < nb_ls; ++i) {
456  mesherls0[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; }
460  }
461  }
462  mesherls0[j]->grad(ctx.xref(), un);
463  gmm::mult(ctx.B(), un, vec);
464  scalar_type no = gmm::vect_norm2(vec);
465  if (no != scalar_type(0))
466  gmm::scale(vec, scalar_type(1) / gmm::vect_norm2(vec));
467  }
468 
469 
470 
472  { is_adapted = false; }
473 
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();
478  cut_im.clear();
479  }
480 
481  void mesh_im_cross_level_set::clear(void)
482  { mesh_im::clear(); clear_build_methods(); is_adapted = false; }
483 
484  void mesh_im_cross_level_set::init_with_mls(mesh_level_set &me,
485  size_type ind_ls1_, size_type ind_ls2_,
486  pintegration_method pim) {
487  init_with_mesh(me.linked_mesh());
488  cut_im.init_with_mesh(me.linked_mesh());
489  mls = &me;
490  ind_ls1 = ind_ls1_; ind_ls2 = ind_ls2_;
491  set_segment_im(pim);
492  this->add_dependency(*mls);
493  is_adapted = false;
494  }
495 
496  mesh_im_cross_level_set::mesh_im_cross_level_set(mesh_level_set &me,
497  size_type ind_ls1_, size_type ind_ls2_,
498  pintegration_method pim)
499  { mls = 0; init_with_mls(me, ind_ls1_, ind_ls2_, pim); }
500 
501  mesh_im_cross_level_set::mesh_im_cross_level_set(void)
502  { mls = 0; is_adapted = false; }
503 
504 
505  pintegration_method
507  if (!is_adapted) const_cast<mesh_im_cross_level_set *>(this)->adapt();
508  if (cut_im.convex_index().is_in(cv))
509  return cut_im.int_method_of_element(cv);
510  else {
511  if (ignored_im.is_in(cv)) return getfem::im_none();
512 
514  }
515  }
516 
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) {
521 
522  bool r = true;
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;
528  }
529  return r;
530  }
531 
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;
537  for (size_type k = 0; k < n; ++k)
538  if (gmm::abs(V[k]) > gmm::abs(c1)) { c1 = V[k]; k1 = k; }
539 
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;
544  if (gmm::vect_norm2(W1) > 1e-7*gmm::vect_norm2(V)) return false;
545  if (gmm::vect_norm2(W2) > 1e-7*gmm::vect_norm2(V)) return false;
546  if (alpha1 > 1.-1e-7 && alpha2 > 1.-1e-7) return false;
547  if (alpha1 < 1e-7 && alpha2 < 1e-7) return false;
548  return true;
549  }
550 
551 
552  void mesh_im_cross_level_set::build_method_of_convex
553  (size_type cv, mesh &global_intersection, bgeot::rtree &rtree_seg) {
554  const mesh &msh(mls->mesh_of_convex(cv));
555  GMM_ASSERT3(msh.convex_index().card() != 0, "Internal error");
556  base_matrix G;
557  base_node B;
558 
559  std::vector<pmesher_signed_distance> mesherls0(2);
560  std::vector<pmesher_signed_distance> mesherls1(2);
561  dal::bit_vector convexes_arein;
562 
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);
569 
570  bgeot::pgeometric_trans pgt = linked_mesh().trans_of_convex(cv);
572  = msh.trans_of_convex(msh.convex_index().first_true());
573  dim_type n = pgt->dim();
574 
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;
580 
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");
585 
586  base_matrix G2;
587  vectors_to_base_matrix(G2, linked_mesh().points_of_convex(cv));
589  cc(linked_mesh().trans_of_convex(cv), base_node(n), G2);
590 
591  mesh::ref_mesh_pt_ct cvpts = msh.points_of_convex(i);
592 
593  dal::bit_vector ptinter;
594  for (short_type k = 0; k < n; ++k) {
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))
598  ptinter.add(ipt);
599  }
600 
601  switch (n) {
602  case 2:
603  for (short_type k = 0; k < n; ++k) {
604  size_type ipt = msh.structure_of_convex(i)->ind_dir_points()[k];
605  if (ptinter.is_in(ipt)) {
606 
607  const base_node &P = cvpts[ipt];
608  cc.set_xref(P);
609 
610  if (global_intersection.search_point(cc.xreal())
611  == size_type(-1)) {
612  global_intersection.add_point(cc.xreal());
613  new_approx->add_point(msh.points_of_convex(i)[ipt],
614  scalar_type(1));
615  }
616 
617  }
618  }
619  break;
620  case 3:
621  {
622  for (short_type k1 = 1; k1 < n; ++k1) {
623  size_type ipt1 = msh.structure_of_convex(i)->ind_dir_points()[k1];
624  for (short_type k2 = 0; k2 < k1; ++k2) {
625  size_type ipt2=msh.structure_of_convex(i)->ind_dir_points()[k2];
626  if (ptinter.is_in(ipt1) && ptinter.is_in(ipt2)) {
627 
628  const base_node &P1 = cvpts[ipt1];
629  const base_node &P2 = cvpts[ipt2];
630  cc.set_xref(P1);
631  base_node PR1 = cc.xreal();
632  cc.set_xref(P2);
633  base_node PR2 = cc.xreal();
634 
635  size_type i1 = global_intersection.search_point(PR1);
636  size_type i2 = global_intersection.search_point(PR2);
637 
638  if (i1 == size_type(-1) || i2 == size_type(-1) ||
639  !global_intersection.nb_convex_with_edge(i1, i2)) {
640 
641  base_node min(n), max(n);
642  for (size_type k = 0; k < n; ++k) {
643  min[k] = std::min(PR1[k], PR2[k]);
644  max[k] = std::max(PR1[k], PR2[k]);
645  }
646  bgeot::rtree::pbox_set boxlst;
647  rtree_seg.find_intersecting_boxes(min, max, boxlst);
648 
649  bool found_intersect = false;
650 
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; }
659  }
660 
661  if (!found_intersect) {
662 
663  i1 = global_intersection.add_point(PR1);
664  i2 = global_intersection.add_point(PR2);
665 
666  size_type is = global_intersection.add_segment(i1, i2);
667 
668  rtree_seg.add_box(min, max, is);
669  rtree_seg.build_tree(); // Not efficient !
670 
671 
672  const base_node &PE1
673  = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
674  const base_node &PE2
675  = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
676  base_node V = PE2 - PE1, W1(n), W2(n);
677 
678  base_matrix G3;
679  vectors_to_base_matrix(G3, msh.points_of_convex(i));
681  ccc(msh.trans_of_convex(i), base_node(n), G3);
682 
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;
686  ccc.set_xref(PE);
687  cc.set_xref(ccc.xreal());
688  gmm::mult(ccc.K(), V, W1);
689  gmm::mult(cc.K(), W1, W2);
690  new_approx->add_point(ccc.xreal(),
691  pai->coeff(j) * gmm::vect_norm2(W2));
692  }
693  }
694  }
695  }
696  }
697  }
698  }
699  break;
700  default: GMM_ASSERT1(false, "internal error");
701 
702  }
703  }
704 
705  if (new_approx->nb_points()) {
706  new_approx->valid_method();
707  pintegration_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);
711  dal::add_stored_object(pk, pim, new_approx->ref_convex(),
712  new_approx->pintegration_points());
713  build_methods.push_back(pim);
714  cut_im.set_integration_method(cv, pim);
715  }
716  }
717 
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");
722 
723  context_check();
724  clear_build_methods();
725  ignored_im.clear();
726  mesh global_intersection;
727  bgeot::rtree rtree_seg;
728 
729  std::vector<size_type> icv;
730  std::vector<dal::bit_vector> ils;
731  mls->find_level_set_potential_intersections(icv, ils);
732 
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);
736  }
737  }
738 
739  for (dal::bv_visitor cv(linked_mesh().convex_index());
740  !cv.finished(); ++cv)
741  if (!cut_im.convex_index().is_in(cv)) ignored_im.add(cv);
742 
743  is_adapted = true; touch();
744  }
745 
746 
747 } /* end of namespace getfem. */
748 
749 
750 
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.
Definition: bgeot_rtree.h:97
bool context_check() const
return true if update_from_context was called
structure passed as the argument of fem interpolation functions.
Definition: getfem_fem.h:749
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).
Definition: getfem_mesh.h:98
a subclass of mesh_im which is conformal to a number of level sets.
An experimental mesher.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
Definition: gmm_blas.h:556
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
linalg_traits< DenseMatrixLU >::value_type lu_det(const DenseMatrixLU &LU, const Pvector &pvector)
Compute the matrix determinant (via a LU factorization)
Definition: gmm_dense_lu.h:240
size_type convex_num() const
get the current convex number
Definition: getfem_fem.cc:52
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:72
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
Definition: bgeot_poly.h:48
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