GetFEM  5.5
getfem_regular_meshes.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 
23 
24 namespace getfem
25 {
26  void parallelepiped_regular_simplex_mesh_
27  (mesh &me, dim_type N, const base_node &org,
28  const base_small_vector *ivect, const size_type *iref) {
30  pararef = *(bgeot::parallelepiped_of_reference(N));
31 
32  if (N >= 5) GMM_WARNING1("CAUTION : Simplexification in dimension >= 5 "
33  "has not been tested and the resulting mesh "
34  "should be not conformal");
35 
36  const bgeot::mesh_structure &sl
37  = *(bgeot::parallelepiped_of_reference(N)->simplexified_convex());
38 
39  base_node a = org;
40  size_type i, nbpt = pararef.nb_points();
41 
42  for (i = 0; i < nbpt; ++i) {
43  gmm::clear(a);
44  for (dim_type n = 0; n < N; ++n)
45  gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
46  pararef.points()[i] = a;
47  }
48 
49  // bgeot::simplexify(cvt, sl, pararef.points(), N, me.eps());
50 
51  size_type nbs = sl.nb_convex();
52  std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
53  size_type total = 0;
54  std::fill(tab.begin(), tab.end(), 0);
55  while (tab[N-1] != iref[N-1]) {
56  for (a = org, i = 0; i < N; i++)
57  gmm::add(gmm::scaled(ivect[i],scalar_type(tab[i])),a);
58  //a.addmul(scalar_type(tab[i]), ivect[i]);
59 
60  for (i = 0; i < nbpt; i++)
61  tab3[i] = me.add_point(a + pararef.points()[i]);
62 
63  for (i = 0; i < nbs; i++) {
64  const mesh::ind_cv_ct &tab2 = sl.ind_points_of_convex(i);
65  for (dim_type l = 0; l <= N; l++)
66  // tab1[l] = tab3[tab2[l]];
67  tab1[l] = tab3[(tab2[l]
68  + (((total & 1) && N != 3) ? (nbpt/2) : 0)) % nbpt];
69  me.add_simplex(N, tab1.begin());
70  }
71 
72  for (dim_type l = 0; l < N; l++) {
73  tab[l]++; total++;
74  if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
75  else break;
76  }
77  }
78  }
79 
80 
81  void parallelepiped_regular_prism_mesh_
82  (mesh &me, dim_type N, const base_node &org,
83  const base_small_vector *ivect, const size_type *iref) {
84  mesh aux;
85  parallelepiped_regular_simplex_mesh_(aux, dim_type(N-1), org, ivect, iref);
86  std::vector<base_node> ptab(2 * N);
87 
88  for (dal::bv_visitor cv(aux.convex_index()); !cv.finished(); ++cv) {
89  std::copy(aux.points_of_convex(cv).begin(),
90  aux.points_of_convex(cv).end(), ptab.begin());
91 
92  for (size_type k = 0; k < iref[N-1]; ++k) {
93 
94  for (dim_type j = 0; j < N; ++j) ptab[j+N] = ptab[j] + ivect[N-1];
95  me.add_prism_by_points(N, ptab.begin());
96 
97  std::copy(ptab.begin()+N, ptab.end(), ptab.begin());
98  }
99  }
100  }
101 
102  void parallelepiped_regular_mesh_
103  (mesh &me, dim_type N, const base_node &org,
104  const base_small_vector *ivect, const size_type *iref, bool linear_gt) {
106  pararef = *(bgeot::parallelepiped_of_reference(N));
107  base_node a = org;
108  size_type i, nbpt = pararef.nb_points();
109 
110  for (i = 0; i < nbpt; ++i) {
111  gmm::clear(a);
112  for (dim_type n = 0; n < N; ++n)
113  gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
114  //a.addmul(pararef.points()[i][n], ivect[n]);
115  pararef.points()[i] = a;
116  }
117 
118  std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
119  size_type total = 0;
120  std::fill(tab.begin(), tab.end(), 0);
121  while (tab[N-1] != iref[N-1]) {
122  for (a = org, i = 0; i < N; i++)
123  gmm::add(gmm::scaled(ivect[i], scalar_type(tab[i])),a);
124  //a.addmul(scalar_type(tab[i]), ivect[i]);
125 
126  for (i = 0; i < nbpt; i++)
127  tab3[i] = me.add_point(a + pararef.points()[i]);
128  me.add_convex(linear_gt ?
129  bgeot::parallelepiped_linear_geotrans(N) :
130  bgeot::parallelepiped_geotrans(N, 1), tab3.begin());
131 
132  for (dim_type l = 0; l < N; l++) {
133  tab[l]++; total++;
134  if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
135  else break;
136  }
137  }
138  }
139 
140  void parallelepiped_regular_pyramid_mesh_
141  (mesh &me, const base_node &org,
142  const base_small_vector *ivect, const size_type *iref) {
143  dim_type N = 3;
145  pararef = *(bgeot::parallelepiped_of_reference(N));
146  base_node a = org, barycenter(N);
147  size_type i, nbpt = pararef.nb_points();
148 
149  for (i = 0; i < nbpt; ++i) {
150  gmm::clear(a);
151  for (dim_type n = 0; n < N; ++n)
152  gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
153  //a.addmul(pararef.points()[i][n], ivect[n]);
154  pararef.points()[i] = a;
155  barycenter += a;
156  }
157  barycenter /= double(nbpt);
158 
159  std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
160  size_type total = 0;
161  std::fill(tab.begin(), tab.end(), 0);
162  while (tab[N-1] != iref[N-1]) {
163  for (a = org, i = 0; i < N; i++)
164  gmm::add(gmm::scaled(ivect[i], scalar_type(tab[i])),a);
165  //a.addmul(scalar_type(tab[i]), ivect[i]);
166 
167  for (i = 0; i < nbpt; i++)
168  tab3[i] = me.add_point(a + pararef.points()[i]);
169  size_type ib = me.add_point(a + barycenter);
170  me.add_pyramid(tab3[0],tab3[1],tab3[2],tab3[3],ib);
171  me.add_pyramid(tab3[4],tab3[6],tab3[5],tab3[7],ib);
172  me.add_pyramid(tab3[0],tab3[4],tab3[1],tab3[5],ib);
173  me.add_pyramid(tab3[1],tab3[5],tab3[3],tab3[7],ib);
174  me.add_pyramid(tab3[3],tab3[7],tab3[2],tab3[6],ib);
175  me.add_pyramid(tab3[2],tab3[6],tab3[0],tab3[4],ib);
176 
177  for (dim_type l = 0; l < N; l++) {
178  tab[l]++; total++;
179  if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
180  else break;
181  }
182  }
183  }
184 
185 
186  /* deformation inside a unit square -- ugly */
187  static base_node shake_func(const base_node& x) {
188  base_node z(x.size());
189  scalar_type c1 = 1., c2 = 1.;
190  for (size_type i=0; i < x.size(); ++i) {
191  c1*=(x[i]*(1.-x[i]));
192  c2*=(.5 - gmm::abs(x[i]-.5));
193  }
194  z[0] = x[0] + c1; // 1.
195  for (size_type i=1; i < x.size(); ++i) {
196  z[i] = x[i] + c2/3.; // /10
197  }
198  return z;
199  }
200 
201  static base_node radial_deformation(const base_node& x) {
202  GMM_ASSERT1(x.size() == 2, "For two-dimensional meshes only. \n");
203  base_node z(x.size());
204  z[0] = x[0] - 0.5 ;
205  z[1] = x[1] - 0.5 ;
206  scalar_type r = sqrt( z[0] * z[0] + z[1] * z[1] ) ;
207  scalar_type theta = atan2(z[1], z[0]);
208  if ( r < 0.5 - 1.e-6)
209 // theta += 1000. * gmm::sqrt(r) * (0.5 - r) * (0.5 - r) * (0.5 - r) * (0.5 - r) * gmm::sqrt(gmm::abs(0.1 - r)) * gmm::sqrt(gmm::abs(0.15 - r)) ;
210  theta += 10000. * gmm::sqrt(r) * (0.5 - r) * (0.5 - r) * (0.5 - r) * (0.5 - r) * (0.1 - r) * (0.15 - r) ;
211  z[0] = r * cos(theta) + 0.5;
212  z[1] = r * sin(theta) + 0.5;
213  return z;
214  }
215 
216  static void noise_unit_mesh(mesh& m, std::vector<size_type> nsubdiv,
218  size_type N = nsubdiv.size();
219  for (dal::bv_visitor ip(m.points().index()); !ip.finished(); ++ip) {
220  bool is_border = false;
221  base_node& P = m.points()[ip];
222  for (size_type i=0; i < N; ++i) {
223  if (gmm::abs(P[i]) < 1e-10 || gmm::abs(P[i]-1.) < 1e-10)
224  is_border = true;
225  }
226  if (!is_border) {
227  P = shake_func(P);
228  if (N == 2) P = radial_deformation(P) ;
229  for (size_type i=0; i < N; ++i)
230  P[i] += 0.*(double(1)/double(nsubdiv[i]* pgt->complexity()))
231  * gmm::random(double());
232  }
233  }
234  }
235 
236 
237  void regular_unit_mesh(mesh& m, std::vector<size_type> nsubdiv,
238  bgeot::pgeometric_trans pgt, bool noised) {
239  mesh msh;
240  dim_type N = dim_type(nsubdiv.size());
241  base_node org(N); gmm::clear(org);
242  std::vector<base_small_vector> vtab(N);
243  for (dim_type i = 0; i < N; i++) {
244  vtab[i] = base_small_vector(N); gmm::clear(vtab[i]);
245  (vtab[i])[i] = 1. / scalar_type(nsubdiv[i]) * 1.;
246  }
247  if (pgt->basic_structure() == bgeot::simplex_structure(N)) {
248  getfem::parallelepiped_regular_simplex_mesh
249  (msh, N, org, vtab.begin(), nsubdiv.begin());
250  } else if (pgt->basic_structure() == bgeot::parallelepiped_structure(N)) {
251  getfem::parallelepiped_regular_mesh
252  (msh, N, org, vtab.begin(), nsubdiv.begin());
253  } else if (pgt->basic_structure() == bgeot::prism_P1_structure(N)) {
254  getfem::parallelepiped_regular_prism_mesh
255  (msh, N, org, vtab.begin(), nsubdiv.begin());
256  } else if (pgt->basic_structure() == bgeot::pyramid_QK_structure(1)) {
257  getfem::parallelepiped_regular_pyramid_mesh
258  (msh, org, vtab.begin(), nsubdiv.begin());
259  } else {
260  GMM_ASSERT1(false, "cannot build a regular mesh for "
262  }
263 
264  m.clear();
265  /* build a mesh with a geotrans of degree K */
266  for (dal::bv_visitor cv(msh.convex_index()); !cv.finished(); ++cv) {
267  if (pgt == msh.trans_of_convex(cv)) {
268  m.add_convex_by_points(msh.trans_of_convex(cv),
269  msh.points_of_convex(cv).begin());
270  } else {
271  std::vector<base_node> pts(pgt->nb_points());
272  for (size_type i=0; i < pgt->nb_points(); ++i) {
273  pts[i] = msh.trans_of_convex(cv)->transform
274  (pgt->convex_ref()->points()[i], msh.points_of_convex(cv));
275  }
276  m.add_convex_by_points(pgt, pts.begin());
277  }
278  }
279 
280  /* apply a continuous deformation + some noise */
281  if (noised) noise_unit_mesh(m, nsubdiv, pgt);
282 
283  m.optimize_structure(false);
284  }
285 
286 
287 
288  void regular_mesh(mesh& m, const std::string &st) {
289  std::stringstream s(st);
290  bgeot::md_param PARAM;
291  PARAM.read_param_file(s);
292 
293  std::string GT = PARAM.string_value("GT");
294  GMM_ASSERT1(!GT.empty(), "regular mesh : you have at least to "
295  "specify the geometric transformation");
297 
298  size_type N = pgt->dim();
299  base_small_vector org(N); gmm::clear(org);
300 
301  const auto &o = PARAM.array_value("ORG");
302  if (o.size() > 0) {
303  GMM_ASSERT1(o.size() == N,
304  "ORG parameter should be an array of size " << N);
305  for (size_type i = 0; i < N; ++i) {
306  GMM_ASSERT1(o[i].type_of_param() == bgeot::md_param::REAL_VALUE,
307  "ORG should be a real array.");
308  org[i] = o[i].real();
309  }
310  }
311 
312  bool noised = (PARAM.int_value("NOISED") != 0);
313 
314  std::vector<size_type> nsubdiv(N);
315  gmm::fill(nsubdiv, 2);
316  const auto &ns = PARAM.array_value("NSUBDIV");
317  if (ns.size() > 0) {
318  GMM_ASSERT1(ns.size() == N,
319  "NSUBDIV parameter should be an array of size " << N);
320  for (size_type i = 0; i < N; ++i) {
321  GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
322  "NSUBDIV should be an integer array");
323  nsubdiv[i] = size_type(ns[i].real()+0.5);
324  }
325  }
326 
327  base_small_vector sizes(N);
328  gmm::fill(sizes, 1.0);
329 
330  const auto &si = PARAM.array_value("SIZES");
331  if (si.size() > 0) {
332  GMM_ASSERT1(si.size() == N,
333  "SIZES parameter should be an array of size " << N);
334  for (size_type i = 0; i < N; ++i) {
335  GMM_ASSERT1(si[i].type_of_param() == bgeot::md_param::REAL_VALUE,
336  "SIZES should be a real array");
337  sizes[i] = si[i].real();
338  }
339  }
340 
341  regular_unit_mesh(m, nsubdiv, pgt, noised);
342 
343  base_matrix M(N,N);
344  for (size_type i=0; i < N; ++i) M(i,i) = sizes[i];
345  m.transformation(M);
346  m.translation(org);
347 
348  }
349 
350 
351  void regular_ball_mesh(mesh& m, const std::string &st) {
352  std::stringstream s(st);
353  bgeot::md_param PARAM;
354  PARAM.read_param_file(s);
355 
356  std::string GT = PARAM.string_value("GT");
357  GMM_ASSERT1(!GT.empty(), "regular ball mesh : you have at least to "
358  "specify the geometric transformation");
360 
361  size_type N = pgt->dim();
362  base_small_vector org(N);
363 
364  const auto &o = PARAM.array_value("ORG");
365  if (o.size() > 0) {
366  GMM_ASSERT1(o.size() == N,
367  "ORG parameter should be an array of size " << N);
368  for (size_type i = 0; i < N; ++i) {
369  GMM_ASSERT1(o[i].type_of_param() == bgeot::md_param::REAL_VALUE,
370  "ORG should be a real array");
371  org[i] = o[i].real();
372  }
373  }
374 
375  // "NOISED" applies only to the interior of all merged sub-meshes
376  bool noised = (PARAM.int_value("NOISED") != 0);
377 
378  size_type nsubdiv0(2), nsubdiv1(2);
379  const auto &ns = PARAM.array_value("NSUBDIV");
380  if (ns.size() > 0) {
381  GMM_ASSERT1(ns.size() == 2,
382  "NSUBDIV parameter should be an array of size 2");
383  for (size_type i = 0; i < 2; ++i)
384  GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
385  "NSUBDIV should be an integer array");
386  nsubdiv0 = size_type(ns[0].real()+0.5);
387  nsubdiv1 = size_type(ns[1].real()+0.5);
388  }
389 
390  scalar_type radius(1), core_ratio(M_SQRT1_2);
391  const auto &si = PARAM.array_value("SIZES");
392  if (si.size() > 0) {
393  GMM_ASSERT1(si.size() == 1,
394  "SIZES parameter should be an array of size 1");
395  GMM_ASSERT1(si[0].type_of_param() == bgeot::md_param::REAL_VALUE,
396  "SIZES should be a real array");
397  radius = si[0].real();
398  }
399 
400  std::vector<size_type> nsubdiv(N);
401  gmm::fill(nsubdiv, nsubdiv0);
402  regular_unit_mesh(m, nsubdiv, pgt, noised);
403  std::vector<mesh> mm(N);
404  for (size_type i = 0; i < N; ++i) {
405  gmm::fill(nsubdiv, nsubdiv0);
406  nsubdiv[i] = nsubdiv1;
407  regular_unit_mesh(mm[i], nsubdiv, pgt, noised);
408  }
409 
410  base_matrix M(N,N);
411  for (size_type i=0; i < N; ++i) M(i,i) = core_ratio;
412  m.transformation(M);
413 
414  scalar_type peel_ratio = scalar_type(1)-core_ratio;
415  for (size_type i = 0; i < N; ++i) {
416  base_matrix MM(M);
417  MM(i,i) = peel_ratio;
418  mm[i].transformation(MM);
419 
420  std::vector<base_node> pts(mm[i].points().card(), base_node(N));
421  size_type j(0);
422  for (dal::bv_visitor pt(mm[i].points().index()); !pt.finished(); ++pt, ++j) {
423  pts[j] = mm[i].points()[pt];
424  for (unsigned k=0; k < N; ++k)
425  if (k != i) pts[j][k] += (pts[j][k]/core_ratio) * pts[j][i];
426  }
427  j = size_type(0);
428  for (dal::bv_visitor pt(mm[i].points().index()); !pt.finished(); ++pt, ++j)
429  mm[i].points()[pt] = pts[j];
430 
431  base_small_vector trsl(N);
432  trsl[i] = core_ratio;
433  mm[i].translation(trsl);
434  for (dal::bv_visitor cv(mm[i].convex_index()); !cv.finished(); ++cv)
435  m.add_convex_by_points(mm[i].trans_of_convex(cv),
436  mm[i].points_of_convex(cv).begin());
437  }
438 
439  std::vector<base_node> pts(m.points().card(), base_node(N));
440  size_type j(0);
441  for (dal::bv_visitor pt(m.points().index()); !pt.finished(); ++pt, ++j) {
442  pts[j] = m.points()[pt];
443  scalar_type maxcoord(0);
444  size_type kmax(0);
445  for (size_type k=0; k < N; ++k)
446  if (gmm::abs(pts[j][k]) > maxcoord) {
447  maxcoord = gmm::abs(pts[j][k]);
448  kmax = k;
449  }
450  if (maxcoord > 1e-10) {
451  scalar_type l(0), l0(0);
452  for (size_type k=0; k < N; ++k) {
453  if (k != kmax) {
454  scalar_type theta = M_PI_4 * pts[j][k] / maxcoord;
455  scalar_type c0 = std::min(scalar_type(1), maxcoord);
456  pts[j][k] = c0*tan(theta)* maxcoord + (scalar_type(1)-c0)*pts[j][k];
457  }
458  l += pts[j][k] * pts[j][k];
459  }
460  l = sqrt(l);
461  l0 = l/maxcoord;
462  scalar_type scale(radius);
463  scalar_type c(core_ratio);
464  c *= std::max(scalar_type(0.3),
465  (scalar_type(1) - sqrt(l0*l0 - scalar_type(1))));
466  if (l > c) {
467  scale -= (l - c) / (l0 - c) * (radius - radius/(l/maxcoord));
468  }
469  for (size_type k=0; k < N; ++k)
470  pts[j][k] *= scale;
471  }
472  }
473  j = size_type(0);
474  for (dal::bv_visitor pt(m.points().index()); !pt.finished(); ++pt, ++j)
475  m.points()[pt] = pts[j];
476  m.points().resort();
477 
478  size_type symmetries(PARAM.int_value("SYMMETRIES"));
479  symmetries = std::min(symmetries,N);
480 
481  for (size_type sym=0; sym < N-symmetries; ++sym) {
482  size_type sym0 = (sym+1) % N;
483  if (sym0 != 0) {
484  gmm::clear(M);
485  M(sym,sym0) = scalar_type(-1);
486  M(sym0,sym) = scalar_type(1);
487  for (size_type i=0; i < N; ++i)
488  if (i != sym && i != sym0) M(i,i) = scalar_type(1);
489  } else {
490  base_matrix M1(M), M2(M);
491  gmm::mult(M1,M2,M);
492  }
493  mesh m0;
494  m0.copy_from(m);
495  m0.transformation(M);
496  for (dal::bv_visitor cv(m0.convex_index()); !cv.finished(); ++cv)
497  m.add_convex_by_points(m0.trans_of_convex(cv),
498  m0.points_of_convex(cv).begin());
499  }
500 
501  m.translation(org);
502 
503  }
504  void regular_ball_shell_mesh(mesh &m, const std::string &st) {
505  std::stringstream s(st);
506  bgeot::md_param PARAM;
507  PARAM.read_param_file(s);
508 
509  std::string GT = PARAM.string_value("GT");
510  GMM_ASSERT1(!GT.empty(), "regular ball mesh : you have at least to "
511  "specify the geometric transformation");
513 
514  size_type N = pgt->dim();
515  base_small_vector org(N);
516  const auto &o = PARAM.array_value("ORG");
517  if (o.size() > 0) {
518  GMM_ASSERT1(o.size() == N,
519  "ORG parameter should be an array of size " << N);
520  for (size_type i = 0; i < N; ++i) {
521  GMM_ASSERT1(o[i].type_of_param() == bgeot::md_param::REAL_VALUE,
522  "ORG should be a real array");
523  org[i] = o[i].real();
524  }
525  }
526 
527  // "NOISED" applies only to the interior of all merged sub-meshes
528  bool noised = (PARAM.int_value("NOISED") != 0);
529 
530  size_type nsubdiv0(3), nsubdiv1(2);
531  const auto &ns = PARAM.array_value("NSUBDIV");
532  if (ns.size() > 0) {
533  GMM_ASSERT1(ns.size() == 2,
534  "NSUBDIV parameter should be an array of size 2");
535  for (size_type i = 0; i < 2; ++i)
536  GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
537  "NSUBDIV should be an integer array");
538  nsubdiv0 = size_type(ns[0].real()+0.5);
539  nsubdiv1 = size_type(ns[1].real()+0.5);
540  }
541 
542  scalar_type radius(1), thickness(0.5);
543  const auto &si = PARAM.array_value("SIZES");
544  if (si.size() > 0) {
545  GMM_ASSERT1(si.size() == 2,
546  "SIZES parameter should be an array of size 2");
547  GMM_ASSERT1(si[0].type_of_param() == bgeot::md_param::REAL_VALUE &&
548  si[1].type_of_param() == bgeot::md_param::REAL_VALUE ,
549  "SIZES should be a real array");
550  radius = si[0].real();
551  thickness = si[1].real();
552  }
553 
554  std::vector<size_type> nsubdiv(N, nsubdiv0);
555  nsubdiv[N-1] = nsubdiv1;
556 
557  mesh m0;
558  regular_unit_mesh(m0, nsubdiv, pgt, noised);
559 
560  std::vector<base_node> pts(m0.points().card(), base_node(N));
561  size_type j(0);
562  for (dal::bv_visitor pt(m0.points().index()); !pt.finished(); ++pt, ++j) {
563  pts[j] = m0.points()[pt];
564  scalar_type l(1);
565  for (size_type k=0; k < N-1; ++k) {
566  pts[j][k] = tan(pts[j][k]*M_PI_4);
567  l += pts[j][k]*pts[j][k];
568  }
569  l = sqrt(l);
570  scalar_type r(radius-thickness+thickness*pts[j][N-1]);
571  for (size_type k=0; k < N-1; ++k)
572  pts[j][k] *= r/l;
573  pts[j][N-1] = r/l;
574  }
575 
576  j = size_type(0);
577  for (dal::bv_visitor pt(m0.points().index()); !pt.finished(); ++pt, ++j)
578  m0.points()[pt] = pts[j];
579  m0.points().resort();
580 
581  base_matrix M(N,N);
582  for (size_type i=0; i < N-1; ++i)
583  M(i,i+1) = scalar_type(1);
584  M(N-1,0) = scalar_type(1);
585 
586  for (size_type i = 0; i < N; ++i) {
587  m0.transformation(M);
588  for (dal::bv_visitor cv(m0.convex_index()); !cv.finished(); ++cv)
589  m.add_convex_by_points(m0.trans_of_convex(cv),
590  m0.points_of_convex(cv).begin());
591  }
592 
593  size_type symmetries(PARAM.int_value("SYMMETRIES"));
594  symmetries = std::min(symmetries,N);
595 
596  for (size_type sym=0; sym < N-symmetries; ++sym) {
597  size_type sym0 = (sym+1) % N;
598  if (sym0 != 0) {
599  gmm::clear(M);
600  M(sym,sym0) = scalar_type(-1);
601  M(sym0,sym) = scalar_type(1);
602  for (size_type i=0; i < N; ++i)
603  if (i != sym && i != sym0) M(i,i) = scalar_type(1);
604  } else {
605  base_matrix M1(M), M2(M);
606  gmm::mult(M1,M2,M);
607  }
608  m0.copy_from(m);
609  m0.transformation(M);
610  for (dal::bv_visitor cv(m0.convex_index()); !cv.finished(); ++cv)
611  m.add_convex_by_points(m0.trans_of_convex(cv),
612  m0.points_of_convex(cv).begin());
613  }
614 
615  m.translation(org);
616 
617  }
618 
619 
620 } /* end of namespace getfem. */
Mesh structure definition.
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
size_type nb_convex() const
The total number of convexes in the mesh.
const ind_set & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:98
void transformation(const base_matrix &)
apply the given matrix transformation to each mesh node.
Definition: getfem_mesh.cc:254
void optimize_structure(bool with_renumbering=true)
Pack the mesh : renumber convexes and nodes such that there is no holes in their numbering.
Definition: getfem_mesh.cc:222
void copy_from(const mesh &m)
Clone a mesh.
Definition: getfem_mesh.cc:486
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
Build regular meshes.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
Definition: gmm_blas.h:58
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
pconvex_structure pyramid_QK_structure(dim_type k)
Give a pointer on the 3D pyramid structure for a degree k = 1 or 2.
std::string name_of_geometric_trans(pgeometric_trans p)
Get the string name of a geometric transformation.
pconvex_structure parallelepiped_structure(dim_type nc, dim_type k)
Give a pointer on the structures of a parallelepiped of dimension d.
pconvex_structure prism_P1_structure(dim_type nc)
Give a pointer on the structures of a prism of dimension d.
pconvex_ref parallelepiped_of_reference(dim_type nc, dim_type k)
parallelepiped of reference of dimension nc (and degree 1)
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
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
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
GEneric Tool for Finite Element Methods.
void regular_mesh(mesh &m, const std::string &st)
Build a regular mesh parametrized by the string st.
void regular_ball_mesh(mesh &m, const std::string &st)
Build a regular mesh on a ball, parametrized by the string st.
void regular_unit_mesh(mesh &m, std::vector< size_type > nsubdiv, bgeot::pgeometric_trans pgt, bool noised=false)
Build a regular mesh of the unit square/cube/, etc.
void regular_ball_shell_mesh(mesh &m, const std::string &st)
Build a regular mesh on a ball shell, parametrized by the string st.