GetFEM  5.5
getfem_mesh.cc
1 /*===========================================================================
2 
3  Copyright (C) 1999-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 
21 #include "getfem/bgeot_torus.h"
22 #include "getfem/dal_singleton.h"
24 #include "getfem/getfem_mesh.h"
26 
27 #if defined(GETFEM_HAVE_METIS_OLD_API)
28 extern "C" void METIS_PartGraphKway(int *, int *, int *, int *, int *, int *,
29  int *, int *, int *, int *, int *);
30 #elif defined(GETFEM_HAVE_METIS)
31 # include <metis.h>
32 #endif
33 
34 namespace getfem {
35 
36  gmm::uint64_type act_counter(void) {
37  static gmm::uint64_type c = gmm::uint64_type(1);
38  return ++c;
39  }
40 
42  for (dal::bv_visitor i(valid_cvf_sets); !i.finished(); ++i)
43  cvf_sets[i].sup_all(c);
44  touch();
45  }
46 
47  void mesh::swap_convex_in_regions(size_type c1, size_type c2) {
48  for (dal::bv_visitor i(valid_cvf_sets); !i.finished(); ++i)
49  cvf_sets[i].swap_convex(c1, c2);
50  touch();
51  }
52 
53  void mesh::handle_region_refinement(size_type ic,
54  const std::vector<size_type> &icv,
55  bool refine) {
56 
57  bgeot::pgeometric_trans pgt = trans_of_convex(ic);
58  ind_set s;
59 
60  for (dal::bv_visitor ir(valid_cvf_sets); !ir.finished(); ++ir) {
61  mesh_region &r = cvf_sets[ir];
62 
63 
64  if (refine && r[ic].any()) {
65  if (r[ic][0])
66  for (size_type jc = 0; jc < icv.size(); ++jc)
67  r.add(icv[jc]);
68 
70  for (short_type f = 0; f < pgt->structure()->nb_faces(); ++f) {
71  if (r[ic][f+1]) {
72 
73  for (size_type jc = 0; jc < icv.size(); ++jc) {
74  bgeot::pgeometric_trans pgtsub = trans_of_convex(icv[jc]);
75  for (short_type fsub = 0; fsub < pgtsub->structure()->nb_faces();
76  ++fsub) {
77  neighbors_of_convex(icv[jc], fsub, s);
78  ind_set::const_iterator it = s.begin(), ite = s.end();
79  bool found = false;
80  for (; it != ite; ++it)
81  if (std::find(icv.begin(), icv.end(), *it) != icv.end())
82  { found = true; break; }
83  if (found) continue;
84 
85  base_node pt, barycentre
86  =gmm::mean_value(pgtsub->convex_ref()->points_of_face(fsub));
87  pt = pgtsub->transform(barycentre, points_of_convex(icv[jc]));
88 
89  giv.init(points_of_convex(ic), pgt);
90  giv.invert(pt, barycentre);
91 
92 
93  if (gmm::abs(pgt->convex_ref()->is_in_face(f,barycentre)) < 0.001)
94  r.add(icv[jc], fsub);
95  }
96  }
97  }
98  }
99  }
100 
101  for (size_type jc = 0; jc < icv.size(); ++jc)
102  if (!refine && r[icv[jc]].any()) {
103  if (r[icv[jc]][0])
104  r.add(ic);
106  bgeot::pgeometric_trans pgtsub = trans_of_convex(icv[jc]);
107  for (short_type fsub = 0; fsub < pgtsub->structure()->nb_faces();
108  ++fsub)
109  if (r[icv[jc]][fsub+1]) {
110  base_node pt, barycentre
111  = gmm::mean_value(pgtsub->convex_ref()->points_of_face(fsub));
112  pt = pgtsub->transform(barycentre, points_of_convex(icv[jc]));
113 
114  giv.init(points_of_convex(ic), pgt);
115  giv.invert(pt, barycentre);
116 
117  for (short_type f = 0; f < pgt->structure()->nb_faces(); ++f)
118  if (gmm::abs(pgt->convex_ref()->is_in_face(f,barycentre)) < 0.001)
119  { r.add(ic, f); break; }
120  }
121  }
122  }
123  }
124 
125  void mesh::init(void) {
126 #if GETFEM_PARA_LEVEL > 1
127  modified = true;
128 #endif
129  cuthill_mckee_uptodate = false;
130  }
131 
132  mesh::mesh(const std::string name) : name_(name) { init(); }
133 
134  mesh::mesh(const bgeot::basic_mesh &m, const std::string name)
135  : bgeot::basic_mesh(m), name_(name) { init(); }
136 
137  mesh::mesh(const mesh &m) : context_dependencies(),
138  std::enable_shared_from_this<getfem::mesh>()
139  { copy_from(m); }
140 
141  mesh &mesh::operator=(const mesh &m) {
142  clear_dependencies();
143  clear();
144  copy_from(m);
145  return *this;
146  }
147 
148 #if GETFEM_PARA_LEVEL > 1
149 
150  void mesh::compute_mpi_region() const {
151  int size, rank;
152  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
153  MPI_Comm_size(MPI_COMM_WORLD, &size);
154 
155  if (size < 2) {
156  mpi_region = mesh_region::all_convexes();
157  mpi_region.from_mesh(*this);
158  } else {
159  int ne = int(nb_convex());
160  std::vector<int> xadj(ne+1), adjncy, numelt(ne), npart(ne);
161  std::vector<int> indelt(nb_allocated_convex());
162 
163  double t_ref = MPI_Wtime();
164 
165  int j = 0, k = 0;
166  ind_set s;
167  for (dal::bv_visitor ic(convex_index()); !ic.finished(); ++ic, ++j) {
168  numelt[j] = ic;
169  indelt[ic] = j;
170  }
171  j = 0;
172  for (dal::bv_visitor ic(convex_index()); !ic.finished(); ++ic, ++j) {
173  xadj[j] = k;
174  neighbors_of_convex(ic, s);
175  for (ind_set::iterator it = s.begin();
176  it != s.end(); ++it) { adjncy.push_back(indelt[*it]); ++k; }
177  }
178  xadj[j] = k;
179 
180 #ifdef GETFEM_HAVE_METIS_OLD_API
181  int wgtflag = 0, numflag = 0, edgecut;
182  int options[5] = {0,0,0,0,0};
183  METIS_PartGraphKway(&ne, &(xadj[0]), &(adjncy[0]), 0, 0, &wgtflag,
184  &numflag, &size, options, &edgecut, &(npart[0]));
185 #else
186  int ncon = 1, edgecut;
187  int options[METIS_NOPTIONS] = { 0 };
188  METIS_SetDefaultOptions(options);
189  METIS_PartGraphKway(&ne, &ncon, &(xadj[0]), &(adjncy[0]), 0, 0, 0,
190  &size, 0, 0, options, &edgecut, &(npart[0]));
191 #endif
192 
193  for (size_type i = 0; i < size_type(ne); ++i)
194  if (npart[i] == rank) mpi_region.add(numelt[i]);
195 
196  if (MPI_IS_MASTER())
197  cout << "Partition time "<< MPI_Wtime()-t_ref << endl;
198  }
199  modified = false;
200  valid_sub_regions.clear();
201  }
202 
203  void mesh::compute_mpi_sub_region(size_type n) const {
204  if (valid_cvf_sets.is_in(n)) {
205  mpi_sub_region[n] = mesh_region::intersection(cvf_sets[n], mpi_region);
206  }
207  else
208  mpi_sub_region[n] = mesh_region();
209  valid_sub_regions.add(n);
210  }
211 
212  void mesh::intersect_with_mpi_region(mesh_region &rg) const {
213  if (rg.id() == mesh_region::all_convexes().id()) {
214  rg = get_mpi_region();
215  } else if (int(rg.id()) >= 0) {
216  rg = get_mpi_sub_region(rg.id());
217  } else
218  rg = mesh_region::intersection(rg, get_mpi_region());
219  }
220 #endif
221 
222  void mesh::optimize_structure(bool with_renumbering) {
223  pts.resort();
224  size_type i, j = nb_convex(), nbc = j;
225  for (i = 0; i < j; i++)
226  if (!convex_tab.index_valid(i))
227  swap_convex(i, convex_tab.ind_last());
228  if (pts.size())
229  for (i = 0, j = pts.size()-1;
230  i < j && j != ST_NIL; ++i, --j) {
231  while (i < j && j != ST_NIL && pts.index()[i]) ++i;
232  while (i < j && j != ST_NIL && !(pts.index()[j])) --j;
233  if (i < j && j != ST_NIL ) swap_points(i, j);
234  }
235  if (with_renumbering) { // Could be optimized no using only swap_convex
236  std::vector<size_type> cmk, iord(nbc), iordinv(nbc);
237  for (i = 0; i < nbc; ++i) iord[i] = iordinv[i] = i;
238 
240  for (i = 0; i < nbc; ++i) {
241  j = iordinv[cmk[i]];
242  if (i != j) {
243  swap_convex(i, j);
244  std::swap(iord[i], iord[j]);
245  std::swap(iordinv[iord[i]], iordinv[iord[j]]);
246  }
247  }
248  }
249  }
250 
251  void mesh::translation(const base_small_vector &V)
252  { pts.translation(V); touch(); }
253 
254  void mesh::transformation(const base_matrix &M) {
255  pts.transformation(M);
256  Bank_info = std::unique_ptr<Bank_info_struct>();
257  touch();
258  }
259 
260  void mesh::bounding_box(base_node& Pmin, base_node& Pmax) const {
261  bool is_first = true;
262  Pmin.clear(); Pmax.clear();
263  for (dal::bv_visitor i(pts.index()); !i.finished(); ++i) {
264  if (is_first) { Pmin = Pmax = pts[i]; is_first = false; }
265  else for (dim_type j=0; j < dim(); ++j) {
266  Pmin[j] = std::min(Pmin[j], pts[i][j]);
267  Pmax[j] = std::max(Pmax[j], pts[i][j]);
268  }
269  }
270  }
271 
272  void mesh::clear(void) {
273  mesh_structure::clear();
274  pts.clear();
275  gtab.clear(); trans_exists.clear();
276  cvf_sets.clear(); valid_cvf_sets.clear();
277  cvs_v_num.clear();
278  Bank_info = nullptr;
279  touch();
280  }
281 
283  size_type ipt[2]; ipt[0] = a; ipt[1] = b;
284  return add_convex(bgeot::simplex_geotrans(1, 1), &(ipt[0]));
285  }
286 
288  size_type b, size_type c) {
289  size_type ipt[3]; ipt[0] = a; ipt[1] = b; ipt[2] = c;
290  return add_simplex(2, &(ipt[0]));
291  }
292 
294  (const base_node &p1, const base_node &p2, const base_node &p3)
295  { return add_triangle(add_point(p1), add_point(p2), add_point(p3)); }
296 
298  size_type c, size_type d) {
299  size_type ipt[4]; ipt[0] = a; ipt[1] = b; ipt[2] = c; ipt[3] = d;
300  return add_simplex(3, &(ipt[0]));
301  }
302 
304  size_type c, size_type d, size_type e) {
305  size_type ipt[5] = {a, b, c, d, e};
306  return add_convex(bgeot::pyramid_QK_geotrans(1), &(ipt[0]));
307  }
308 
310  (const base_node &p1, const base_node &p2,
311  const base_node &p3, const base_node &p4) {
312  return add_tetrahedron(add_point(p1), add_point(p2),
313  add_point(p3), add_point(p4));
314  }
315 
317  scalar_type tol) {
318 
319  size_type nbpt = points_index().last()+1;
320  GMM_ASSERT1(nbpt == nb_points(),
321  "Please call the optimize_structure() function before "
322  "merging elements from another mesh");
323  GMM_ASSERT1(rg == size_type(-1) || msource.region(rg).is_only_convexes(),
324  "The provided mesh region should only contain convexes");
325 
326  const mesh_region &mr = msource.region(rg);
327  const dal::bit_vector &convexes = (rg == size_type(-1))
328  ? msource.convex_index() : mr.index();
329  std::vector<size_type> old2new(msource.points_index().last()+1, size_type(-1));
330  for (dal::bv_visitor cv(convexes); !cv.finished(); ++cv) {
331 
332  bgeot::pgeometric_trans pgt = msource.trans_of_convex(cv);
333  short_type nb = short_type(pgt->nb_points());
334  const ind_cv_ct &rct = msource.ind_points_of_convex(cv);
335  GMM_ASSERT1(nb == rct.size(), "Internal error");
336  std::vector<size_type> ind(nb);
337  for (short_type i = 0; i < nb; ++i) {
338  size_type old_pid = rct[i];
339  size_type new_pid = old2new[old_pid];
340  if (new_pid == size_type(-1)) {
341  size_type next_pid = points_index().last()+1;
342  base_node pt = msource.points()[old_pid];
343  new_pid = pts.add_node(pt, tol);
344  if (new_pid < next_pid && new_pid >= nbpt) {
345  // do not allow internal merging of nodes in the source mesh
346  new_pid = pts.add_node(pt, -1.);
347  GMM_ASSERT1(new_pid == next_pid, "Internal error");
348  }
349  old2new[old_pid] = new_pid;
350  }
351  ind[i] = new_pid;
352  }
353  add_convex(pgt, ind.begin());
354  }
355  }
356 
357  void mesh::sup_convex(size_type ic, bool sup_points) {
358  static std::vector<size_type> ipt;
359  if (sup_points) {
360  const ind_cv_ct &ct = ind_points_of_convex(ic);
361  ipt.assign(ct.begin(), ct.end());
362  }
364  if (sup_points)
365  for (const size_type &ip : ipt) sup_point(ip);
366  trans_exists.sup(ic);
368  if (Bank_info.get()) Bank_sup_convex_from_green(ic);
369  touch();
370  }
371 
373  if (i != j) {
375  trans_exists.swap(i, j);
376  gtab.swap(i,j);
377  swap_convex_in_regions(i, j);
378  if (Bank_info.get()) Bank_swap_convex(i,j);
379  cvs_v_num[i] = cvs_v_num[j] = act_counter(); touch();
380  }
381  }
382 
384  const base_node &pt) const {
385  bgeot::pgeometric_trans pgt = trans_of_convex(ic);
386  base_matrix G(dim(),pgt->nb_points());
387  vectors_to_base_matrix(G, points_of_convex(ic));
388  bgeot::geotrans_interpolation_context c(trans_of_convex(ic), pt, G);
389  return bgeot::compute_normal(c, f);
390  }
391 
392 
393  base_small_vector mesh::normal_of_face_of_convex(size_type ic, short_type f,
394  size_type n) const {
395  bgeot::pgeometric_trans pgt = trans_of_convex(ic);
396  bgeot::pgeotrans_precomp pgp
397  = bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
398  base_matrix G;
399  vectors_to_base_matrix(G, points_of_convex(ic));
401  c(pgp,pgt->structure()->ind_points_of_face(f)[n], G);
402  return bgeot::compute_normal(c, f);
403  }
404 
405  base_small_vector mesh::mean_normal_of_face_of_convex(size_type ic,
406  short_type f) const {
407  bgeot::pgeometric_trans pgt = trans_of_convex(ic);
408  base_matrix G; vectors_to_base_matrix(G,points_of_convex(ic));
409  base_small_vector ptmean(dim());
410  size_type nbpt = pgt->structure()->nb_points_of_face(f);
411  for (size_type i = 0; i < nbpt; ++i)
412  gmm::add(pgt->geometric_nodes()[pgt->structure()->ind_points_of_face(f)[i]], ptmean);
413  ptmean /= scalar_type(nbpt);
414  bgeot::geotrans_interpolation_context c(pgt,ptmean, G);
415  base_small_vector n = bgeot::compute_normal(c, f);
416  n /= gmm::vect_norm2(n);
417  return n;
418  }
419 
421  const base_node &pt) const {
422  bgeot::pgeometric_trans pgt = trans_of_convex(ic);
423  base_matrix G(dim(),pgt->nb_points());
424  vectors_to_base_matrix(G,points_of_convex(ic));
425  bgeot::geotrans_interpolation_context c(trans_of_convex(ic), pt, G);
426  return bgeot::compute_local_basis(c, f);
427  }
428 
430  size_type n) const {
431  bgeot::pgeometric_trans pgt = trans_of_convex(ic);
432  bgeot::pgeotrans_precomp pgp
433  = bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
434  base_matrix G(dim(),pgt->nb_points());
435  vectors_to_base_matrix(G,points_of_convex(ic));
437  c(pgp,pgt->structure()->ind_points_of_face(f)[n], G);
438  return bgeot::compute_local_basis(c, f);
439  }
440 
441  scalar_type mesh::convex_area_estimate(size_type ic, size_type deg) const {
442  base_matrix G;
443  bgeot::vectors_to_base_matrix(G, points_of_convex(ic));
445  (trans_of_convex(ic), G, classical_approx_im(trans_of_convex(ic),
446  dim_type(deg)));
447  }
448 
449  scalar_type mesh::convex_quality_estimate(size_type ic) const {
450  base_matrix G;
451  bgeot::vectors_to_base_matrix(G, points_of_convex(ic));
452  auto pgt = trans_of_convex(ic);
453  if (auto pgt_torus = dynamic_cast<const bgeot::torus_geom_trans*>(pgt.get())) {
454  pgt = pgt_torus->get_original_transformation();
455  G.resize(pgt->dim(), G.ncols());
456  }
457  return getfem::convex_quality_estimate(pgt, G);
458  }
459 
460  scalar_type mesh::convex_radius_estimate(size_type ic) const {
461  base_matrix G;
462  bgeot::vectors_to_base_matrix(G, points_of_convex(ic));
463  return getfem::convex_radius_estimate(trans_of_convex(ic), G);
464  }
465 
467  if (convex_index().empty()) return 1;
468  scalar_type r = convex_radius_estimate(convex_index().first_true());
469  for (dal::bv_visitor cv(convex_index()); !cv.finished(); ++cv) {
470  r = std::min(r, convex_radius_estimate(cv));
471  }
472  return r;
473  }
474 
476  if (convex_index().empty()) return 1;
477  scalar_type r = convex_radius_estimate(convex_index().first_true());
478  for (dal::bv_visitor cv(convex_index()); !cv.finished(); ++cv) {
479  r = std::max(r, convex_radius_estimate(cv));
480  }
481  return r;
482  }
483 
484  void mesh::set_name(const std::string& name){name_=name;}
485 
486  void mesh::copy_from(const mesh& m) {
487  clear();
488  set_name(m.name_);
489  bgeot::basic_mesh::operator=(m);
490  for (const auto &kv : m.cvf_sets) {
491  if (kv.second.get_parent_mesh() != 0)
492  cvf_sets[kv.first].set_parent_mesh(this);
493  cvf_sets[kv.first] = kv.second;
494  }
495  valid_cvf_sets = m.valid_cvf_sets;
496  cvs_v_num.clear();
497  gmm::uint64_type d = act_counter();
498  for (dal::bv_visitor i(convex_index()); !i.finished(); ++i)
499  cvs_v_num[i] = d;
500  Bank_info = std::unique_ptr<Bank_info_struct>();
501  if (m.Bank_info.get())
502  Bank_info = std::make_unique<Bank_info_struct>(*(m.Bank_info));
503  }
504 
505  struct mesh_convex_structure_loc {
506  bgeot::pgeometric_trans cstruct;
507  std::vector<size_type> pts;
508  };
509 
510  void mesh::read_from_file(std::istream &ist) {
511  gmm::stream_standard_locale sl(ist);
512  dal::bit_vector npt;
514  std::string tmp;
515  bool te = false, please_get = true;
516 
517  ist.precision(16);
518  clear();
519  ist.seekg(0);ist.clear();
520  bgeot::read_until(ist, "BEGIN POINTS LIST");
521 
522  while (!te) {
523  if (please_get) bgeot::get_token(ist, tmp); else please_get = true;
524 
525  if (!bgeot::casecmp(tmp, "END"))
526  { te = true; }
527  else if (!bgeot::casecmp(tmp, "POINT")) {
528  bgeot::get_token(ist, tmp);
529  if (!bgeot::casecmp(tmp, "COUNT")) {
530  bgeot::get_token(ist, tmp); // Ignored. Used in some applications
531  } else {
532  size_type ip = atoi(tmp.c_str());
533  dim_type d = 0;
534  GMM_ASSERT1(!npt.is_in(ip),
535  "Two points with the same index. loading aborted.");
536  npt.add(ip);
537  bgeot::get_token(ist, tmp);
538  while (isdigit(tmp[0]) || tmp[0] == '-' || tmp[0] == '+'
539  || tmp[0] == '.')
540  { tmpv[d++] = atof(tmp.c_str()); bgeot::get_token(ist, tmp); }
541  please_get = false;
542  base_node v(d);
543  for (size_type i = 0; i < d; i++) v[i] = tmpv[i];
544  size_type ipl = add_point(v);
545  if (ip != ipl) {
546  GMM_ASSERT1(!npt.is_in(ipl), "Two points [#" << ip << " and #"
547  << ipl << "] with the same coords "<< v
548  << ". loading aborted.");
549  swap_points(ip, ipl);
550  }
551  }
552  } else if (tmp.size()) {
553  GMM_ASSERT1(false, "Syntax error in file, at token '" << tmp
554  << "', pos=" << std::streamoff(ist.tellg()));
555  } else if (ist.eof()) {
556  GMM_ASSERT1(false, "Unexpected end of stream while reading mesh");
557  }
558  }
559 
560  bool tend = false;
562  dal::bit_vector ncv;
563 
564  ist.seekg(0);
565  if (!bgeot::read_until(ist, "BEGIN MESH STRUCTURE DESCRIPTION"))
566  GMM_ASSERT1(false, "This seems not to be a mesh file");
567 
568  while (!tend) {
569  tend = !bgeot::get_token(ist, tmp);
570  if (!bgeot::casecmp(tmp, "END"))
571  { tend = true; }
572  else if (!bgeot::casecmp(tmp, "CONVEX")) {
573  size_type ic;
574  bgeot::get_token(ist, tmp);
575  if (!bgeot::casecmp(tmp, "COUNT")) {
576  bgeot::get_token(ist, tmp); // Ignored. Used in some applications
577  } else {
578  ic = gmm::abs(atoi(tmp.c_str()));
579  GMM_ASSERT1(!ncv.is_in(ic),
580  "Negative or repeated index, loading aborted.");
581  ncv.add(ic);
582 
583  int rgt = bgeot::get_token(ist, tmp);
584  if (rgt != 3) { // for backward compatibility with version 1.7
585  char c; ist.get(c);
586  while (!isspace(c)) { tmp.push_back(c); ist.get(c); }
587  }
588 
590  size_type nb = pgt->nb_points();
591 
592  cv[ic].cstruct = pgt;
593  cv[ic].pts.resize(nb);
594  for (size_type i = 0; i < nb; i++) {
595  bgeot::get_token(ist, tmp);
596  cv[ic].pts[i] = gmm::abs(atoi(tmp.c_str()));
597  }
598  }
599  }
600  else if (tmp.size()) {
601  GMM_ASSERT1(false, "Syntax error reading a mesh file "
602  " at pos " << std::streamoff(ist.tellg())
603  << "(expecting 'CONVEX' or 'END', found '"<< tmp << "')");
604  } else if (ist.eof()) {
605  GMM_ASSERT1(false, "Unexpected end of stream "
606  << "(missing BEGIN MESH/END MESH ?)");
607  }
608  }
609  ist >> bgeot::skip("MESH STRUCTURE DESCRIPTION");
610 
611  for (dal::bv_visitor ic(ncv); !ic.finished(); ++ic) {
612  size_type i = add_convex(cv[ic].cstruct, cv[ic].pts.begin());
613  if (i != ic) swap_convex(i, ic);
614  }
615 
616  tend = false;
617  while (!tend) {
618  tend = !bgeot::get_token(ist, tmp);
619  // bool error = false;
620  if (bgeot::casecmp(tmp, "BEGIN")==0) {
621  bgeot::get_token(ist, tmp);
622  if (bgeot::casecmp(tmp, "BOUNDARY")==0 ||
623  bgeot::casecmp(tmp, "REGION")==0) {
624  bgeot::get_token(ist, tmp);
625  size_type bnum = atoi(tmp.c_str());
626  bgeot::get_token(ist, tmp);
627  while (true) {
628  if (bgeot::casecmp(tmp, "END")!=0) {
629  size_type ic = atoi(tmp.c_str());
630  bgeot::get_token(ist, tmp);
631  if (tmp[0] == '/') {
632  bgeot::get_token(ist, tmp);
633  if (!bgeot::casecmp(tmp, "END")) break;
634  int f = atoi(tmp.c_str());
635  region(bnum).add(ic, short_type(f));
636  bgeot::get_token(ist, tmp);
637  }
638  else {
639  region(bnum).add(ic);
640  if (!bgeot::casecmp(tmp, "END")) break;
641  }
642  } else break;
643  }
644  bgeot::get_token(ist, tmp);
645  bgeot::get_token(ist, tmp);
646  } else tend = true;
647  /*else GMM_ASSERT1(false, "Syntax error in file at token '"
648  << tmp << "' [pos=" << std::streamoff(ist.tellg())
649  << "]");*/
650  } else tend=true;
651  }
652  }
653 
654  void mesh::read_from_file(const std::string &name) {
655  std::ifstream o(name.c_str());
656  GMM_ASSERT1(o, "Mesh file '" << name << "' does not exist");
657  read_from_file(o);
658  o.close();
659  }
660 
661  template<class ITER>
662  void write_tab_to_file_(std::ostream &ost, const ITER& b_, const ITER& e)
663  { for (ITER b(b_) ; b != e; ++b) ost << " " << *b; }
664 
665  template<class ITER>
666  static void write_convex_to_file_(const mesh &ms,
667  std::ostream &ost,
668  ITER b, ITER e) {
669  for ( ; b != e; ++b) {
670  size_type i = b.index();
671  ost << " CONVEX " << i << " \'"
672  << bgeot::name_of_geometric_trans(ms.trans_of_convex(i)).c_str()
673  << "\' ";
674  write_tab_to_file_(ost, ms.ind_points_of_convex(i).begin(),
675  ms.ind_points_of_convex(i).end() );
676  ost << '\n';
677  }
678  }
679 
680  template<class ITER> static void write_point_to_file_(std::ostream &ost,
681  ITER b, ITER e)
682  { for ( ; b != e; ++b) ost << " " << *b; ost << '\n'; }
683 
684  void mesh::write_to_file(std::ostream &ost) const {
685  ost.precision(16);
686  gmm::stream_standard_locale sl(ost);
687  ost << '\n' << "BEGIN POINTS LIST" << '\n' << '\n';
688  ost << " POINT COUNT " << points().index().last_true()+1 << '\n';
689  for (size_type i = 0; i < points_tab.size(); ++i)
690  if (is_point_valid(i) ) {
691  ost << " POINT " << i;
692  write_point_to_file_(ost, pts[i].begin(), pts[i].end());
693  }
694  ost << '\n' << "END POINTS LIST" << '\n' << '\n' << '\n';
695 
696  ost << '\n' << "BEGIN MESH STRUCTURE DESCRIPTION" << '\n' << '\n';
697  ost << " CONVEX COUNT " << convex_index().last_true()+1 << '\n';
698  write_convex_to_file_(*this, ost, convex_tab.tas_begin(),
699  convex_tab.tas_end());
700  ost << '\n' << "END MESH STRUCTURE DESCRIPTION" << '\n';
701 
702  for (dal::bv_visitor bnum(valid_cvf_sets); !bnum.finished(); ++bnum) {
703  ost << "BEGIN REGION " << bnum << "\n" << region(bnum) << "\n"
704  << "END REGION " << bnum << "\n";
705  }
706  }
707 
708  void mesh::write_to_file(const std::string &name) const {
709  std::ofstream o(name.c_str());
710  GMM_ASSERT1(o, "impossible to write to file '" << name << "'");
711  o << "% GETFEM MESH FILE " << '\n';
712  o << "% GETFEM VERSION " << GETFEM_VERSION << '\n' << '\n' << '\n';
713  write_to_file(o);
714  o.close();
715  }
716 
717  size_type mesh::memsize(void) const {
718  return bgeot::mesh_structure::memsize() - sizeof(bgeot::mesh_structure)
719  + pts.memsize() + (pts.index().last_true()+1)*dim()*sizeof(scalar_type)
720  + sizeof(mesh) + trans_exists.memsize() + gtab.memsize()
721  + valid_cvf_sets.card()*sizeof(mesh_region) + valid_cvf_sets.memsize();
722  }
723 
724  struct equilateral_to_GT_PK_grad_aux : public std::vector<base_matrix> {};
725  static const base_matrix &equilateral_to_GT_PK_grad(dim_type N) {
726  std::vector<base_matrix>
728  if (N > pbm.size()) pbm.resize(N);
729  if (pbm[N-1].empty()) {
730  bgeot::pgeometric_trans pgt = bgeot::simplex_geotrans(N,1);
731  base_matrix Gr(N,N);
732  base_matrix G(N,N+1);
733  vectors_to_base_matrix
734  (G, bgeot::equilateral_simplex_of_reference(N)->points());
735  gmm::mult(G, bgeot::geotrans_precomp
736  (pgt, pgt->pgeometric_nodes(), 0)->grad(0), Gr);
737  gmm::lu_inverse(Gr);
738  pbm[N-1].swap(Gr);
739  }
740  return pbm[N-1];
741  }
742 
743 
745  const base_matrix& G,
746  pintegration_method pi) {
747  double area(0);
748  static bgeot::pgeometric_trans pgt_old = 0;
749  static bgeot::pgeotrans_precomp pgp = 0;
750  static pintegration_method pim_old = 0;
751  papprox_integration pai = get_approx_im_or_fail(pi);
752  if (pgt_old != pgt || pim_old != pi) {
753  pgt_old = pgt;
754  pim_old = pi;
755  pgp = bgeot::geotrans_precomp
756  (pgt, pai->pintegration_points(), pi);
757  }
759  for (size_type i = 0; i < pai->nb_points_on_convex(); ++i) {
760  gic.set_ii(i);
761  area += pai->coeff(i) * gic.J();
762  }
763  return area;
764  }
765 
766  /* TODO : use the geotrans from an "equilateral" reference element to
767  the real element
768  check if the sign of the determinants does change
769  (=> very very bad quality of the convex)
770  */
772  const base_matrix& G) {
773  static bgeot::pgeometric_trans pgt_old = 0;
774  static bgeot::pgeotrans_precomp pgp = 0;
775  if (pgt_old != pgt) {
776  pgt_old=pgt;
777  pgp=bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
778  }
779 
780  size_type n = (pgt->is_linear()) ? 1 : pgt->nb_points();
781  scalar_type q = 1;
782  dim_type N = dim_type(G.nrows()), P = pgt->structure()->dim();
783  base_matrix K(N,P);
784  for (size_type ip=0; ip < n; ++ip) {
785  gmm::mult(G, pgp->grad(ip), K);
786  /* TODO : this is an ugly fix for simplexes only.. there should be
787  a transformation of any pgt to the equivalent equilateral pgt
788  (for prisms etc) */
789  if (bgeot::basic_structure(pgt->structure())
791  gmm::mult(base_matrix(K),equilateral_to_GT_PK_grad(P),K);
792  q = std::max(q, gmm::condition_number(K));
793  }
794  return 1./q;
795  }
796 
798  const base_matrix& G) {
799  static bgeot::pgeometric_trans pgt_old = 0;
800  static bgeot::pgeotrans_precomp pgp = 0;
801  if (pgt_old != pgt) {
802  pgt_old=pgt;
803  pgp=bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
804  }
805  size_type N = G.nrows();
806  size_type n = (pgt->is_linear()) ? 1 : pgt->nb_points();
807  scalar_type q = 0;
808  base_matrix K(pgp->grad(0).ncols(),G.nrows());
809  for (size_type ip=0; ip < n; ++ip) {
810  gmm::mult(gmm::transposed(pgp->grad(ip)), gmm::transposed(G), K);
811  scalar_type emax, emin; gmm::condition_number(K,emin,emax);
812  q = std::max(q, emax);
813  }
814  return q * sqrt(scalar_type(N)) / scalar_type(2);
815  }
816 
817  /* extract faces of convexes which are not shared
818  + convexes whose dimension is smaller that m.dim()
819  */
820  void
821  outer_faces_of_mesh(const getfem::mesh &m, const dal::bit_vector& cvlst,
822  convex_face_ct& flist) {
823  for (dal::bv_visitor ic(cvlst); !ic.finished(); ++ic) {
824  if (m.structure_of_convex(ic)->dim() == m.dim()) {
825  for (short_type f = 0; f < m.structure_of_convex(ic)->nb_faces(); f++) {
826  if (m.neighbor_of_convex(ic,f) == size_type(-1)) {
827  flist.push_back(convex_face(ic,f));
828  }
829  }
830  } else {
831  flist.push_back(convex_face(ic, short_type(-1)));
832  }
833  }
834  }
835 
836  void outer_faces_of_mesh(const mesh &m,
837  const mesh_region &cvlst,
838  mesh_region &flist) {
839  cvlst.error_if_not_convexes();
840  for (mr_visitor i(cvlst); !i.finished(); ++i) {
841  if (m.structure_of_convex(i.cv())->dim() == m.dim()) {
842  for (short_type f = 0; f < m.structure_of_convex(i.cv())->nb_faces();
843  f++) {
844  size_type cv2 = m.neighbor_of_convex(i.cv(), f);
845  if (cv2 == size_type(-1) || !cvlst.is_in(cv2)) {
846  flist.add(i.cv(),f);
847  }
848  }
849  }
850  else flist.add(i.cv());
851  }
852  }
853 
854  /* Select all the faces of the given mesh region (counted twice if they
855  are shared by two neighbor elements)
856  */
858  mesh_region mrr;
859  mr.from_mesh(m);
860  mr.error_if_not_convexes();
861 
862  for (mr_visitor i(mr); !i.finished(); ++i) {
863  size_type cv1 = i.cv();
864  short_type nbf = m.structure_of_convex(i.cv())->nb_faces();
865  for (short_type f = 0; f < nbf; ++f)
866  mrr.add(cv1, f);
867  }
868  return mrr;
869  }
870 
871  /* Select all the faces sharing at least two element of the given mesh
872  region. Each face is represented only once and is arbitrarily chosen
873  between the two neighbor elements. Try to minimize the number of
874  elements.
875  */
877  mesh_region mrr;
878  mr.from_mesh(m);
879  mr.error_if_not_convexes();
880  dal::bit_vector visited;
881  bgeot::mesh_structure::ind_set neighbors;
882 
883  for (mr_visitor i(mr); !i.finished(); ++i) {
884  size_type cv1 = i.cv();
885  short_type nbf = m.structure_of_convex(i.cv())->nb_faces();
886  bool neighbor_visited = false;
887  for (short_type f = 0; f < nbf; ++f) {
888  neighbors.resize(0); m.neighbors_of_convex(cv1, f, neighbors);
889  for (size_type j = 0; j < neighbors.size(); ++j)
890  if (visited.is_in(neighbors[j]))
891  { neighbor_visited = true; break; }
892  }
893  if (!neighbor_visited) {
894  for (short_type f = 0; f < nbf; ++f) {
895  size_type cv2 = m.neighbor_of_convex(cv1, f);
896  if (cv2 != size_type(-1) && mr.is_in(cv2)) mrr.add(cv1,f);
897  }
898  visited.add(cv1);
899  }
900  }
901 
902  for (mr_visitor i(mr); !i.finished(); ++i) {
903  size_type cv1 = i.cv();
904  if (!(visited.is_in(cv1))) {
905  short_type nbf = m.structure_of_convex(i.cv())->nb_faces();
906  for (short_type f = 0; f < nbf; ++f) {
907  neighbors.resize(0); m.neighbors_of_convex(cv1, f, neighbors);
908  bool ok = false;
909  for (size_type j = 0; j < neighbors.size(); ++j) {
910  if (visited.is_in(neighbors[j])) { ok = false; break; }
911  if (mr.is_in(neighbors[j])) { ok = true; }
912  }
913  if (ok) { mrr.add(cv1,f); }
914  }
915  visited.add(cv1);
916  }
917  }
918  return mrr;
919  }
920 
921 
923  const base_small_vector &V,
924  scalar_type angle) {
925  mesh_region mrr;
926  scalar_type threshold = gmm::vect_norm2(V)*cos(angle);
927  for (getfem::mr_visitor i(mr); !i.finished(); ++i)
928  if (i.f() != short_type(-1)) {
929  base_node un = m.mean_normal_of_face_of_convex(i.cv(), i.f());
930  if (gmm::vect_sp(V, un) - threshold >= -1E-8)
931  mrr.add(i.cv(), i.f());
932  }
933  return mrr;
934  }
935 
937  const base_node &pt1, const base_node &pt2) {
938  mesh_region mrr;
939  size_type N = m.dim();
940  GMM_ASSERT1(pt1.size() == N && pt2.size() == N, "Wrong dimensions");
941  for (getfem::mr_visitor i(mr, m); !i.finished(); ++i)
942  if (i.f() != short_type(-1)) {
944  = m.ind_points_of_face_of_convex(i.cv(), i.f());
945 
946  bool is_in = true;
948  it != pt.end(); ++it) {
949  for (size_type j = 0; j < N; ++j)
950  if (m.points()[*it][j] < pt1[j] || m.points()[*it][j] > pt2[j])
951  { is_in = false; break; }
952  if (!is_in) break;
953  }
954  if (is_in) mrr.add(i.cv(), i.f());
955  }
956  return mrr;
957  }
958 
960  const base_node &center, scalar_type radius) {
961  mesh_region mrr;
962  size_type N = m.dim();
963  GMM_ASSERT1(center.size() == N, "Wrong dimensions");
964  for (getfem::mr_visitor i(mr, m); !i.finished(); ++i)
965  if (i.f() != short_type(-1)) {
967  = m.ind_points_of_face_of_convex(i.cv(), i.f());
968 
969  bool is_in = true;
971  it != pt.end(); ++it) {
972  scalar_type checked_radius = scalar_type(0.0);
973  for (size_type j = 0; j < N; ++j)
974  checked_radius += pow(m.points()[*it][j] - center[j], 2);
975  checked_radius = std::sqrt(checked_radius);
976  if (checked_radius > radius) { is_in = false; break; }
977  }
978  if (is_in) mrr.add(i.cv(), i.f());
979  }
980  return mrr;
981  }
982 
983  mesh_region select_convexes_in_box(const mesh &m, const mesh_region &mr,
984  const base_node &pt1, const base_node &pt2) {
985  mesh_region mrr;
986  size_type N = m.dim();
987  GMM_ASSERT1(pt1.size() == N && pt2.size() == N, "Wrong dimensions");
988  for (getfem::mr_visitor i(mr, m); !i.finished(); ++i)
989  if (i.f() == short_type(-1)) {
990  bgeot::mesh_structure::ind_cv_ct pt = m.ind_points_of_convex(i.cv());
991 
992  bool is_in = true;
993  for (bgeot::mesh_structure::ind_cv_ct::iterator it = pt.begin();
994  it != pt.end(); ++it) {
995  for (size_type j = 0; j < N; ++j)
996  if (m.points()[*it][j] < pt1[j] || m.points()[*it][j] > pt2[j])
997  { is_in = false; break; }
998  if (!is_in) break;
999  }
1000  if (is_in) mrr.add(i.cv());
1001  }
1002  return mrr;
1003  }
1004 
1005  void extrude(const mesh& in, mesh& out, size_type nb_layers, short_type degree) {
1006  dim_type dim = in.dim();
1007  base_node pt(dim+1);
1008  out.clear();
1009  size_type nbpt = in.points().index().last()+1;
1010  GMM_ASSERT1(nbpt == in.points().index().card(),
1011  "please call the optimize_structure() method before using "
1012  "the mesh as a base for prismatic mesh");
1013  size_type nb_layers_total = nb_layers * degree;
1014  for (const base_node &inpt : in.points()) {
1015  std::copy(inpt.begin(), inpt.end(), pt.begin());
1016  pt[dim] = 0.0;
1017  for (size_type j = 0; j <= nb_layers_total;
1018  ++j, pt[dim] += scalar_type(1) / scalar_type(nb_layers_total))
1019  out.add_point(pt);
1020  }
1021 
1022  std::vector<size_type> tab;
1023  for (dal::bv_visitor cv(in.convex_index()); !cv.finished(); ++cv) {
1024  size_type nbp = in.nb_points_of_convex(cv);
1025  tab.resize((degree+1)*nbp);
1026  for (size_type j = 0; j < nb_layers; ++j) {
1027  for (short_type d = 0; d < degree+1; ++d)
1028  for (size_type k = 0; k < nbp; ++k)
1029  tab[k+nbp*d] = (nb_layers_total+1)*in.ind_points_of_convex(cv)[k] + j*degree + d;
1031  bgeot::product_geotrans(in.trans_of_convex(cv),
1032  bgeot::simplex_geotrans(1,degree));
1033  out.add_convex(pgt, tab.begin());
1034  }
1035  }
1036  }
1037 }
1038 
1039 
1040 //
1041 // Bank refinement
1042 //
1043 
1044 
1045 namespace bgeot {
1046  size_type refinement_simplexe_tab(size_type n, size_type **tab);
1047 }
1048 
1049 namespace getfem {
1050 
1051  bool mesh::edge::operator <(const edge &e) const {
1052  if (i0 < e.i0) return true;
1053  if (i0 > e.i0) return false;
1054  if (i1 < e.i1) return true;
1055  if (i1 > e.i1) return false;
1056  if (i2 < e.i2) return true;
1057  return false;
1058  }
1059 
1060  void mesh::Bank_sup_convex_from_green(size_type i) {
1061  if (Bank_info.get() && Bank_info->is_green_simplex.is_in(i)) {
1062  size_type igs = Bank_info->num_green_simplex[i];
1063  green_simplex &gs = Bank_info->green_simplices[igs];
1064  for (size_type j = 0; j < gs.sub_simplices.size(); ++j) {
1065  Bank_info->num_green_simplex.erase(gs.sub_simplices[j]);
1066  Bank_info->is_green_simplex.sup(gs.sub_simplices[j]);
1067  }
1068  Bank_info->green_simplices.sup(igs);
1069  }
1070  }
1071 
1072  void mesh::Bank_swap_convex(size_type i, size_type j) {
1073  if (Bank_info.get()) {
1074  Bank_info->is_green_simplex.swap(i, j);
1075  std::map<size_type, size_type>::iterator
1076  iti = Bank_info->num_green_simplex.find(i);
1077  std::map<size_type, size_type>::iterator
1078  ite = Bank_info->num_green_simplex.end();
1079  std::map<size_type, size_type>::iterator
1080  itj = Bank_info->num_green_simplex.find(j);
1081  size_type numi(0), numj(0);
1082  if (iti != ite)
1083  { numi = iti->second; Bank_info->num_green_simplex.erase(i); }
1084  if (itj != ite)
1085  { numj = itj->second; Bank_info->num_green_simplex.erase(j); }
1086  if (iti != ite) {
1087  Bank_info->num_green_simplex[j] = numi;
1088  green_simplex &gs = Bank_info->green_simplices[numi];
1089  for (size_type k = 0; k < gs.sub_simplices.size(); ++k)
1090  if (gs.sub_simplices[k] == i) gs.sub_simplices[k] = j;
1091  else if (gs.sub_simplices[k] == j) gs.sub_simplices[k] = i;
1092  }
1093  if (itj != ite) {
1094  Bank_info->num_green_simplex[i] = numj;
1095  if (iti == ite || numi != numj) {
1096  green_simplex &gs = Bank_info->green_simplices[numj];
1097  for (size_type k = 0; k < gs.sub_simplices.size(); ++k)
1098  if (gs.sub_simplices[k] == i) gs.sub_simplices[k] = j;
1099  else if (gs.sub_simplices[k] == j) gs.sub_simplices[k] = i;
1100  }
1101  }
1102  }
1103  }
1104 
1105  void mesh::Bank_build_first_mesh(mesh &m, size_type n) {
1106  bgeot::pconvex_ref pcr = bgeot::simplex_of_reference(dim_type(n), 2);
1107  m.clear();
1108  for (size_type ip = 0; ip < pcr->nb_points(); ++ip)
1109  m.add_point(pcr->points()[ip]);
1110  size_type *tab;
1111  size_type nbc = bgeot::refinement_simplexe_tab(n, &tab);
1112  for (size_type ic = 0; ic < nbc; ++ic, tab+=(n+1))
1113  m.add_simplex(dim_type(n), tab);
1114  }
1115 
1116  struct mesh_cache_for_Bank_basic_refine_convex : public mesh {};
1117 
1118  void mesh::Bank_basic_refine_convex(size_type i) {
1119  bgeot::pgeometric_trans pgt = trans_of_convex(i);
1120  size_type n = pgt->basic_structure()->dim();
1121 
1122  static bgeot::pgeometric_trans pgt1 = 0;
1123 
1125 
1126  static bgeot::pstored_point_tab pspt = 0;
1127  static bgeot::pgeotrans_precomp pgp = 0;
1128  static std::vector<size_type> ipt, ipt2, icl;
1129 
1130  if (pgt != pgt1) {
1131  pgt1 = pgt;
1132  mesh mesh1;
1133  Bank_build_first_mesh(mesh1, n);
1134 
1135  mesh2.clear();
1136  ipt.resize(pgt->nb_points());
1137  for (size_type ic = 0; ic < mesh1.nb_convex(); ++ic) {
1138  assert(mesh1.convex_index().is_in(ic));
1139  bgeot::pgeometric_trans pgt2 = mesh1.trans_of_convex(ic);
1140  for (size_type ip = 0; ip < pgt->nb_points(); ++ip)
1141  ipt[ip] =
1142  mesh2.add_point(pgt2->transform(pgt->geometric_nodes()[ip],
1143  mesh1.points_of_convex(ic)));
1144  mesh2.add_convex(pgt, &ipt[0]);
1145  }
1146 
1147  // if (pspt) dal::del_stored_object(pspt);
1148  pspt = bgeot::store_point_tab(mesh2.points());
1149  pgp = bgeot::geotrans_precomp(pgt, pspt, 0);
1150  }
1151 
1152  base_node pt(dim());
1153  ipt.resize(pspt->size());
1154  for (size_type ip = 0; ip < pspt->size(); ++ip) {
1155  pgp->transform(points_of_convex(i), ip, pt);
1156  ipt[ip] = add_point(pt);
1157  }
1158 
1159  ipt2.resize(pgt->nb_points()); icl.resize(0);
1160  for (size_type ic = 0; ic < mesh2.nb_convex(); ++ic) {
1161  for (size_type j = 0; j < pgt->nb_points(); ++j)
1162  ipt2[j] = ipt[mesh2.ind_points_of_convex(ic)[j]];
1163  icl.push_back(add_convex(pgt, ipt2.begin()));
1164  }
1165  handle_region_refinement(i, icl, true);
1166  sup_convex(i, true);
1167  }
1168 
1169  void mesh::Bank_convex_with_edge(size_type i1, size_type i2,
1170  std::vector<size_type> &ipt) {
1171  ipt.resize(0);
1172  for (size_type k = 0; k < points_tab[i1].size(); ++k) {
1173  size_type cv = points_tab[i1][k], found = 0;
1174  const std::vector<size_type> &loc_ind = trans_of_convex(cv)->vertices();
1175  for (size_type i = 0; i < loc_ind.size(); ++i) {
1176  size_type ipp = convex_tab[cv].pts[loc_ind[i]];
1177  if (ipp == i1) ++found;
1178  if (ipp == i2) ++found;
1179  }
1180  GMM_ASSERT1(found <= 2, "Invalid convex with repeated nodes ");
1181  if (found == 2) ipt.push_back(cv);
1182  }
1183  }
1184 
1185  bool mesh::Bank_is_convex_having_points(size_type cv,
1186  const std::vector<size_type> &ipt) {
1187  size_type found = 0;
1188  const std::vector<size_type> &loc_ind = trans_of_convex(cv)->vertices();
1189  for (size_type i = 0; i < loc_ind.size(); ++i)
1190  if (std::find(ipt.begin(), ipt.end(),
1191  convex_tab[cv].pts[loc_ind[i]]) != ipt.end()) ++found;
1192  return (found >= ipt.size());
1193  }
1194 
1195  void mesh::Bank_refine_normal_convex(size_type i) {
1196  bgeot::pgeometric_trans pgt = trans_of_convex(i);
1197  GMM_ASSERT1(pgt->basic_structure() == bgeot::simplex_structure(pgt->dim()),
1198  "Sorry, refinement is only working with simplices.");
1199 
1200  const std::vector<size_type> &loc_ind = pgt->vertices();
1201  for (size_type ip1 = 0; ip1 < loc_ind.size(); ++ip1)
1202  for (size_type ip2 = ip1+1; ip2 < loc_ind.size(); ++ip2)
1203  Bank_info->edges.insert(edge(ind_points_of_convex(i)[loc_ind[ip1]],
1204  ind_points_of_convex(i)[loc_ind[ip2]]));
1205  Bank_basic_refine_convex(i);
1206  }
1207 
1208  size_type mesh::Bank_test_and_refine_convex(size_type i,
1209  dal::bit_vector &b, bool ref) {
1210  if (Bank_info->is_green_simplex[i]) {
1211  size_type igs = Bank_info->num_green_simplex[i];
1212  green_simplex &gs = Bank_info->green_simplices[igs];
1213 
1214  size_type icc = add_convex_by_points(gs.pgt, gs.cv.points().begin());
1215  handle_region_refinement(icc, gs.sub_simplices, false);
1216  for (size_type ic = 0; ic < gs.sub_simplices.size(); ++ic) {
1217  sup_convex(gs.sub_simplices[ic], true);
1218  b.sup(gs.sub_simplices[ic]);
1219  }
1220  if (!ref)
1221  for (size_type ip = 0; ip < gs.ipt_loc.size(); ++ip)
1222  for (size_type jp = ip+1; jp < gs.ipt_loc.size(); ++jp)
1223  Bank_info->edges.insert
1224  (edge(ind_points_of_convex(icc)[gs.ipt_loc[ip]],
1225  ind_points_of_convex(icc)[gs.ipt_loc[jp]]));
1226  Bank_sup_convex_from_green(i);
1227  if (ref) { Bank_refine_normal_convex(icc); return size_type(-1); }
1228  else return icc;
1229  }
1230  else if (ref) Bank_refine_normal_convex(i);
1231 
1232  return size_type(-1);
1233  }
1234 
1235  struct mesh_cache_for_Bank_build_green_simplexes : public mesh {};
1236 
1237  void mesh::Bank_build_green_simplexes(size_type ic,
1238  std::vector<size_type> &ipt) {
1239  GMM_ASSERT1(convex_index().is_in(ic), "Internal error");
1240  size_type igs = Bank_info->green_simplices.add(green_simplex());
1241  green_simplex &gs(Bank_info->green_simplices[igs]);
1242  std::vector<base_node> pt_tab(nb_points_of_convex(ic));
1243  ref_mesh_pt_ct ptab = points_of_convex(ic);
1244  pt_tab.assign(ptab.begin(), ptab.end());
1245  gs.cv = bgeot::convex<base_node>(structure_of_convex(ic), pt_tab);
1246 
1247  bgeot::pgeometric_trans pgt = gs.pgt = trans_of_convex(ic);
1248 
1249  size_type d = ipt.size() - 1, n = structure_of_convex(ic)->dim();
1250  static size_type d0 = 0;
1251  static bgeot::pstored_point_tab pspt1 = 0;
1252  mesh &mesh1
1254  if (d0 != d) {
1255  d0 = d;
1256  Bank_build_first_mesh(mesh1, d);
1257  pspt1 = bgeot::store_point_tab(mesh1.points());
1258  }
1259 
1260  const std::vector<size_type> &loc_ind = pgt->vertices();
1261  const bgeot::mesh_structure::ind_cv_ct &ct = ind_points_of_convex(ic);
1262 
1263  gs.ipt_loc.resize(ipt.size());
1264  std::vector<size_type> ipt_other;
1265  size_type nb_found = 0;
1266  for (size_type ip = 0; ip < loc_ind.size(); ++ip) {
1267  bool found = false;
1268  for (size_type i = 0; i < ipt.size(); ++i)
1269  if (ct[loc_ind[ip]] == ipt[i])
1270  { gs.ipt_loc[i] = ip; found = true; ++nb_found; break; }
1271  if (!found) ipt_other.push_back(ip);
1272  }
1273  assert(nb_found == ipt.size());
1274 
1275  mesh mesh2;
1276  for (size_type ip = 0; ip < loc_ind.size(); ++ip)
1277  mesh2.add_point(pgt->geometric_nodes()[loc_ind[ip]]);
1278  size_type ic1 = mesh2.add_simplex(dim_type(d), gs.ipt_loc.begin());
1279  bgeot::pgeometric_trans pgt1 = mesh2.trans_of_convex(ic1);
1280  for (size_type i = 0; i < ipt.size(); ++i)
1281  gs.ipt_loc[i] = loc_ind[gs.ipt_loc[i]];
1282 
1283  bgeot::pgeotrans_precomp pgp = bgeot::geotrans_precomp(pgt1, pspt1, 0);
1284 
1285  std::vector<size_type> ipt1(pspt1->size());
1286  base_node pt(dim());
1287  for (size_type i = 0; i < pspt1->size(); ++i) {
1288  pgp->transform(mesh2.points_of_convex(ic1), i, pt);
1289  ipt1[i] = mesh2.add_point(pt);
1290  }
1291  mesh2.sup_convex(ic1);
1292 
1293  std::vector<size_type> ipt2(n+1);
1294  for (size_type i = 0; i < mesh1.nb_convex(); ++i) {
1295  for (size_type j = 0; j <= d; ++j)
1296  ipt2[j] = ipt1[mesh1.ind_points_of_convex(i)[j]];
1297  for (size_type j = d+1; j <= n; ++j)
1298  ipt2[j] = ipt_other[j-d-1];
1299  mesh2.add_simplex(dim_type(n), ipt2.begin());
1300  }
1301 
1302  mesh mesh3;
1303  ipt1.resize(pgt->nb_points());
1304  for (dal::bv_visitor i(mesh2.convex_index()); !i.finished(); ++i) {
1305  bgeot::pgeometric_trans pgt2 = mesh2.trans_of_convex(i);
1306  for (size_type ip = 0; ip < pgt->nb_points(); ++ip)
1307  ipt1[ip] =
1308  mesh3.add_point(pgt2->transform(pgt->geometric_nodes()[ip],
1309  mesh2.points_of_convex(i)));
1310  mesh3.add_convex(pgt, ipt1.begin());
1311  }
1312 
1313 
1314  bgeot::pstored_point_tab pspt3 = bgeot::store_point_tab(mesh3.points());
1315  pgp = bgeot::geotrans_precomp(pgt, pspt3, 0);
1316 
1317  ipt1.resize(pspt3->size());
1318  for (size_type ip = 0; ip < pspt3->size(); ++ip) {
1319  pgp->transform(points_of_convex(ic), ip, pt);
1320  ipt1[ip] = add_point(pt);
1321  }
1322  // dal::del_stored_object(pspt3);
1323 
1324  ipt2.resize(pgt->nb_points());
1325  for (size_type icc = 0; icc < mesh3.nb_convex(); ++icc) {
1326  for (size_type j = 0; j < pgt->nb_points(); ++j)
1327  ipt2[j] = ipt1[mesh3.ind_points_of_convex(icc)[j]];
1328  size_type i = add_convex(pgt, ipt2.begin());
1329  gs.sub_simplices.push_back(i);
1330  Bank_info->is_green_simplex.add(i);
1331  Bank_info->num_green_simplex[i] = igs;
1332  }
1333 
1334  for (size_type ip1 = 0; ip1 < ipt.size(); ++ip1)
1335  for (size_type ip2 = ip1+1; ip2 < ipt.size(); ++ip2)
1336  Bank_info->edges.insert(edge(ipt[ip1], ipt[ip2]));
1337 
1338  handle_region_refinement(ic, gs.sub_simplices, true);
1339  sup_convex(ic, true);
1340  }
1341 
1342  void mesh::Bank_refine(dal::bit_vector b) {
1343  if (!(Bank_info.get())) Bank_info = std::make_unique<Bank_info_struct>();
1344 
1345  b &= convex_index();
1346  if (b.card() == 0) return;
1347 
1348  Bank_info->edges.clear();
1349  while (b.card() > 0)
1350  Bank_test_and_refine_convex(b.take_first(), b);
1351 
1352  std::vector<size_type> ipt;
1353  edge_set marked_convexes;
1354  while (Bank_info->edges.size()) {
1355  marked_convexes.clear();
1356  b = convex_index();
1357  edge_set::const_iterator it = Bank_info->edges.begin();
1358  edge_set::const_iterator ite = Bank_info->edges.end(), it2=it;
1359  assert(!Bank_info->edges.empty());
1360  for (; it != ite; it = it2) {
1361  if (it2 != ite) ++it2;
1362  Bank_convex_with_edge(it->i1, it->i2, ipt);
1363  if (ipt.size() == 0) ; // Bank_info->edges.erase(it);
1364  else for (size_type ic = 0; ic < ipt.size(); ++ic)
1365  marked_convexes.insert(edge(ipt[ic], it->i1, it->i2));
1366  }
1367 
1368  it = marked_convexes.begin(); ite = marked_convexes.end();
1369  if (it == ite) break;
1370 
1371  while (it != ite) {
1372  size_type ic = it->i0;
1373  ipt.resize(0);
1374  while (it != ite && it->i0 == ic) {
1375  bool found1 = false, found2 = false;
1376  for (size_type j = 0; j < ipt.size(); ++j) {
1377  if (ipt[j] == it->i1) found1 = true;
1378  if (ipt[j] == it->i2) found2 = true;
1379  }
1380  if (!found1) ipt.push_back(it->i1);
1381  if (!found2) ipt.push_back(it->i2);
1382  ++it;
1383  }
1384  if (b.is_in(ic)) {
1385  if (ipt.size() > structure_of_convex(ic)->dim())
1386  Bank_test_and_refine_convex(ic, b);
1387  else if (Bank_info->is_green_simplex[ic]) {
1388  size_type icc = Bank_test_and_refine_convex(ic, b, false);
1389  if (!Bank_is_convex_having_points(icc, ipt)) {
1390  Bank_test_and_refine_convex(icc, b);
1391  }
1392  }
1393  else Bank_build_green_simplexes(ic, ipt);
1394  }
1395  }
1396  }
1397  Bank_info->edges.clear();
1398  }
1399 
1400  struct dummy_mesh_ {
1401  mesh m;
1402  dummy_mesh_() : m() {}
1403  };
1404 
1405  const mesh &dummy_mesh()
1407 
1408 } /* end of namespace getfem. */
Provides mesh of torus.
the geotrans_interpolation_context structure is passed as the argument of geometric transformation in...
void set_ii(size_type ii__)
change the current point (assuming a geotrans_precomp_ is used)
scalar_type J() const
get the Jacobian of the geometric trans (taken at point xref() )
does the inversion of the geometric transformation for a given convex
bool invert(const base_node &n, base_node &n_ref, scalar_type IN_EPS=1e-12, bool project_into_element=false)
given the node on the real element, returns the node on the reference element (even if it is outside ...
Mesh structure definition.
short_type nb_points_of_convex(size_type ic) const
Return the number of points of convex ic.
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
size_type neighbor_of_convex(size_type ic, short_type f) const
Return a neighbor convex of a given convex face.
ind_pt_face_ct ind_points_of_face_of_convex(size_type ic, short_type f) const
Return a container of the (global) point number for face f or convex ic.
size_type nb_convex() const
The total number of convexes in the mesh.
void neighbors_of_convex(size_type ic, short_type f, ind_set &s) const
Return in s a list of neighbors of a given convex face.
void swap_convex(size_type cv1, size_type cv2)
Exchange two convex IDs.
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
void optimize_structure()
Reorder the convex IDs and point IDs, such that there is no hole in their numbering.
const ind_set & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
bool is_point_valid(size_type i) const
Return true if the point i is used by at least one convex.
size_type nb_allocated_convex() const
The number of convex indexes from 0 to the index of the last convex.
void sup_convex(size_type ic)
Remove the convex ic.
size_type add_node(const base_node &pt, const scalar_type radius=0, bool remove_duplicated_nodes=true)
Add a point to the array or use an existing point, located within a distance smaller than radius.
Dynamic Array.
Definition: dal_basic.h:195
iterator begin(void)
Iterator on the first element.
Definition: dal_basic.h:230
size_type size(void) const
Number of allocated elements.
Definition: dal_basic.h:224
void clear(void)
Clear and desallocate all the elements.
Definition: dal_basic.h:303
static T & instance()
Instance from the current thread.
"iterator" class for regions.
structure used to hold a set of convexes and/or convex faces.
const mesh_region & from_mesh(const mesh &m) const
For regions which have been built with just a number 'id', from_mesh(m) sets the current region to 'm...
static mesh_region all_convexes()
provide a default value for the mesh_region parameters of assembly procedures etc.
static mesh_region intersection(const mesh_region &a, const mesh_region &b)
return the intersection of two mesh regions
bool is_only_convexes() const
Return true if the region do not contain any convex face.
const dal::bit_vector & index() const
Index of the region convexes, or the convexes from the partition on the current thread.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:98
mesh(const std::string name="")
Constructor.
Definition: getfem_mesh.cc:132
virtual scalar_type convex_radius_estimate(size_type ic) const
Return an estimate of the convex largest dimension.
Definition: getfem_mesh.cc:460
void sup_convex_from_regions(size_type cv)
Remove all references to a convex from all regions stored in the mesh.
Definition: getfem_mesh.cc:41
size_type add_tetrahedron_by_points(const base_node &p1, const base_node &p2, const base_node &p3, const base_node &p4)
Add a tetrahedron to the mesh, given the coordinates of its vertices.
Definition: getfem_mesh.cc:310
void sup_convex(size_type ic, bool sup_points=false)
Delete the convex of index ic from the mesh.
Definition: getfem_mesh.cc:357
const dal::bit_vector & points_index() const
Return the points index.
Definition: getfem_mesh.h:195
size_type nb_points() const
Give the number of geometrical nodes in the mesh.
Definition: getfem_mesh.h:193
void transformation(const base_matrix &)
apply the given matrix transformation to each mesh node.
Definition: getfem_mesh.cc:254
scalar_type convex_quality_estimate(size_type ic) const
Return an estimate of the convex quality (0 <= Q <= 1).
Definition: getfem_mesh.cc:449
size_type add_triangle(size_type a, size_type b, size_type c)
Add a triangle to the mesh, given the point id of its vertices.
Definition: getfem_mesh.cc:287
base_matrix local_basis_of_face_of_convex(size_type ic, short_type f, const base_node &pt) const
Return a local basis for the convex face.
Definition: getfem_mesh.cc:420
scalar_type convex_area_estimate(size_type ic, size_type degree=2) const
Return an estimate of the convex area.
Definition: getfem_mesh.cc:441
void write_to_file(const std::string &name) const
Write the mesh to a file.
Definition: getfem_mesh.cc:708
void bounding_box(base_node &Pmin, base_node &Pmax) const
Return the bounding box [Pmin - Pmax] of the mesh.
Definition: getfem_mesh.cc:260
void swap_convex(size_type i, size_type j)
Swap the indexes of the convex of indexes i and j in the whole structure.
Definition: getfem_mesh.cc:372
void Bank_refine(dal::bit_vector)
Use the Bank strategy to refine some convexes.
size_type add_pyramid(size_type a, size_type b, size_type c, size_type d, size_type e)
Add a pyramid to the mesh, given the point id of its vertices.
Definition: getfem_mesh.cc:303
size_type add_segment(size_type a, size_type b)
Add a segment to the mesh, given the point id of its vertices.
Definition: getfem_mesh.cc:282
base_small_vector normal_of_face_of_convex(size_type ic, short_type f, const base_node &pt) const
Return the normal of the given convex face, evaluated at the point pt.
Definition: getfem_mesh.cc:383
scalar_type minimal_convex_radius_estimate() const
Return an estimate of the convex smallest dimension.
Definition: getfem_mesh.cc:466
const mesh_region region(size_type id) const
Return the region of index 'id'.
Definition: getfem_mesh.h:420
size_type add_convex(bgeot::pgeometric_trans pgt, ITER ipts)
Add a convex to the mesh.
Definition: getfem_mesh.h:225
void read_from_file(const std::string &name)
Load the mesh from a file.
Definition: getfem_mesh.cc:654
size_type add_tetrahedron(size_type a, size_type b, size_type c, size_type d)
Add a tetrahedron to the mesh, given the point id of its vertices.
Definition: getfem_mesh.cc:297
void sup_point(size_type i)
Delete the point of index i from the mesh if it is not linked to a convex.
Definition: getfem_mesh.h:199
void swap_points(size_type i, size_type j)
Swap the indexes of points of index i and j in the whole structure.
Definition: getfem_mesh.h:201
size_type add_triangle_by_points(const base_node &p1, const base_node &p2, const base_node &p3)
Add a triangle to the mesh, given the coordinates of its vertices.
Definition: getfem_mesh.cc:294
void copy_from(const mesh &m)
Clone a mesh.
Definition: getfem_mesh.cc:486
size_type add_simplex(dim_type di, ITER ipts)
Add a simplex to the mesh, given its dimension and point numbers.
Definition: getfem_mesh.h:251
scalar_type maximal_convex_radius_estimate() const
Return an estimate of the convex largest dimension.
Definition: getfem_mesh.cc:475
void merge_convexes_from_mesh(const mesh &m, size_type rg=size_type(-1), scalar_type tol=scalar_type(0))
Merge all convexes from a another mesh, possibly restricted to a mesh region.
Definition: getfem_mesh.cc:316
void clear()
Erase the mesh.
Definition: getfem_mesh.cc:272
void translation(const base_small_vector &)
Apply the given translation to each mesh node.
Definition: getfem_mesh.cc:251
indexed array reference (given a container X, and a set of indexes I, this class provides a pseudo-co...
Definition: gmm_ref.h:303
A simple singleton implementation.
Integration methods (exact and approximated) on convexes.
Define a getfem::getfem_mesh object.
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
computation of the condition number of dense matrices.
void lu_inverse(const DenseMatrixLU &LU, const Pvector &pvector, const DenseMatrix &AInv_)
Given an LU factored matrix, build the inverse of the matrix.
Definition: gmm_dense_lu.h:211
scalar_type APIDECL convex_radius_estimate(bgeot::pgeometric_trans pgt, const base_matrix &pts)
rough estimate of the radius of the convex using the largest eigenvalue of the jacobian of the geomet...
Definition: getfem_mesh.cc:797
scalar_type APIDECL convex_quality_estimate(bgeot::pgeometric_trans pgt, const base_matrix &pts)
rough estimate of the maximum value of the condition number of the jacobian of the geometric transfor...
Definition: getfem_mesh.cc:771
mesh_region APIDECL select_faces_of_normal(const mesh &m, const mesh_region &mr, const base_small_vector &V, scalar_type angle)
Select in the region mr the faces of the mesh m with their unit outward vector having a maximal angle...
Definition: getfem_mesh.cc:922
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.
Definition: getfem_mesh.h:557
mesh_region APIDECL select_faces_in_ball(const mesh &m, const mesh_region &mr, const base_node &center, scalar_type radius)
Select in the region mr the faces of the mesh m lying entirely in the ball delimated by pt1 and radiu...
Definition: getfem_mesh.cc:959
scalar_type APIDECL convex_area_estimate(bgeot::pgeometric_trans pgt, const base_matrix &pts, pintegration_method pim)
rough estimate of the convex area.
Definition: getfem_mesh.cc:744
mesh_region APIDECL inner_faces_of_mesh(const mesh &m, const mesh_region &mr=mesh_region::all_convexes())
Select all the faces sharing at least two element of the given mesh region.
Definition: getfem_mesh.cc:876
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.
Definition: getfem_mesh.cc:821
mesh_region APIDECL select_faces_in_box(const mesh &m, const mesh_region &mr, const base_node &pt1, const base_node &pt2)
Select in the region mr the faces of the mesh m lying entirely in the box delimated by pt1 and pt2.
Definition: getfem_mesh.cc:936
void APIDECL extrude(const mesh &in, mesh &out, size_type nb_layers, short_type degree=short_type(1))
build a N+1 dimensions mesh from a N-dimensions mesh by extrusion.
mesh_region APIDECL all_faces_of_mesh(const mesh &m, const mesh_region &mr=mesh_region::all_convexes())
Select all the faces of the given mesh region.
Definition: getfem_mesh.cc:857
Basic Geometric Tools.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:72
std::string name_of_geometric_trans(pgeometric_trans p)
Get the string name of a geometric transformation.
pconvex_ref equilateral_simplex_of_reference(dim_type nc)
equilateral simplex (degree 1).
pconvex_ref simplex_of_reference(dim_type nc, short_type K)
returns a simplex of reference of dimension nc and degree k
int get_token(std::istream &ist, std::string &st, bool ignore_cr, bool to_up, bool read_un_pm, int *linenb)
Very simple lexical analysis of general interest for reading small languages with a "MATLAB like" syn...
Definition: bgeot_ftool.cc:49
void cuthill_mckee_on_convexes(const bgeot::mesh_structure &ms, std::vector< size_type > &cmk)
Return the cuthill_mc_kee ordering on the convexes.
base_matrix compute_local_basis(const geotrans_interpolation_context &c, size_type face)
return the local basis (i.e.
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
base_small_vector compute_normal(const geotrans_interpolation_context &c, size_type face)
norm of returned vector is the ratio between the face surface on the real element and the face surfac...
pgeometric_trans geometric_trans_descriptor(std::string name)
Get the geometric transformation from its string name.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
pconvex_structure basic_structure(pconvex_structure cv)
Original structure (if concerned)
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
GEneric Tool for Finite Element Methods.
pintegration_method classical_approx_im(bgeot::pgeometric_trans pgt, dim_type degree)
try to find an approximate integration method for the geometric transformation pgt which is able to i...
An adaptor that adapts a two dimensional geometric_trans to include radial dimension.
Definition: bgeot_torus.h:47
iterator over a gmm::tab_ref_index_ref<ITER,ITER_INDEX>
Definition: gmm_ref.h:236