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