27 void parallelepiped_regular_simplex_mesh_
28 (mesh &me, dim_type N,
const base_node &org,
29 const base_small_vector *ivect,
const size_type *iref) {
33 if (N >= 5) GMM_WARNING1(
"CAUTION : Simplexification in dimension >= 5 "
34 "has not been tested and the resulting mesh "
35 "should be not conformal");
43 for (i = 0; i < nbpt; ++i) {
45 for (dim_type n = 0; n < N; ++n)
46 gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
47 pararef.points()[i] = a;
53 std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
55 std::fill(tab.begin(), tab.end(), 0);
56 while (tab[N-1] != iref[N-1]) {
57 for (a = org, i = 0; i < N; i++)
58 gmm::add(gmm::scaled(ivect[i],scalar_type(tab[i])),a);
61 for (i = 0; i < nbpt; i++)
62 tab3[i] = me.add_point(a + pararef.points()[i]);
64 for (i = 0; i < nbs; i++) {
66 for (dim_type l = 0; l <= N; l++)
68 tab1[l] = tab3[(tab2[l]
69 + (((total & 1) && N != 3) ? (nbpt/2) : 0)) % nbpt];
70 me.add_simplex(N, tab1.begin());
73 for (dim_type l = 0; l < N; l++) {
75 if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
82 void parallelepiped_regular_prism_mesh_
83 (mesh &me, dim_type N,
const base_node &org,
84 const base_small_vector *ivect,
const size_type *iref) {
86 parallelepiped_regular_simplex_mesh_(aux, dim_type(N-1), org, ivect, iref);
87 std::vector<base_node> ptab(2 * N);
89 for (dal::bv_visitor cv(aux.convex_index()); !cv.finished(); ++cv) {
90 std::copy(aux.points_of_convex(cv).begin(),
91 aux.points_of_convex(cv).end(), ptab.begin());
93 for (
size_type k = 0; k < iref[N-1]; ++k) {
95 for (dim_type j = 0; j < N; ++j) ptab[j+N] = ptab[j] + ivect[N-1];
96 me.add_prism_by_points(N, ptab.begin());
98 std::copy(ptab.begin()+N, ptab.end(), ptab.begin());
103 void parallelepiped_regular_mesh_
104 (mesh &me, dim_type N,
const base_node &org,
105 const base_small_vector *ivect,
const size_type *iref,
bool linear_gt) {
111 for (i = 0; i < nbpt; ++i) {
113 for (dim_type n = 0; n < N; ++n)
114 gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
116 pararef.points()[i] = a;
119 std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
121 std::fill(tab.begin(), tab.end(), 0);
122 while (tab[N-1] != iref[N-1]) {
123 for (a = org, i = 0; i < N; i++)
124 gmm::add(gmm::scaled(ivect[i], scalar_type(tab[i])),a);
127 for (i = 0; i < nbpt; i++)
128 tab3[i] = me.add_point(a + pararef.points()[i]);
129 me.add_convex(linear_gt ?
130 bgeot::parallelepiped_linear_geotrans(N) :
131 bgeot::parallelepiped_geotrans(N, 1), tab3.begin());
133 for (dim_type l = 0; l < N; l++) {
135 if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
141 void parallelepiped_regular_pyramid_mesh_
142 (mesh &me,
const base_node &org,
143 const base_small_vector *ivect,
const size_type *iref) {
147 base_node a = org, barycenter(N);
150 for (i = 0; i < nbpt; ++i) {
152 for (dim_type n = 0; n < N; ++n)
153 gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
155 pararef.points()[i] = a;
158 barycenter /= double(nbpt);
160 std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
162 std::fill(tab.begin(), tab.end(), 0);
163 while (tab[N-1] != iref[N-1]) {
164 for (a = org, i = 0; i < N; i++)
165 gmm::add(gmm::scaled(ivect[i], scalar_type(tab[i])),a);
168 for (i = 0; i < nbpt; i++)
169 tab3[i] = me.add_point(a + pararef.points()[i]);
170 size_type ib = me.add_point(a + barycenter);
171 me.add_pyramid(tab3[0],tab3[1],tab3[2],tab3[3],ib);
172 me.add_pyramid(tab3[4],tab3[6],tab3[5],tab3[7],ib);
173 me.add_pyramid(tab3[0],tab3[4],tab3[1],tab3[5],ib);
174 me.add_pyramid(tab3[1],tab3[5],tab3[3],tab3[7],ib);
175 me.add_pyramid(tab3[3],tab3[7],tab3[2],tab3[6],ib);
176 me.add_pyramid(tab3[2],tab3[6],tab3[0],tab3[4],ib);
178 for (dim_type l = 0; l < N; l++) {
180 if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
188 static base_node shake_func(
const base_node& x) {
189 base_node z(x.size());
190 scalar_type c1 = 1., c2 = 1.;
192 c1*=(x[i]*(1.-x[i]));
193 c2*=(.5 - gmm::abs(x[i]-.5));
202 static base_node radial_deformation(
const base_node& x) {
203 GMM_ASSERT1(x.size() == 2,
"For two-dimensional meshes only. \n");
204 base_node z(x.size());
207 scalar_type r = sqrt( z[0] * z[0] + z[1] * z[1] ) ;
208 scalar_type theta = atan2(z[1], z[0]);
209 if ( r < 0.5 - 1.e-6)
211 theta += 10000. * gmm::sqrt(r) * (0.5 - r) * (0.5 - r) * (0.5 - r) * (0.5 - r) * (0.1 - r) * (0.15 - r) ;
212 z[0] = r * cos(theta) + 0.5;
213 z[1] = r * sin(theta) + 0.5;
217 static void noise_unit_mesh(mesh& m, std::vector<size_type> nsubdiv,
220 for (dal::bv_visitor ip(m.points().index()); !ip.finished(); ++ip) {
221 bool is_border =
false;
222 base_node& P = m.points()[ip];
224 if (gmm::abs(P[i]) < 1e-10 || gmm::abs(P[i]-1.) < 1e-10)
229 if (N == 2) P = radial_deformation(P) ;
231 P[i] += 0.*(
double(1)/
double(nsubdiv[i]* pgt->complexity()))
232 * gmm::random(
double());
241 dim_type N = dim_type(nsubdiv.size());
242 base_node org(N); gmm::clear(org);
243 std::vector<base_small_vector> vtab(N);
244 for (dim_type i = 0; i < N; i++) {
245 vtab[i] = base_small_vector(N); gmm::clear(vtab[i]);
246 (vtab[i])[i] = 1. / scalar_type(nsubdiv[i]) * 1.;
249 getfem::parallelepiped_regular_simplex_mesh
250 (msh, N, org, vtab.begin(), nsubdiv.begin());
252 getfem::parallelepiped_regular_mesh
253 (msh, N, org, vtab.begin(), nsubdiv.begin());
255 getfem::parallelepiped_regular_prism_mesh
256 (msh, N, org, vtab.begin(), nsubdiv.begin());
258 getfem::parallelepiped_regular_pyramid_mesh
259 (msh, org, vtab.begin(), nsubdiv.begin());
261 GMM_ASSERT1(
false,
"cannot build a regular mesh for "
267 for (dal::bv_visitor cv(msh.
convex_index()); !cv.finished(); ++cv) {
268 if (pgt == msh.trans_of_convex(cv)) {
270 msh.points_of_convex(cv).begin());
272 std::vector<base_node> pts(pgt->nb_points());
273 for (
size_type i=0; i < pgt->nb_points(); ++i) {
274 pts[i] = msh.trans_of_convex(cv)->transform
275 (pgt->convex_ref()->points()[i], msh.points_of_convex(cv));
282 if (noised) noise_unit_mesh(m, nsubdiv, pgt);
290 std::stringstream s(st);
291 bgeot::md_param PARAM;
292 PARAM.read_param_file(s);
294 std::string GT = PARAM.string_value(
"GT");
295 GMM_ASSERT1(!GT.empty(),
"regular mesh : you have at least to "
296 "specify the geometric transformation");
300 base_small_vector org(N); gmm::clear(org);
302 const auto &o = PARAM.array_value(
"ORG");
304 GMM_ASSERT1(o.size() == N,
305 "ORG parameter should be an array of size " << N);
307 GMM_ASSERT1(o[i].type_of_param() == bgeot::md_param::REAL_VALUE,
308 "ORG should be a real array.");
309 org[i] = o[i].real();
313 bool noised = (PARAM.int_value(
"NOISED") != 0);
315 std::vector<size_type> nsubdiv(N);
316 gmm::fill(nsubdiv, 2);
317 const auto &ns = PARAM.array_value(
"NSUBDIV");
319 GMM_ASSERT1(ns.size() == N,
320 "NSUBDIV parameter should be an array of size " << N);
322 GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
323 "NSUBDIV should be an integer array");
324 nsubdiv[i] =
size_type(ns[i].real()+0.5);
328 base_small_vector sizes(N);
329 gmm::fill(sizes, 1.0);
331 const auto &si = PARAM.array_value(
"SIZES");
333 GMM_ASSERT1(si.size() == N,
334 "SIZES parameter should be an array of size " << N);
336 GMM_ASSERT1(si[i].type_of_param() == bgeot::md_param::REAL_VALUE,
337 "SIZES should be a real array");
338 sizes[i] = si[i].real();
345 for (
size_type i=0; i < N; ++i) M(i,i) = sizes[i];
353 std::stringstream s(st);
354 bgeot::md_param PARAM;
355 PARAM.read_param_file(s);
357 std::string GT = PARAM.string_value(
"GT");
358 GMM_ASSERT1(!GT.empty(),
"regular ball mesh : you have at least to "
359 "specify the geometric transformation");
363 base_small_vector org(N);
365 const auto &o = PARAM.array_value(
"ORG");
367 GMM_ASSERT1(o.size() == N,
368 "ORG parameter should be an array of size " << N);
370 GMM_ASSERT1(o[i].type_of_param() == bgeot::md_param::REAL_VALUE,
371 "ORG should be a real array");
372 org[i] = o[i].real();
377 bool noised = (PARAM.int_value(
"NOISED") != 0);
380 const auto &ns = PARAM.array_value(
"NSUBDIV");
382 GMM_ASSERT1(ns.size() == 2,
383 "NSUBDIV parameter should be an array of size 2");
385 GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
386 "NSUBDIV should be an integer array");
391 scalar_type radius(1), core_ratio(M_SQRT1_2);
392 const auto &si = PARAM.array_value(
"SIZES");
394 GMM_ASSERT1(si.size() == 1,
395 "SIZES parameter should be an array of size 1");
396 GMM_ASSERT1(si[0].type_of_param() == bgeot::md_param::REAL_VALUE,
397 "SIZES should be a real array");
398 radius = si[0].real();
401 std::vector<size_type> nsubdiv(N);
402 gmm::fill(nsubdiv, nsubdiv0);
404 std::vector<mesh> mm(N);
406 gmm::fill(nsubdiv, nsubdiv0);
407 nsubdiv[i] = nsubdiv1;
412 for (
size_type i=0; i < N; ++i) M(i,i) = core_ratio;
415 scalar_type peel_ratio = scalar_type(1)-core_ratio;
418 MM(i,i) = peel_ratio;
419 mm[i].transformation(MM);
421 std::vector<base_node> pts(mm[i].points().card(), base_node(N));
423 for (dal::bv_visitor pt(mm[i].points().index()); !pt.finished(); ++pt, ++j) {
424 pts[j] = mm[i].points()[pt];
425 for (
unsigned k=0; k < N; ++k)
426 if (k != i) pts[j][k] += (pts[j][k]/core_ratio) * pts[j][i];
429 for (dal::bv_visitor pt(mm[i].points().index()); !pt.finished(); ++pt, ++j)
430 mm[i].points()[pt] = pts[j];
432 base_small_vector trsl(N);
433 trsl[i] = core_ratio;
434 mm[i].translation(trsl);
435 for (dal::bv_visitor cv(mm[i].convex_index()); !cv.finished(); ++cv)
437 mm[i].points_of_convex(cv).begin());
440 std::vector<base_node> pts(m.points().card(), base_node(N));
442 for (dal::bv_visitor pt(m.points().index()); !pt.finished(); ++pt, ++j) {
443 pts[j] = m.points()[pt];
444 scalar_type maxcoord(0);
447 if (gmm::abs(pts[j][k]) > maxcoord) {
448 maxcoord = gmm::abs(pts[j][k]);
451 if (maxcoord > 1e-10) {
452 scalar_type l(0), l0(0);
455 scalar_type theta = M_PI_4 * pts[j][k] / maxcoord;
456 scalar_type c0 = std::min(scalar_type(1), maxcoord);
457 pts[j][k] = c0*tan(theta)* maxcoord + (scalar_type(1)-c0)*pts[j][k];
459 l += pts[j][k] * pts[j][k];
463 scalar_type scale(radius);
464 scalar_type c(core_ratio);
465 c *= std::max(scalar_type(0.3),
466 (scalar_type(1) - sqrt(l0*l0 - scalar_type(1))));
468 scale -= (l - c) / (l0 - c) * (radius - radius/(l/maxcoord));
475 for (dal::bv_visitor pt(m.points().index()); !pt.finished(); ++pt, ++j)
476 m.points()[pt] = pts[j];
479 size_type symmetries(PARAM.int_value(
"SYMMETRIES"));
480 symmetries = std::min(symmetries,N);
482 for (
size_type sym=0; sym < N-symmetries; ++sym) {
486 M(sym,sym0) = scalar_type(-1);
487 M(sym0,sym) = scalar_type(1);
489 if (i != sym && i != sym0) M(i,i) = scalar_type(1);
491 base_matrix M1(M), M2(M);
497 for (dal::bv_visitor cv(m0.
convex_index()); !cv.finished(); ++cv)
499 m0.points_of_convex(cv).begin());
506 std::stringstream s(st);
507 bgeot::md_param PARAM;
508 PARAM.read_param_file(s);
510 std::string GT = PARAM.string_value(
"GT");
511 GMM_ASSERT1(!GT.empty(),
"regular ball mesh : you have at least to "
512 "specify the geometric transformation");
516 base_small_vector org(N);
517 const auto &o = PARAM.array_value(
"ORG");
519 GMM_ASSERT1(o.size() == N,
520 "ORG parameter should be an array of size " << N);
522 GMM_ASSERT1(o[i].type_of_param() == bgeot::md_param::REAL_VALUE,
523 "ORG should be a real array");
524 org[i] = o[i].real();
529 bool noised = (PARAM.int_value(
"NOISED") != 0);
532 const auto &ns = PARAM.array_value(
"NSUBDIV");
534 GMM_ASSERT1(ns.size() == 2,
535 "NSUBDIV parameter should be an array of size 2");
537 GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
538 "NSUBDIV should be an integer array");
543 scalar_type radius(1), thickness(0.5);
544 const auto &si = PARAM.array_value(
"SIZES");
546 GMM_ASSERT1(si.size() == 2,
547 "SIZES parameter should be an array of size 2");
548 GMM_ASSERT1(si[0].type_of_param() == bgeot::md_param::REAL_VALUE &&
549 si[1].type_of_param() == bgeot::md_param::REAL_VALUE ,
550 "SIZES should be a real array");
551 radius = si[0].real();
552 thickness = si[1].real();
555 std::vector<size_type> nsubdiv(N, nsubdiv0);
556 nsubdiv[N-1] = nsubdiv1;
561 std::vector<base_node> pts(m0.points().card(), base_node(N));
563 for (dal::bv_visitor pt(m0.points().index()); !pt.finished(); ++pt, ++j) {
564 pts[j] = m0.points()[pt];
567 pts[j][k] = tan(pts[j][k]*M_PI_4);
568 l += pts[j][k]*pts[j][k];
571 scalar_type r(radius-thickness+thickness*pts[j][N-1]);
578 for (dal::bv_visitor pt(m0.points().index()); !pt.finished(); ++pt, ++j)
579 m0.points()[pt] = pts[j];
580 m0.points().resort();
584 M(i,i+1) = scalar_type(1);
585 M(N-1,0) = scalar_type(1);
589 for (dal::bv_visitor cv(m0.
convex_index()); !cv.finished(); ++cv)
591 m0.points_of_convex(cv).begin());
594 size_type symmetries(PARAM.int_value(
"SYMMETRIES"));
595 symmetries = std::min(symmetries,N);
597 for (
size_type sym=0; sym < N-symmetries; ++sym) {
601 M(sym,sym0) = scalar_type(-1);
602 M(sym0,sym) = scalar_type(1);
604 if (i != sym && i != sym0) M(i,i) = scalar_type(1);
606 base_matrix M1(M), M2(M);
611 for (dal::bv_visitor cv(m0.
convex_index()); !cv.finished(); ++cv)
613 m0.points_of_convex(cv).begin());
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).
void transformation(const base_matrix &)
apply the given matrix transformation to each mesh node.
void optimize_structure(bool with_renumbering=true)
Pack the mesh : renumber convexes and nodes such that there is no holes in their numbering.
void copy_from(const mesh &m)
Clone a mesh.
void clear()
Erase the mesh.
void translation(const base_small_vector &)
Apply the given translation to each mesh node.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
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.
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
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.