GetFEM  5.5
bgeot_mesh_structure.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 
22 
24 
25 namespace bgeot {
26 
27 
28  dal::bit_vector mesh_structure::convex_index(dim_type n) const {
29  dal::bit_vector res = convex_tab.index();
30  for (dal::bv_visitor cv(convex_tab.index()); !cv.finished(); ++cv)
31  if (structure_of_convex(cv)->dim() != n) res.sup(cv);
32  return res;
33  }
34 
36  size_type ip) const {
37  mesh_convex_structure::ind_pt_ct::const_iterator it;
38  size_type ind = 0;
39  for (it=convex_tab[ic].pts.begin();
40  it != convex_tab[ic].pts.end() && (*it) != ip; ++it) ++ind;
41  GMM_ASSERT1(it != convex_tab[ic].pts.end(),
42  "This point does not exist on this convex.");
43  return ind;
44  }
45 
47  if (i == j) return;
48  std::vector<size_type> doubles;
49 
50  for (size_type k = 0; k < points_tab[i].size(); ++k) {
51  size_type cv = points_tab[i][k];
52  for (size_type l = 0; l < convex_tab[cv].pts.size(); ++l) {
53  size_type &ind = convex_tab[cv].pts[l];
54  if (ind == i) ind = j;
55  else if (ind == j) { ind = i; doubles.push_back(cv); }
56  }
57  }
58  for (size_type k = 0; k < points_tab[j].size(); ++k) {
59  size_type cv = points_tab[j][k];
60  if (std::find(doubles.begin(), doubles.end(), cv) == doubles.end()) {
61  for (size_type l = 0; l < convex_tab[cv].pts.size(); ++l)
62  if (convex_tab[cv].pts[l] == j) convex_tab[cv].pts[l] = i;
63  }
64  }
65  points_tab.swap(i,j);
66  }
67 
69  if (i == j) return;
70  std::vector<size_type> doubles;
71 
72  if (is_convex_valid(i))
73  for (size_type k = 0; k < convex_tab[i].pts.size(); ++k) {
74  size_type ip = convex_tab[i].pts[k];
75  for (size_type l = 0; l < points_tab[ip].size(); ++l) {
76  size_type &ind = points_tab[ip][l];
77  if (ind == i) ind = j;
78  else if (ind == j) { ind = i; doubles.push_back(ip); }
79  }
80  }
81  if (is_convex_valid(j))
82  for (size_type k = 0; k < convex_tab[j].pts.size(); ++k) {
83  size_type ip = convex_tab[j].pts[k];
84  if (std::find(doubles.begin(), doubles.end(), ip) == doubles.end()) {
85  for (size_type l = 0; l < points_tab[ip].size(); ++l)
86  if (points_tab[ip][l] == j) points_tab[ip][l] = i;
87  }
88  }
89  convex_tab.swap(i,j);
90  }
91 
92  size_type mesh_structure::add_segment(size_type a, size_type b) {
93  static pconvex_structure cs = NULL;
94  if (!cs) cs = simplex_structure(1);
95  size_type t[2]; t[0] = a; t[1] = b;
96  return add_convex(cs, &t[0]);
97  }
98 
100  if (!(is_convex_valid(ic))) return;
101  for (size_type l = 0; l < convex_tab[ic].pts.size(); ++l) {
102  size_type &ind = convex_tab[ic].pts[l];
103  std::vector<size_type>::iterator it1= points_tab[ind].begin(), it2 = it1;
104  std::vector<size_type>::iterator ite= points_tab[ind].end();
105  for (; it2 != ite; ++it2) { *it1 = *it2; if (*it1 != ic) ++it1; }
106  points_tab[ind].pop_back();
107  }
108  convex_tab.sup(ic);
109  }
110 
112  return add_convex( (structure_of_convex(ic)->faces_structure())[f],
113  ind_points_of_face_of_convex(ic, f).begin());
114  }
115 
118  for (short_type iff = 0; iff < ps->nb_faces(); ++iff)
119  add_convex( (ps->faces_structure())[iff],
120  ind_points_of_face_of_convex(ic, iff).begin());
121  }
122 
123  void mesh_structure::to_faces(dim_type n) { // not efficient
124  dal::bit_vector nn = convex_index();
125  for (dal::bv_visitor i(nn); !i.finished(); ++i)
126  if (convex_tab[i].cstruct->dim() == n)
127  { add_faces_of_convex(i); sup_convex(i); }
128  }
129 
130  void mesh_structure::to_edges(void) { // not efficient at all !
131  dim_type dmax = 0;
132  dal::bit_vector nn = convex_index();
133  for (dal::bv_visitor i(nn); !i.finished(); ++i)
134  dmax = std::max(dmax, convex_tab[i].cstruct->dim());
135  for ( ; dmax > 1; --dmax) to_faces(dmax);
136  }
137 
138  size_type mesh_structure::nb_convex_with_edge(size_type i1, size_type i2) {
139  size_type nb = 0;
140  for (size_type k = 0; k < points_tab[i1].size(); ++k) {
141  size_type cv = points_tab[i1][k];
142  for (size_type l = 0; l < convex_tab[cv].pts.size(); ++l)
143  if (convex_tab[cv].pts[l] == i2) { ++nb; break; }
144  }
145  return nb;
146  }
147 
148  void mesh_structure::convex_with_edge(size_type i1, size_type i2,
149  std::vector<size_type> &ipt) const {
150  ipt.resize(0);
151  for (size_type k = 0; k < points_tab[i1].size(); ++k) {
152  size_type cv = points_tab[i1][k];
153  for (size_type l = 0; l < convex_tab[cv].pts.size(); ++l)
154  if (convex_tab[cv].pts[l] == i2) { ipt.push_back(cv); break; }
155  }
156  }
157 
158  void mesh_structure::ind_points_to_point(size_type ip, ind_set &s) const {
159  // not efficient
160  s.resize(0);
161  for (size_type k = 0; k < points_tab[ip].size(); ++k) {
162  size_type cv = points_tab[ip][k];
163  for (size_type l = 0; l < convex_tab[cv].pts.size(); ++l)
164  if (ip != convex_tab[cv].pts[l]) {
165  size_type ind = convex_tab[cv].pts[l];
166  if (std::find(s.begin(), s.end(), ind) != s.end()) s.push_back(ind);
167  }
168  }
169  }
170 
173  short_type iff) const {
174  const mesh_convex_structure *q = &(convex_tab[ic]);
175  std::vector<size_type>::const_iterator r = q->pts.begin();
176  const convex_ind_ct *p = &(q->cstruct->ind_points_of_face(iff));
177  return ind_pt_face_ct(r, p->begin(), p->end());
178  }
179 
180  size_type mesh_structure::memsize(void) const {
181  size_type mems = sizeof(mesh_structure) + points_tab.memsize()
182  + convex_tab.memsize();
183  for (size_type i = 0; i < convex_tab.size(); ++i)
184  mems += convex_tab[i].pts.size() * sizeof(size_type);
185  for (size_type i = 0; i < points_tab.size(); ++i)
186  mems += points_tab[i].size() * sizeof(size_type);
187  return mems;
188  }
189 
191  size_type i, j = nb_convex();
192  for (i = 0; i < j; i++)
193  if (!convex_tab.index_valid(i))
194  swap_convex(i, convex_tab.ind_last());
195 
196  if (points_tab.size())
197  for (i=0, j = (points_tab.end()-points_tab.begin())-1; i < j; ++i, --j){
198  while (i < j && !(points_tab[i].empty())) ++i;
199  while (i < j && points_tab[j].empty()) --j;
200  if (i < j) swap_points(i, j);
201  }
202  }
203 
205  points_tab = dal::dynamic_tas<ind_cv_ct, 8>();
206  convex_tab = dal::dynamic_tas<mesh_convex_structure, 8>();
207 
208  }
209 
210  void mesh_structure::stat(void) {
211  cout << "mesh structure with " << nb_convex() << " valid convex, "
212  << "for a total memory size of " << memsize() << " bytes.\n";
213  }
214 
215 
217  ind_set &s) const {
218  s.resize(0);
220 
221  for (size_type i = 0; i < points_tab[pt[0]].size(); ++i) {
222  size_type icv = points_tab[pt[0]][i];
223  if (icv != ic && is_convex_having_points(icv, short_type(pt.size()),
224  pt.begin())
225  && (convex_tab[ic].cstruct->dim()==convex_tab[icv].cstruct->dim()))
226  s.push_back(icv);
227  }
228  }
229 
230 
232  const std::vector<short_type> &ftab,
233  ind_set &s) const {
234  s.resize(0);
235  std::vector<size_type> ipts;
236 
237  switch (ftab.size()) {
238  case 0:
239  {
240  ind_cv_ct pt = ind_points_of_convex(ic);
241  ipts.resize(pt.size());
242  std::copy(pt.begin(), pt.end(), ipts.begin());
243  }
244  break;
245 
246  case 1:
247  {
249  ipts.resize(pt.size());
250  std::copy(pt.begin(), pt.end(), ipts.begin());
251  }
252  break;
253 
254  default:
255  {
256  const mesh_convex_structure &q = convex_tab[ic];
257  const convex_ind_ct &ind = q.cstruct->ind_common_points_of_faces(ftab);
258  if (ind.size() == 0) return neighbors_of_convex(ic, s);
259  ipts.resize(ind.size());
260  auto it = ind.cbegin();
261  for (size_type &ipt : ipts) ipt = q.pts[*it++];
262  }
263  break;
264  }
265 
266  if (ipts.size() == 0) {
267  return; // Should we return the all the neighbors ?
268  }
269 
270  auto ipt0 = ipts.cbegin();
271  auto ipt1 = ipt0 + 1;
272  short_type nbpts = short_type(ipts.size()-1);
273  for (size_type icv : points_tab[*ipt0]) {
274  if (icv != ic && (nbpts==0 || is_convex_having_points(icv, nbpts, ipt1)))
275  s.push_back(icv);
276  }
277  }
278 
279  void mesh_structure::neighbors_of_convex(size_type ic, ind_set &s) const {
280  s.resize(0);
281  unsigned nbf = nb_faces_of_convex(ic);
282  for (short_type iff = 0; iff < nbf; ++iff) {
284 
285  for (size_type i = 0; i < points_tab[pt[0]].size(); ++i) {
286  size_type icv = points_tab[pt[0]][i];
287  if (icv != ic && is_convex_having_points(icv, short_type(pt.size()),
288  pt.begin())
289  && (convex_tab[ic].cstruct->dim()==convex_tab[icv].cstruct->dim()))
290  if (std::find(s.begin(), s.end(), icv) == s.end())
291  s.push_back(icv);
292  }
293  }
294  }
295 
297  short_type iff) const {
299 
300  for (size_type i = 0; i < points_tab[pt[0]].size(); ++i) {
301  size_type icv = points_tab[pt[0]][i];
302  if (icv != ic && is_convex_having_points(icv, short_type(pt.size()),
303  pt.begin())
304  && (convex_tab[ic].cstruct->dim()==convex_tab[icv].cstruct->dim()))
305  return icv;
306  }
307  return size_type(-1);
308  }
309 
311  size_type neighbor_element = neighbor_of_convex(cv, f);
312  if (neighbor_element == size_type(-1)) return convex_face::invalid_face();
313  auto pcs = structure_of_convex(neighbor_element);
314  auto face_points = ind_points_of_face_of_convex(cv, f);
315  auto nNeighborElementFaces = pcs->nb_faces();
316  for (short_type iff = 0; iff < nNeighborElementFaces; ++iff) {
317  auto nPointsOnFace = pcs->nb_points_of_face(iff);
318  if (is_convex_face_having_points(neighbor_element, iff,
319  nPointsOnFace, face_points.begin()))
320  return {neighbor_element, iff};
321  }
322  GMM_ASSERT2(false, "failed to determine neighboring face");
323  return convex_face::invalid_face();
324  }
325 
327  size_type ip) const {
328  const ind_cv_ct &ct = ind_points_of_convex(ic);
329  ind_cv_ct::const_iterator it = std::find(ct.begin(), ct.end(), ip);
330  return (it != ct.end()) ? (it - ct.begin()): size_type(-1);
331  }
332 
333  /* ********************************************************************* */
334  /* */
335  /* Gives the list of edges of a convex face. */
336  /* */
337  /* ********************************************************************* */
338 
339  void mesh_edge_list_convex(pconvex_structure cvs, std::vector<size_type> points_of_convex,
340  size_type cv_id, edge_list &el, bool merge_convex)
341  { // a tester ... optimisable.
342  dim_type n = cvs->dim();
343  short_type nbp = cvs->nb_points();
344  size_type ncv = merge_convex ? 0 : cv_id;
345 
346  if (nbp == n+1 && cvs == simplex_structure(n)) {
347  for (dim_type k = 0; k < n; ++k)
348  for (dim_type l = dim_type(k+1); l <= n; ++l)
349  el.add(edge_list_elt(points_of_convex[k],
350  points_of_convex[l], ncv));
351  }
352  else if (nbp == (size_type(1) << n)
353  && cvs == parallelepiped_structure(n)) {
354  for (size_type k = 0; k < (size_type(1) << n); ++k)
355  for (dim_type j = 0; j < n; ++j)
356  if ((k & (1 << j)) == 0)
357  el.add(edge_list_elt(points_of_convex[k],
358  points_of_convex[k | (1 << j)], ncv));
359  }
360  else if (nbp == 2 * n && cvs == prism_P1_structure(n)) {
361  for (dim_type k = 0; k < n - 1; ++k)
362  for (dim_type l = dim_type(k+1); l < n; ++l) {
363  el.add(edge_list_elt(points_of_convex[k],
364  points_of_convex[l], ncv));
365  el.add(edge_list_elt(points_of_convex[k+n],
366  points_of_convex[l+n], ncv));
367  }
368  for (dim_type k = 0; k < n; ++k)
369  el.add(edge_list_elt(points_of_convex[k],
370  points_of_convex[k+n], ncv));
371  }
372  else {
375  size_type ncs = 1;
376  cvstab[0] = cvs;
377  indpttab[0].resize(cvstab[0]->nb_points());
378  std::copy(points_of_convex.begin(),
379  points_of_convex.end(), indpttab[0].begin());
380 
381  /* pseudo recursive decomposition of the initial convex into
382  face of face of ... of face of convex , cvstab and indpttab
383  being the "stack" of convexes to treat
384  */
385  while (ncs != 0) {
386  ncs--;
387  cvs = cvstab[ncs];
388  std::vector< size_type > pts = indpttab[ncs];
389  if (cvs->dim() == 1) { // il faudrait étendre aux autres cas classiques.
390 
391  for (size_type j = 1; j < cvs->nb_points(); ++j) {
392  //cerr << "ncs=" << ncs << "j=" << j << ", ajout de " << (indpttab[ncs])[j-1] << "," << (indpttab[ncs])[j] << endl;
393  el.add(edge_list_elt((indpttab[ncs])[j-1],(indpttab[ncs])[j],ncv));
394  }
395  }
396  else {
397  short_type nf = cvs->nb_faces();
398  //cerr << "ncs = " << ncs << ",cvs->dim=" << int(cvs->dim()) << ", nb_faces=" << nf << endl;
399  for (short_type f = 0; f < nf; ++f) {
400  cvstab[ncs+f] = (cvs->faces_structure())[f];
401  indpttab[ncs+f].resize(cvs->nb_points_of_face(f));
402  /*
403  cerr << " -> f=" << f << ", cvs->nb_points_of_face(f)=" <<
404  cvs->nb_points_of_face(f) << "=[";
405  for (size_type k = 0; k < cvs->nb_points_of_face(f); ++k)
406  cerr << (std::string(k==0?"":","))
407  << int(cvs->ind_points_of_face(f)[k]) << "{" << pts[cvs->ind_points_of_face(f)[k]] << "}";
408  cerr << "]" << endl;
409  */
410  for (size_type k = 0; k < cvs->nb_points_of_face(f); ++k)
411  (indpttab[ncs+f])[k] = pts[cvs->ind_points_of_face(f)[k]];
412  }
413  // cvstab[ncs] = cvstab[ncs + nf - 1];
414  //indpttab[ncs] = indpttab[ncs + nf - 1];
415  ncs += nf;
416  //cerr << "on empile les " << nf << " faces, -> ncs=" << ncs << endl;
417  }
418  }
419  }
420  }
421 
422 
423  void mesh_edge_list(const mesh_structure &m, edge_list &el,
424  bool merge_convex) {
425  std::vector<size_type> p;
426  for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
427  p.resize(m.nb_points_of_convex(cv));
428  std::copy(m.ind_points_of_convex(cv).begin(),
429  m.ind_points_of_convex(cv).end(), p.begin());
430  mesh_edge_list_convex(m.structure_of_convex(cv), p, cv,
431  el, merge_convex);
432  }
433  }
434 
435 
436  // static double enumerate_dof_time = 0;
438  std::vector<size_type> &cmk) {
439  const dal::bit_vector &cvlst = ms.convex_index();
440  cmk.reserve(cvlst.card()); cmk.resize(0);
441  if (ms.convex_index().card() == 0) return;
442  std::deque<int> pile;
443  std::vector<size_type> tab, connectivity(cvlst.last_true()+1),
444  temp(cvlst.last_true()+1);
445 
446  size_type cv = cvlst.first_true();
447 
448  std::fill(connectivity.begin(), connectivity.end(), size_type(-1));
449  // double t = dal::uclock_sec();
450 
451  /* count neighbors for each convex */
452  for (dal::bv_visitor j(cvlst); !j.finished(); ++j) {
453  const mesh_structure::ind_cv_ct &ct = ms.ind_points_of_convex(j);
454  mesh_structure::ind_cv_ct::const_iterator itp = ct.begin(),
455  itpe = ct.end();
456  size_type nei = 0;
457 
458  for (; itp != itpe; ++itp) {
459  size_type ip = *itp;
460  mesh_structure::ind_cv_ct::const_iterator
461  it = ms.convex_to_point(ip).begin(),
462  ite = ms.convex_to_point(ip).end();
463  for ( ; it != ite; ++it)
464  if (temp[*it] != j+1) { temp[*it] = j+1; nei++; }
465  }
466  connectivity[j] = nei-1;
467  if (nei < connectivity[cv]) cv = j;
468  }
469 
470  /* do the cuthill mckee */
471  while (cv != size_type(-1)) {
472  connectivity[cv] = size_type(-1);
473  cmk.push_back(cv);
474  size_type nbp = ms.nb_points_of_convex(cv);
475 
476  for (size_type i = 0; i < nbp; i++) {
477  size_type ip = ms.ind_points_of_convex(cv)[i];
478  mesh_structure::ind_cv_ct::const_iterator
479  it = ms.convex_to_point(ip).begin(),
480  ite = ms.convex_to_point(ip).end();
481  for ( ; it != ite; ++it)
482  if (connectivity[*it] != size_type(-1)) {
483  connectivity[*it] = size_type(-1);
484  pile.push_front(int(*it));
485  }
486  }
487 
488  if (pile.empty()) {
489  cv = std::min_element(connectivity.begin(), connectivity.end()) - connectivity.begin();
490  if (connectivity[cv] == size_type(-1)) break;
491  }
492  else { cv = pile.back(); pile.pop_back(); }
493  }
494 
495  // enumerate_dof_time += dal::uclock_sec() - t;
496  // cerr << "cuthill_mckee_on_convexes: " << enumerate_dof_time << " sec\n";
497  }
498 
499 } /* end of namespace bgeot. */
Mesh structure definition.
Mesh structure definition.
bool is_convex_valid(size_type i)
Return true if i is in convex_index()
size_type add_face_of_convex(size_type ic, short_type f)
Insert a new convex corresponding to face f of the convex ic.
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.
short_type nb_faces_of_convex(size_type ic) const
Return the number of faces of convex ic.
bool is_convex_face_having_points(size_type ic, short_type face_num, short_type nb, ITER pit) const
Return true if the face of the convex contains the given list of points.
void clear()
erase the mesh
bool is_convex_having_points(size_type ic, short_type nb, ITER pit) const
Return true if the convex contains the listed points.
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.
size_type local_ind_of_convex_point(size_type ic, size_type ip) const
Return the "local" index for point ip of 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.
const ind_cv_ct & convex_to_point(size_type ip) const
Return a container of the convexes attached to point ip.
size_type add_convex(pconvex_structure cs, ITER ipts, bool *present=0)
Insert a new convex in the mesh_structure.
void add_faces_of_convex(size_type ic)
Insert new convexes corresponding to the faces of the convex ic.
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
void ind_points_to_point(size_type, ind_set &) const
Return a container of the points attached (via an edge) to point ip.
size_type ind_in_convex_of_point(size_type ic, size_type ip) const
Find the local index of the point of global index ip with respect to the convex cv.
void optimize_structure()
Reorder the convex IDs and point IDs, such that there is no hole in their numbering.
void to_faces(dim_type n)
build a new mesh, such that its convexes are the faces of the convexes of the previous one
convex_face adjacent_face(size_type ic, short_type f) const
Return a face of the neighbouring element that is adjacent to the given face.
const ind_set & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
void sup_convex(size_type ic)
Remove the convex ic.
void swap_points(size_type i, size_type j)
Exchange two point IDs.
void to_edges()
build a new mesh, such that its convexes are the edges of the convexes of the previous one
Dynamic Array.
Definition: dal_basic.h:195
size_type memsize(void) const
Gives the total memory occupied by the array.
Definition: dal_basic.h:278
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
iterator end(void)
Iterator on the last + 1 element.
Definition: dal_basic.h:234
indexed array reference (given a container X, and a set of indexes I, this class provides a pseudo-co...
Definition: gmm_ref.h:303
Basic Geometric Tools.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:72
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
pconvex_structure parallelepiped_structure(dim_type nc, dim_type k)
Give a pointer on the structures of a parallelepiped of dimension d.
void cuthill_mckee_on_convexes(const bgeot::mesh_structure &ms, std::vector< size_type > &cmk)
Return the cuthill_mc_kee ordering on the convexes.
pconvex_structure prism_P1_structure(dim_type nc)
Give a pointer on the structures of a prism of dimension d.
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48