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) {
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");
42 for (i = 0; i < nbpt; ++i) {
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;
52 std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
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);
60 for (i = 0; i < nbpt; i++)
61 tab3[i] = me.add_point(a + pararef.points()[i]);
63 for (i = 0; i < nbs; i++) {
65 for (dim_type l = 0; l <= N; l++)
67 tab1[l] = tab3[(tab2[l]
68 + (((total & 1) && N != 3) ? (nbpt/2) : 0)) % nbpt];
69 me.add_simplex(N, tab1.begin());
72 for (dim_type l = 0; l < N; l++) {
74 if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
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) {
85 parallelepiped_regular_simplex_mesh_(aux, dim_type(N-1), org, ivect, iref);
86 std::vector<base_node> ptab(2 * N);
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());
92 for (
size_type k = 0; k < iref[N-1]; ++k) {
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());
97 std::copy(ptab.begin()+N, ptab.end(), ptab.begin());
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) {
110 for (i = 0; i < nbpt; ++i) {
112 for (dim_type n = 0; n < N; ++n)
113 gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
115 pararef.points()[i] = a;
118 std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
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);
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());
132 for (dim_type l = 0; l < N; l++) {
134 if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
140 void parallelepiped_regular_pyramid_mesh_
141 (mesh &me,
const base_node &org,
142 const base_small_vector *ivect,
const size_type *iref) {
146 base_node a = org, barycenter(N);
149 for (i = 0; i < nbpt; ++i) {
151 for (dim_type n = 0; n < N; ++n)
152 gmm::add(gmm::scaled(ivect[n],pararef.points()[i][n]),a);
154 pararef.points()[i] = a;
157 barycenter /= double(nbpt);
159 std::vector<size_type> tab1(N+1), tab(N), tab3(nbpt);
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);
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);
177 for (dim_type l = 0; l < N; l++) {
179 if (l < N-1 && tab[l] >= iref[l]) { total -= tab[l]; tab[l] = 0; }
187 static base_node shake_func(
const base_node& x) {
188 base_node z(x.size());
189 scalar_type c1 = 1., c2 = 1.;
191 c1*=(x[i]*(1.-x[i]));
192 c2*=(.5 - gmm::abs(x[i]-.5));
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());
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)
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;
216 static void noise_unit_mesh(mesh& m, std::vector<size_type> nsubdiv,
219 for (dal::bv_visitor ip(m.points().index()); !ip.finished(); ++ip) {
220 bool is_border =
false;
221 base_node& P = m.points()[ip];
223 if (gmm::abs(P[i]) < 1e-10 || gmm::abs(P[i]-1.) < 1e-10)
228 if (N == 2) P = radial_deformation(P) ;
230 P[i] += 0.*(
double(1)/
double(nsubdiv[i]* pgt->complexity()))
231 * gmm::random(
double());
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.;
248 getfem::parallelepiped_regular_simplex_mesh
249 (msh, N, org, vtab.begin(), nsubdiv.begin());
251 getfem::parallelepiped_regular_mesh
252 (msh, N, org, vtab.begin(), nsubdiv.begin());
254 getfem::parallelepiped_regular_prism_mesh
255 (msh, N, org, vtab.begin(), nsubdiv.begin());
257 getfem::parallelepiped_regular_pyramid_mesh
258 (msh, org, vtab.begin(), nsubdiv.begin());
260 GMM_ASSERT1(
false,
"cannot build a regular mesh for "
266 for (dal::bv_visitor cv(msh.
convex_index()); !cv.finished(); ++cv) {
267 if (pgt == msh.trans_of_convex(cv)) {
269 msh.points_of_convex(cv).begin());
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));
281 if (noised) noise_unit_mesh(m, nsubdiv, pgt);
289 std::stringstream s(st);
290 bgeot::md_param PARAM;
291 PARAM.read_param_file(s);
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");
299 base_small_vector org(N); gmm::clear(org);
301 const auto &o = PARAM.array_value(
"ORG");
303 GMM_ASSERT1(o.size() == N,
304 "ORG parameter should be an array of size " << N);
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();
312 bool noised = (PARAM.int_value(
"NOISED") != 0);
314 std::vector<size_type> nsubdiv(N);
315 gmm::fill(nsubdiv, 2);
316 const auto &ns = PARAM.array_value(
"NSUBDIV");
318 GMM_ASSERT1(ns.size() == N,
319 "NSUBDIV parameter should be an array of size " << N);
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);
327 base_small_vector sizes(N);
328 gmm::fill(sizes, 1.0);
330 const auto &si = PARAM.array_value(
"SIZES");
332 GMM_ASSERT1(si.size() == N,
333 "SIZES parameter should be an array of size " << N);
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();
344 for (
size_type i=0; i < N; ++i) M(i,i) = sizes[i];
352 std::stringstream s(st);
353 bgeot::md_param PARAM;
354 PARAM.read_param_file(s);
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");
362 base_small_vector org(N);
364 const auto &o = PARAM.array_value(
"ORG");
366 GMM_ASSERT1(o.size() == N,
367 "ORG parameter should be an array of size " << N);
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();
376 bool noised = (PARAM.int_value(
"NOISED") != 0);
379 const auto &ns = PARAM.array_value(
"NSUBDIV");
381 GMM_ASSERT1(ns.size() == 2,
382 "NSUBDIV parameter should be an array of size 2");
384 GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
385 "NSUBDIV should be an integer array");
390 scalar_type radius(1), core_ratio(M_SQRT1_2);
391 const auto &si = PARAM.array_value(
"SIZES");
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();
400 std::vector<size_type> nsubdiv(N);
401 gmm::fill(nsubdiv, nsubdiv0);
403 std::vector<mesh> mm(N);
405 gmm::fill(nsubdiv, nsubdiv0);
406 nsubdiv[i] = nsubdiv1;
411 for (
size_type i=0; i < N; ++i) M(i,i) = core_ratio;
414 scalar_type peel_ratio = scalar_type(1)-core_ratio;
417 MM(i,i) = peel_ratio;
418 mm[i].transformation(MM);
420 std::vector<base_node> pts(mm[i].points().card(), base_node(N));
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];
428 for (dal::bv_visitor pt(mm[i].points().index()); !pt.finished(); ++pt, ++j)
429 mm[i].points()[pt] = pts[j];
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)
436 mm[i].points_of_convex(cv).begin());
439 std::vector<base_node> pts(m.points().card(), base_node(N));
441 for (dal::bv_visitor pt(m.points().index()); !pt.finished(); ++pt, ++j) {
442 pts[j] = m.points()[pt];
443 scalar_type maxcoord(0);
446 if (gmm::abs(pts[j][k]) > maxcoord) {
447 maxcoord = gmm::abs(pts[j][k]);
450 if (maxcoord > 1e-10) {
451 scalar_type l(0), l0(0);
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];
458 l += pts[j][k] * pts[j][k];
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))));
467 scale -= (l - c) / (l0 - c) * (radius - radius/(l/maxcoord));
474 for (dal::bv_visitor pt(m.points().index()); !pt.finished(); ++pt, ++j)
475 m.points()[pt] = pts[j];
478 size_type symmetries(PARAM.int_value(
"SYMMETRIES"));
479 symmetries = std::min(symmetries,N);
481 for (
size_type sym=0; sym < N-symmetries; ++sym) {
485 M(sym,sym0) = scalar_type(-1);
486 M(sym0,sym) = scalar_type(1);
488 if (i != sym && i != sym0) M(i,i) = scalar_type(1);
490 base_matrix M1(M), M2(M);
496 for (dal::bv_visitor cv(m0.
convex_index()); !cv.finished(); ++cv)
498 m0.points_of_convex(cv).begin());
505 std::stringstream s(st);
506 bgeot::md_param PARAM;
507 PARAM.read_param_file(s);
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");
515 base_small_vector org(N);
516 const auto &o = PARAM.array_value(
"ORG");
518 GMM_ASSERT1(o.size() == N,
519 "ORG parameter should be an array of size " << N);
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();
528 bool noised = (PARAM.int_value(
"NOISED") != 0);
531 const auto &ns = PARAM.array_value(
"NSUBDIV");
533 GMM_ASSERT1(ns.size() == 2,
534 "NSUBDIV parameter should be an array of size 2");
536 GMM_ASSERT1(ns[i].type_of_param() == bgeot::md_param::REAL_VALUE,
537 "NSUBDIV should be an integer array");
542 scalar_type radius(1), thickness(0.5);
543 const auto &si = PARAM.array_value(
"SIZES");
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();
554 std::vector<size_type> nsubdiv(N, nsubdiv0);
555 nsubdiv[N-1] = nsubdiv1;
560 std::vector<base_node> pts(m0.points().card(), base_node(N));
562 for (dal::bv_visitor pt(m0.points().index()); !pt.finished(); ++pt, ++j) {
563 pts[j] = m0.points()[pt];
566 pts[j][k] = tan(pts[j][k]*M_PI_4);
567 l += pts[j][k]*pts[j][k];
570 scalar_type r(radius-thickness+thickness*pts[j][N-1]);
577 for (dal::bv_visitor pt(m0.points().index()); !pt.finished(); ++pt, ++j)
578 m0.points()[pt] = pts[j];
579 m0.points().resort();
583 M(i,i+1) = scalar_type(1);
584 M(N-1,0) = scalar_type(1);
588 for (dal::bv_visitor cv(m0.
convex_index()); !cv.finished(); ++cv)
590 m0.points_of_convex(cv).begin());
593 size_type symmetries(PARAM.int_value(
"SYMMETRIES"));
594 symmetries = std::min(symmetries,N);
596 for (
size_type sym=0; sym < N-symmetries; ++sym) {
600 M(sym,sym0) = scalar_type(-1);
601 M(sym0,sym) = scalar_type(1);
603 if (i != sym && i != sym0) M(i,i) = scalar_type(1);
605 base_matrix M1(M), M2(M);
610 for (dal::bv_visitor cv(m0.
convex_index()); !cv.finished(); ++cv)
612 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.