27 #if defined(GETFEM_HAVE_METIS_OLD_API)
28 extern "C" void METIS_PartGraphKway(
int *,
int *,
int *,
int *,
int *,
int *,
29 int *,
int *,
int *,
int *,
int *);
30 #elif defined(GETFEM_HAVE_METIS)
36 gmm::uint64_type act_counter(
void) {
37 static gmm::uint64_type c = gmm::uint64_type(1);
42 for (dal::bv_visitor i(valid_cvf_sets); !i.finished(); ++i)
43 cvf_sets[i].sup_all(c);
48 for (dal::bv_visitor i(valid_cvf_sets); !i.finished(); ++i)
53 void mesh::handle_region_refinement(
size_type ic,
54 const std::vector<size_type> &icv,
60 for (dal::bv_visitor ir(valid_cvf_sets); !ir.finished(); ++ir) {
61 mesh_region &r = cvf_sets[ir];
64 if (refine && r[ic].any()) {
66 for (
size_type jc = 0; jc < icv.size(); ++jc)
70 for (
short_type f = 0; f < pgt->structure()->nb_faces(); ++f) {
73 for (
size_type jc = 0; jc < icv.size(); ++jc) {
75 for (
short_type fsub = 0; fsub < pgtsub->structure()->nb_faces();
78 ind_set::const_iterator it = s.begin(), ite = s.end();
80 for (; it != ite; ++it)
81 if (std::find(icv.begin(), icv.end(), *it) != icv.end())
82 { found =
true;
break; }
85 base_node pt, barycentre
86 =gmm::mean_value(pgtsub->convex_ref()->points_of_face(fsub));
87 pt = pgtsub->transform(barycentre, points_of_convex(icv[jc]));
89 giv.init(points_of_convex(ic), pgt);
90 giv.
invert(pt, barycentre);
93 if (gmm::abs(pgt->convex_ref()->is_in_face(f,barycentre)) < 0.001)
101 for (
size_type jc = 0; jc < icv.size(); ++jc)
102 if (!refine && r[icv[jc]].any()) {
107 for (
short_type fsub = 0; fsub < pgtsub->structure()->nb_faces();
109 if (r[icv[jc]][fsub+1]) {
110 base_node pt, barycentre
111 = gmm::mean_value(pgtsub->convex_ref()->points_of_face(fsub));
112 pt = pgtsub->transform(barycentre, points_of_convex(icv[jc]));
114 giv.init(points_of_convex(ic), pgt);
115 giv.
invert(pt, barycentre);
117 for (
short_type f = 0; f < pgt->structure()->nb_faces(); ++f)
118 if (gmm::abs(pgt->convex_ref()->is_in_face(f,barycentre)) < 0.001)
119 { r.add(ic, f);
break; }
125 void mesh::init(
void) {
126 #if GETFEM_PARA_LEVEL > 1
129 cuthill_mckee_uptodate =
false;
134 mesh::mesh(
const bgeot::basic_mesh &m,
const std::string name)
135 :
bgeot::basic_mesh(m), name_(name) { init(); }
137 mesh::mesh(
const mesh &m) : context_dependencies(),
138 std::enable_shared_from_this<
getfem::mesh>()
141 mesh &mesh::operator=(
const mesh &m) {
142 clear_dependencies();
148 #if GETFEM_PARA_LEVEL > 1
150 void mesh::compute_mpi_region()
const {
152 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
153 MPI_Comm_size(MPI_COMM_WORLD, &size);
157 mpi_region.from_mesh(*
this);
160 std::vector<int> xadj(ne+1), adjncy, numelt(ne), npart(ne);
163 double t_ref = MPI_Wtime();
167 for (dal::bv_visitor ic(
convex_index()); !ic.finished(); ++ic, ++j) {
172 for (dal::bv_visitor ic(
convex_index()); !ic.finished(); ++ic, ++j) {
175 for (ind_set::iterator it = s.begin();
176 it != s.end(); ++it) { adjncy.push_back(indelt[*it]); ++k; }
180 #ifdef GETFEM_HAVE_METIS_OLD_API
181 int wgtflag = 0, numflag = 0, edgecut;
182 int options[5] = {0,0,0,0,0};
183 METIS_PartGraphKway(&ne, &(xadj[0]), &(adjncy[0]), 0, 0, &wgtflag,
184 &numflag, &size, options, &edgecut, &(npart[0]));
186 int ncon = 1, edgecut;
187 int options[METIS_NOPTIONS] = { 0 };
188 METIS_SetDefaultOptions(options);
189 METIS_PartGraphKway(&ne, &ncon, &(xadj[0]), &(adjncy[0]), 0, 0, 0,
190 &size, 0, 0, options, &edgecut, &(npart[0]));
194 if (npart[i] == rank) mpi_region.add(numelt[i]);
197 cout <<
"Partition time "<< MPI_Wtime()-t_ref << endl;
200 valid_sub_regions.clear();
203 void mesh::compute_mpi_sub_region(
size_type n)
const {
204 if (valid_cvf_sets.is_in(n)) {
208 mpi_sub_region[n] = mesh_region();
209 valid_sub_regions.add(n);
212 void mesh::intersect_with_mpi_region(mesh_region &rg)
const {
214 rg = get_mpi_region();
215 }
else if (
int(rg.id()) >= 0) {
216 rg = get_mpi_sub_region(rg.id());
225 for (i = 0; i < j; i++)
226 if (!convex_tab.index_valid(i))
229 for (i = 0, j = pts.size()-1;
230 i < j && j != ST_NIL; ++i, --j) {
231 while (i < j && j != ST_NIL && pts.index()[i]) ++i;
232 while (i < j && j != ST_NIL && !(pts.index()[j])) --j;
235 if (with_renumbering) {
236 std::vector<size_type> cmk, iord(nbc), iordinv(nbc);
237 for (i = 0; i < nbc; ++i) iord[i] = iordinv[i] = i;
240 for (i = 0; i < nbc; ++i) {
244 std::swap(iord[i], iord[j]);
245 std::swap(iordinv[iord[i]], iordinv[iord[j]]);
252 { pts.translation(V); touch(); }
255 pts.transformation(M);
256 Bank_info = std::unique_ptr<Bank_info_struct>();
261 bool is_first =
true;
262 Pmin.clear(); Pmax.clear();
263 for (dal::bv_visitor i(pts.index()); !i.finished(); ++i) {
264 if (is_first) { Pmin = Pmax = pts[i]; is_first =
false; }
265 else for (dim_type j=0; j < dim(); ++j) {
266 Pmin[j] = std::min(Pmin[j], pts[i][j]);
267 Pmax[j] = std::max(Pmax[j], pts[i][j]);
273 mesh_structure::clear();
275 gtab.clear(); trans_exists.clear();
276 cvf_sets.clear(); valid_cvf_sets.clear();
283 size_type ipt[2]; ipt[0] = a; ipt[1] = b;
284 return add_convex(bgeot::simplex_geotrans(1, 1), &(ipt[0]));
289 size_type ipt[3]; ipt[0] = a; ipt[1] = b; ipt[2] = c;
294 (
const base_node &p1,
const base_node &p2,
const base_node &p3)
295 {
return add_triangle(add_point(p1), add_point(p2), add_point(p3)); }
299 size_type ipt[4]; ipt[0] = a; ipt[1] = b; ipt[2] = c; ipt[3] = d;
306 return add_convex(bgeot::pyramid_QK_geotrans(1), &(ipt[0]));
310 (
const base_node &p1,
const base_node &p2,
311 const base_node &p3,
const base_node &p4) {
313 add_point(p3), add_point(p4));
321 "Please call the optimize_structure() function before "
322 "merging elements from another mesh");
324 "The provided mesh region should only contain convexes");
327 const dal::bit_vector &convexes = (rg ==
size_type(-1))
330 for (dal::bv_visitor cv(convexes); !cv.finished(); ++cv) {
335 GMM_ASSERT1(nb == rct.size(),
"Internal error");
336 std::vector<size_type> ind(nb);
342 base_node pt = msource.points()[old_pid];
344 if (new_pid < next_pid && new_pid >= nbpt) {
346 new_pid = pts.add_node(pt, -1.);
347 GMM_ASSERT1(new_pid == next_pid,
"Internal error");
349 old2new[old_pid] = new_pid;
358 static std::vector<size_type> ipt;
361 ipt.assign(ct.begin(), ct.end());
366 trans_exists.sup(ic);
368 if (Bank_info.get()) Bank_sup_convex_from_green(ic);
375 trans_exists.swap(i, j);
377 swap_convex_in_regions(i, j);
378 if (Bank_info.get()) Bank_swap_convex(i,j);
379 cvs_v_num[i] = cvs_v_num[j] = act_counter(); touch();
384 const base_node &pt)
const {
386 base_matrix G(dim(),pgt->nb_points());
387 vectors_to_base_matrix(G, points_of_convex(ic));
396 bgeot::pgeotrans_precomp pgp
397 = bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
399 vectors_to_base_matrix(G, points_of_convex(ic));
401 c(pgp,pgt->structure()->ind_points_of_face(f)[n], G);
405 base_small_vector mesh::mean_normal_of_face_of_convex(
size_type ic,
408 base_matrix G; vectors_to_base_matrix(G,points_of_convex(ic));
409 base_small_vector ptmean(dim());
410 size_type nbpt = pgt->structure()->nb_points_of_face(f);
412 gmm::add(pgt->geometric_nodes()[pgt->structure()->ind_points_of_face(f)[i]], ptmean);
413 ptmean /= scalar_type(nbpt);
416 n /= gmm::vect_norm2(n);
421 const base_node &pt)
const {
423 base_matrix G(dim(),pgt->nb_points());
424 vectors_to_base_matrix(G,points_of_convex(ic));
432 bgeot::pgeotrans_precomp pgp
433 = bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
434 base_matrix G(dim(),pgt->nb_points());
435 vectors_to_base_matrix(G,points_of_convex(ic));
437 c(pgp,pgt->structure()->ind_points_of_face(f)[n], G);
443 bgeot::vectors_to_base_matrix(G, points_of_convex(ic));
451 bgeot::vectors_to_base_matrix(G, points_of_convex(ic));
452 auto pgt = trans_of_convex(ic);
454 pgt = pgt_torus->get_original_transformation();
455 G.resize(pgt->dim(), G.ncols());
462 bgeot::vectors_to_base_matrix(G, points_of_convex(ic));
469 for (dal::bv_visitor cv(
convex_index()); !cv.finished(); ++cv) {
478 for (dal::bv_visitor cv(
convex_index()); !cv.finished(); ++cv) {
484 void mesh::set_name(
const std::string& name){name_=name;}
489 bgeot::basic_mesh::operator=(m);
490 for (
const auto &kv : m.cvf_sets) {
491 if (kv.second.get_parent_mesh() != 0)
492 cvf_sets[kv.first].set_parent_mesh(
this);
493 cvf_sets[kv.first] = kv.second;
495 valid_cvf_sets = m.valid_cvf_sets;
497 gmm::uint64_type d = act_counter();
498 for (dal::bv_visitor i(
convex_index()); !i.finished(); ++i)
500 Bank_info = std::unique_ptr<Bank_info_struct>();
501 if (m.Bank_info.get())
502 Bank_info = std::make_unique<Bank_info_struct>(*(m.Bank_info));
505 struct mesh_convex_structure_loc {
507 std::vector<size_type> pts;
511 gmm::stream_standard_locale sl(ist);
515 bool te =
false, please_get =
true;
519 ist.seekg(0);ist.clear();
520 bgeot::read_until(ist,
"BEGIN POINTS LIST");
525 if (!bgeot::casecmp(tmp,
"END"))
527 else if (!bgeot::casecmp(tmp,
"POINT")) {
529 if (!bgeot::casecmp(tmp,
"COUNT")) {
534 GMM_ASSERT1(!npt.is_in(ip),
535 "Two points with the same index. loading aborted.");
538 while (isdigit(tmp[0]) || tmp[0] ==
'-' || tmp[0] ==
'+'
543 for (
size_type i = 0; i < d; i++) v[i] = tmpv[i];
546 GMM_ASSERT1(!npt.is_in(ipl),
"Two points [#" << ip <<
" and #"
547 << ipl <<
"] with the same coords "<< v
548 <<
". loading aborted.");
552 }
else if (tmp.size()) {
553 GMM_ASSERT1(
false,
"Syntax error in file, at token '" << tmp
554 <<
"', pos=" << std::streamoff(ist.tellg()));
555 }
else if (ist.eof()) {
556 GMM_ASSERT1(
false,
"Unexpected end of stream while reading mesh");
565 if (!bgeot::read_until(ist,
"BEGIN MESH STRUCTURE DESCRIPTION"))
566 GMM_ASSERT1(
false,
"This seems not to be a mesh file");
570 if (!bgeot::casecmp(tmp,
"END"))
572 else if (!bgeot::casecmp(tmp,
"CONVEX")) {
575 if (!bgeot::casecmp(tmp,
"COUNT")) {
578 ic = gmm::abs(atoi(tmp.c_str()));
579 GMM_ASSERT1(!ncv.is_in(ic),
580 "Negative or repeated index, loading aborted.");
586 while (!isspace(c)) { tmp.push_back(c); ist.get(c); }
592 cv[ic].cstruct = pgt;
593 cv[ic].pts.resize(nb);
596 cv[ic].pts[i] = gmm::abs(atoi(tmp.c_str()));
600 else if (tmp.size()) {
601 GMM_ASSERT1(
false,
"Syntax error reading a mesh file "
602 " at pos " << std::streamoff(ist.tellg())
603 <<
"(expecting 'CONVEX' or 'END', found '"<< tmp <<
"')");
604 }
else if (ist.eof()) {
605 GMM_ASSERT1(
false,
"Unexpected end of stream "
606 <<
"(missing BEGIN MESH/END MESH ?)");
609 ist >> bgeot::skip(
"MESH STRUCTURE DESCRIPTION");
611 for (dal::bv_visitor ic(ncv); !ic.finished(); ++ic) {
620 if (bgeot::casecmp(tmp,
"BEGIN")==0) {
622 if (bgeot::casecmp(tmp,
"BOUNDARY")==0 ||
623 bgeot::casecmp(tmp,
"REGION")==0) {
628 if (bgeot::casecmp(tmp,
"END")!=0) {
633 if (!bgeot::casecmp(tmp,
"END"))
break;
634 int f = atoi(tmp.c_str());
640 if (!bgeot::casecmp(tmp,
"END"))
break;
655 std::ifstream o(name.c_str());
656 GMM_ASSERT1(o,
"Mesh file '" << name <<
"' does not exist");
662 void write_tab_to_file_(std::ostream &ost,
const ITER& b_,
const ITER& e)
663 {
for (ITER b(b_) ; b != e; ++b) ost <<
" " << *b; }
666 static void write_convex_to_file_(
const mesh &ms,
669 for ( ; b != e; ++b) {
671 ost <<
" CONVEX " << i <<
" \'"
674 write_tab_to_file_(ost, ms.ind_points_of_convex(i).begin(),
675 ms.ind_points_of_convex(i).end() );
680 template<
class ITER>
static void write_point_to_file_(std::ostream &ost,
682 {
for ( ; b != e; ++b) ost <<
" " << *b; ost <<
'\n'; }
686 gmm::stream_standard_locale sl(ost);
687 ost <<
'\n' <<
"BEGIN POINTS LIST" <<
'\n' <<
'\n';
688 ost <<
" POINT COUNT " << points().index().last_true()+1 <<
'\n';
691 ost <<
" POINT " << i;
692 write_point_to_file_(ost, pts[i].begin(), pts[i].end());
694 ost <<
'\n' <<
"END POINTS LIST" <<
'\n' <<
'\n' <<
'\n';
696 ost <<
'\n' <<
"BEGIN MESH STRUCTURE DESCRIPTION" <<
'\n' <<
'\n';
697 ost <<
" CONVEX COUNT " <<
convex_index().last_true()+1 <<
'\n';
698 write_convex_to_file_(*
this, ost, convex_tab.tas_begin(),
699 convex_tab.tas_end());
700 ost <<
'\n' <<
"END MESH STRUCTURE DESCRIPTION" <<
'\n';
702 for (dal::bv_visitor bnum(valid_cvf_sets); !bnum.finished(); ++bnum) {
703 ost <<
"BEGIN REGION " << bnum <<
"\n" <<
region(bnum) <<
"\n"
704 <<
"END REGION " << bnum <<
"\n";
709 std::ofstream o(name.c_str());
710 GMM_ASSERT1(o,
"impossible to write to file '" << name <<
"'");
711 o <<
"% GETFEM MESH FILE " <<
'\n';
712 o <<
"% GETFEM VERSION " << GETFEM_VERSION <<
'\n' <<
'\n' <<
'\n';
719 + pts.memsize() + (pts.index().last_true()+1)*dim()*
sizeof(scalar_type)
720 +
sizeof(
mesh) + trans_exists.memsize() + gtab.memsize()
721 + valid_cvf_sets.card()*
sizeof(
mesh_region) + valid_cvf_sets.memsize();
724 struct equilateral_to_GT_PK_grad_aux :
public std::vector<base_matrix> {};
725 static const base_matrix &equilateral_to_GT_PK_grad(dim_type N) {
726 std::vector<base_matrix>
728 if (N > pbm.size()) pbm.resize(N);
729 if (pbm[N-1].empty()) {
732 base_matrix G(N,N+1);
733 vectors_to_base_matrix
736 (pgt, pgt->pgeometric_nodes(), 0)->grad(0), Gr);
745 const base_matrix& G,
746 pintegration_method pi) {
749 static bgeot::pgeotrans_precomp pgp = 0;
750 static pintegration_method pim_old = 0;
751 papprox_integration pai = get_approx_im_or_fail(pi);
752 if (pgt_old != pgt || pim_old != pi) {
755 pgp = bgeot::geotrans_precomp
756 (pgt, pai->pintegration_points(), pi);
759 for (
size_type i = 0; i < pai->nb_points_on_convex(); ++i) {
761 area += pai->coeff(i) * gic.
J();
772 const base_matrix& G) {
774 static bgeot::pgeotrans_precomp pgp = 0;
775 if (pgt_old != pgt) {
777 pgp=bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
780 size_type n = (pgt->is_linear()) ? 1 : pgt->nb_points();
782 dim_type N = dim_type(G.nrows()), P = pgt->structure()->dim();
785 gmm::mult(G, pgp->grad(ip), K);
791 gmm::mult(base_matrix(K),equilateral_to_GT_PK_grad(P),K);
792 q = std::max(q, gmm::condition_number(K));
798 const base_matrix& G) {
800 static bgeot::pgeotrans_precomp pgp = 0;
801 if (pgt_old != pgt) {
803 pgp=bgeot::geotrans_precomp(pgt, pgt->pgeometric_nodes(), 0);
806 size_type n = (pgt->is_linear()) ? 1 : pgt->nb_points();
808 base_matrix K(pgp->grad(0).ncols(),G.nrows());
810 gmm::mult(gmm::transposed(pgp->grad(ip)), gmm::transposed(G), K);
811 scalar_type emax, emin; gmm::condition_number(K,emin,emax);
812 q = std::max(q, emax);
814 return q * sqrt(scalar_type(N)) / scalar_type(2);
822 convex_face_ct& flist) {
823 for (dal::bv_visitor ic(cvlst); !ic.finished(); ++ic) {
827 flist.push_back(convex_face(ic,f));
831 flist.push_back(convex_face(ic,
short_type(-1)));
837 const mesh_region &cvlst,
838 mesh_region &flist) {
839 cvlst.error_if_not_convexes();
840 for (mr_visitor i(cvlst); !i.finished(); ++i) {
841 if (m.structure_of_convex(i.cv())->dim() == m.dim()) {
842 for (
short_type f = 0; f < m.structure_of_convex(i.cv())->nb_faces();
844 size_type cv2 = m.neighbor_of_convex(i.cv(), f);
845 if (cv2 ==
size_type(-1) || !cvlst.is_in(cv2)) {
850 else flist.add(i.cv());
860 mr.error_if_not_convexes();
879 mr.error_if_not_convexes();
880 dal::bit_vector visited;
881 bgeot::mesh_structure::ind_set neighbors;
886 bool neighbor_visited =
false;
889 for (
size_type j = 0; j < neighbors.size(); ++j)
890 if (visited.is_in(neighbors[j]))
891 { neighbor_visited =
true;
break; }
893 if (!neighbor_visited) {
896 if (cv2 !=
size_type(-1) && mr.is_in(cv2)) mrr.add(cv1,f);
904 if (!(visited.is_in(cv1))) {
909 for (
size_type j = 0; j < neighbors.size(); ++j) {
910 if (visited.is_in(neighbors[j])) { ok =
false;
break; }
911 if (mr.is_in(neighbors[j])) { ok =
true; }
913 if (ok) { mrr.add(cv1,f); }
923 const base_small_vector &V,
926 scalar_type threshold = gmm::vect_norm2(V)*cos(angle);
929 base_node un = m.mean_normal_of_face_of_convex(i.cv(), i.f());
930 if (gmm::vect_sp(V, un) - threshold >= -1E-8)
931 mrr.add(i.cv(), i.f());
937 const base_node &pt1,
const base_node &pt2) {
940 GMM_ASSERT1(pt1.size() == N && pt2.size() == N,
"Wrong dimensions");
948 it != pt.end(); ++it) {
950 if (m.points()[*it][j] < pt1[j] || m.points()[*it][j] > pt2[j])
951 { is_in =
false;
break; }
954 if (is_in) mrr.add(i.cv(), i.f());
960 const base_node ¢er, scalar_type radius) {
963 GMM_ASSERT1(center.size() == N,
"Wrong dimensions");
971 it != pt.end(); ++it) {
972 scalar_type checked_radius = scalar_type(0.0);
974 checked_radius += pow(m.points()[*it][j] - center[j], 2);
975 checked_radius = std::sqrt(checked_radius);
976 if (checked_radius > radius) { is_in =
false;
break; }
978 if (is_in) mrr.add(i.cv(), i.f());
983 mesh_region select_convexes_in_box(
const mesh &m,
const mesh_region &mr,
984 const base_node &pt1,
const base_node &pt2) {
987 GMM_ASSERT1(pt1.size() == N && pt2.size() == N,
"Wrong dimensions");
990 bgeot::mesh_structure::ind_cv_ct pt = m.ind_points_of_convex(i.cv());
993 for (bgeot::mesh_structure::ind_cv_ct::iterator it = pt.begin();
994 it != pt.end(); ++it) {
996 if (m.points()[*it][j] < pt1[j] || m.points()[*it][j] > pt2[j])
997 { is_in =
false;
break; }
1000 if (is_in) mrr.add(i.cv());
1006 dim_type dim = in.dim();
1007 base_node pt(dim+1);
1009 size_type nbpt = in.points().index().last()+1;
1010 GMM_ASSERT1(nbpt == in.points().index().card(),
1011 "please call the optimize_structure() method before using "
1012 "the mesh as a base for prismatic mesh");
1013 size_type nb_layers_total = nb_layers * degree;
1014 for (
const base_node &inpt : in.points()) {
1015 std::copy(inpt.begin(), inpt.end(), pt.begin());
1017 for (
size_type j = 0; j <= nb_layers_total;
1018 ++j, pt[dim] += scalar_type(1) / scalar_type(nb_layers_total))
1022 std::vector<size_type> tab;
1023 for (dal::bv_visitor cv(in.
convex_index()); !cv.finished(); ++cv) {
1025 tab.resize((degree+1)*nbp);
1026 for (
size_type j = 0; j < nb_layers; ++j) {
1031 bgeot::product_geotrans(in.trans_of_convex(cv),
1032 bgeot::simplex_geotrans(1,degree));
1051 bool mesh::edge::operator <(
const edge &e)
const {
1052 if (i0 < e.i0)
return true;
1053 if (i0 > e.i0)
return false;
1054 if (i1 < e.i1)
return true;
1055 if (i1 > e.i1)
return false;
1056 if (i2 < e.i2)
return true;
1060 void mesh::Bank_sup_convex_from_green(
size_type i) {
1061 if (Bank_info.get() && Bank_info->is_green_simplex.is_in(i)) {
1062 size_type igs = Bank_info->num_green_simplex[i];
1063 green_simplex &gs = Bank_info->green_simplices[igs];
1064 for (
size_type j = 0; j < gs.sub_simplices.size(); ++j) {
1065 Bank_info->num_green_simplex.erase(gs.sub_simplices[j]);
1066 Bank_info->is_green_simplex.sup(gs.sub_simplices[j]);
1068 Bank_info->green_simplices.sup(igs);
1073 if (Bank_info.get()) {
1074 Bank_info->is_green_simplex.swap(i, j);
1075 std::map<size_type, size_type>::iterator
1076 iti = Bank_info->num_green_simplex.find(i);
1077 std::map<size_type, size_type>::iterator
1078 ite = Bank_info->num_green_simplex.end();
1079 std::map<size_type, size_type>::iterator
1080 itj = Bank_info->num_green_simplex.find(j);
1083 { numi = iti->second; Bank_info->num_green_simplex.erase(i); }
1085 { numj = itj->second; Bank_info->num_green_simplex.erase(j); }
1087 Bank_info->num_green_simplex[j] = numi;
1088 green_simplex &gs = Bank_info->green_simplices[numi];
1089 for (
size_type k = 0; k < gs.sub_simplices.size(); ++k)
1090 if (gs.sub_simplices[k] == i) gs.sub_simplices[k] = j;
1091 else if (gs.sub_simplices[k] == j) gs.sub_simplices[k] = i;
1094 Bank_info->num_green_simplex[i] = numj;
1095 if (iti == ite || numi != numj) {
1096 green_simplex &gs = Bank_info->green_simplices[numj];
1097 for (
size_type k = 0; k < gs.sub_simplices.size(); ++k)
1098 if (gs.sub_simplices[k] == i) gs.sub_simplices[k] = j;
1099 else if (gs.sub_simplices[k] == j) gs.sub_simplices[k] = i;
1105 void mesh::Bank_build_first_mesh(mesh &m,
size_type n) {
1108 for (
size_type ip = 0; ip < pcr->nb_points(); ++ip)
1109 m.add_point(pcr->points()[ip]);
1111 size_type nbc = bgeot::refinement_simplexe_tab(n, &tab);
1112 for (
size_type ic = 0; ic < nbc; ++ic, tab+=(n+1))
1113 m.add_simplex(dim_type(n), tab);
1116 struct mesh_cache_for_Bank_basic_refine_convex :
public mesh {};
1118 void mesh::Bank_basic_refine_convex(
size_type i) {
1120 size_type n = pgt->basic_structure()->dim();
1126 static bgeot::pstored_point_tab pspt = 0;
1127 static bgeot::pgeotrans_precomp pgp = 0;
1128 static std::vector<size_type> ipt, ipt2, icl;
1133 Bank_build_first_mesh(mesh1, n);
1136 ipt.resize(pgt->nb_points());
1137 for (
size_type ic = 0; ic < mesh1.nb_convex(); ++ic) {
1138 assert(mesh1.convex_index().is_in(ic));
1140 for (
size_type ip = 0; ip < pgt->nb_points(); ++ip)
1142 mesh2.add_point(pgt2->transform(pgt->geometric_nodes()[ip],
1143 mesh1.points_of_convex(ic)));
1144 mesh2.add_convex(pgt, &ipt[0]);
1148 pspt = bgeot::store_point_tab(mesh2.points());
1149 pgp = bgeot::geotrans_precomp(pgt, pspt, 0);
1152 base_node pt(dim());
1153 ipt.resize(pspt->size());
1154 for (
size_type ip = 0; ip < pspt->size(); ++ip) {
1155 pgp->transform(points_of_convex(i), ip, pt);
1156 ipt[ip] = add_point(pt);
1159 ipt2.resize(pgt->nb_points()); icl.resize(0);
1160 for (
size_type ic = 0; ic < mesh2.nb_convex(); ++ic) {
1161 for (
size_type j = 0; j < pgt->nb_points(); ++j)
1162 ipt2[j] = ipt[mesh2.ind_points_of_convex(ic)[j]];
1163 icl.push_back(
add_convex(pgt, ipt2.begin()));
1165 handle_region_refinement(i, icl,
true);
1170 std::vector<size_type> &ipt) {
1173 size_type cv = points_tab[i1][k], found = 0;
1174 const std::vector<size_type> &loc_ind = trans_of_convex(cv)->vertices();
1175 for (
size_type i = 0; i < loc_ind.size(); ++i) {
1176 size_type ipp = convex_tab[cv].pts[loc_ind[i]];
1177 if (ipp == i1) ++found;
1178 if (ipp == i2) ++found;
1180 GMM_ASSERT1(found <= 2,
"Invalid convex with repeated nodes ");
1181 if (found == 2) ipt.push_back(cv);
1185 bool mesh::Bank_is_convex_having_points(
size_type cv,
1186 const std::vector<size_type> &ipt) {
1188 const std::vector<size_type> &loc_ind = trans_of_convex(cv)->vertices();
1189 for (
size_type i = 0; i < loc_ind.size(); ++i)
1190 if (std::find(ipt.begin(), ipt.end(),
1191 convex_tab[cv].pts[loc_ind[i]]) != ipt.end()) ++found;
1192 return (found >= ipt.size());
1195 void mesh::Bank_refine_normal_convex(
size_type i) {
1198 "Sorry, refinement is only working with simplices.");
1200 const std::vector<size_type> &loc_ind = pgt->vertices();
1201 for (
size_type ip1 = 0; ip1 < loc_ind.size(); ++ip1)
1202 for (
size_type ip2 = ip1+1; ip2 < loc_ind.size(); ++ip2)
1205 Bank_basic_refine_convex(i);
1209 dal::bit_vector &b,
bool ref) {
1210 if (Bank_info->is_green_simplex[i]) {
1211 size_type igs = Bank_info->num_green_simplex[i];
1212 green_simplex &gs = Bank_info->green_simplices[igs];
1215 handle_region_refinement(icc, gs.sub_simplices,
false);
1216 for (
size_type ic = 0; ic < gs.sub_simplices.size(); ++ic) {
1218 b.sup(gs.sub_simplices[ic]);
1221 for (
size_type ip = 0; ip < gs.ipt_loc.size(); ++ip)
1222 for (
size_type jp = ip+1; jp < gs.ipt_loc.size(); ++jp)
1223 Bank_info->edges.insert
1226 Bank_sup_convex_from_green(i);
1227 if (ref) { Bank_refine_normal_convex(icc);
return size_type(-1); }
1230 else if (ref) Bank_refine_normal_convex(i);
1235 struct mesh_cache_for_Bank_build_green_simplexes :
public mesh {};
1237 void mesh::Bank_build_green_simplexes(
size_type ic,
1238 std::vector<size_type> &ipt) {
1239 GMM_ASSERT1(
convex_index().is_in(ic),
"Internal error");
1240 size_type igs = Bank_info->green_simplices.add(green_simplex());
1241 green_simplex &gs(Bank_info->green_simplices[igs]);
1243 ref_mesh_pt_ct ptab = points_of_convex(ic);
1244 pt_tab.assign(ptab.begin(), ptab.end());
1251 static bgeot::pstored_point_tab pspt1 = 0;
1256 Bank_build_first_mesh(mesh1, d);
1257 pspt1 = bgeot::store_point_tab(mesh1.points());
1260 const std::vector<size_type> &loc_ind = pgt->vertices();
1263 gs.ipt_loc.resize(ipt.size());
1264 std::vector<size_type> ipt_other;
1266 for (
size_type ip = 0; ip < loc_ind.size(); ++ip) {
1268 for (
size_type i = 0; i < ipt.size(); ++i)
1269 if (ct[loc_ind[ip]] == ipt[i])
1270 { gs.ipt_loc[i] = ip; found =
true; ++nb_found;
break; }
1271 if (!found) ipt_other.push_back(ip);
1273 assert(nb_found == ipt.size());
1276 for (
size_type ip = 0; ip < loc_ind.size(); ++ip)
1277 mesh2.add_point(pgt->geometric_nodes()[loc_ind[ip]]);
1278 size_type ic1 = mesh2.add_simplex(dim_type(d), gs.ipt_loc.begin());
1280 for (
size_type i = 0; i < ipt.size(); ++i)
1281 gs.ipt_loc[i] = loc_ind[gs.ipt_loc[i]];
1283 bgeot::pgeotrans_precomp pgp = bgeot::geotrans_precomp(pgt1, pspt1, 0);
1285 std::vector<size_type> ipt1(pspt1->size());
1286 base_node pt(dim());
1287 for (
size_type i = 0; i < pspt1->size(); ++i) {
1288 pgp->transform(mesh2.points_of_convex(ic1), i, pt);
1289 ipt1[i] = mesh2.add_point(pt);
1291 mesh2.sup_convex(ic1);
1293 std::vector<size_type> ipt2(n+1);
1294 for (
size_type i = 0; i < mesh1.nb_convex(); ++i) {
1296 ipt2[j] = ipt1[mesh1.ind_points_of_convex(i)[j]];
1298 ipt2[j] = ipt_other[j-d-1];
1299 mesh2.add_simplex(dim_type(n), ipt2.begin());
1303 ipt1.resize(pgt->nb_points());
1304 for (dal::bv_visitor i(mesh2.convex_index()); !i.finished(); ++i) {
1306 for (
size_type ip = 0; ip < pgt->nb_points(); ++ip)
1308 mesh3.add_point(pgt2->transform(pgt->geometric_nodes()[ip],
1309 mesh2.points_of_convex(i)));
1310 mesh3.add_convex(pgt, ipt1.begin());
1314 bgeot::pstored_point_tab pspt3 = bgeot::store_point_tab(mesh3.points());
1315 pgp = bgeot::geotrans_precomp(pgt, pspt3, 0);
1317 ipt1.resize(pspt3->size());
1318 for (
size_type ip = 0; ip < pspt3->size(); ++ip) {
1319 pgp->transform(points_of_convex(ic), ip, pt);
1320 ipt1[ip] = add_point(pt);
1324 ipt2.resize(pgt->nb_points());
1325 for (
size_type icc = 0; icc < mesh3.nb_convex(); ++icc) {
1326 for (
size_type j = 0; j < pgt->nb_points(); ++j)
1327 ipt2[j] = ipt1[mesh3.ind_points_of_convex(icc)[j]];
1329 gs.sub_simplices.push_back(i);
1330 Bank_info->is_green_simplex.add(i);
1331 Bank_info->num_green_simplex[i] = igs;
1334 for (
size_type ip1 = 0; ip1 < ipt.size(); ++ip1)
1335 for (
size_type ip2 = ip1+1; ip2 < ipt.size(); ++ip2)
1336 Bank_info->edges.insert(edge(ipt[ip1], ipt[ip2]));
1338 handle_region_refinement(ic, gs.sub_simplices,
true);
1343 if (!(Bank_info.get())) Bank_info = std::make_unique<Bank_info_struct>();
1346 if (b.card() == 0)
return;
1348 Bank_info->edges.clear();
1349 while (b.card() > 0)
1350 Bank_test_and_refine_convex(b.take_first(), b);
1352 std::vector<size_type> ipt;
1353 edge_set marked_convexes;
1354 while (Bank_info->edges.size()) {
1355 marked_convexes.clear();
1357 edge_set::const_iterator it = Bank_info->edges.begin();
1358 edge_set::const_iterator ite = Bank_info->edges.end(), it2=it;
1359 assert(!Bank_info->edges.empty());
1360 for (; it != ite; it = it2) {
1361 if (it2 != ite) ++it2;
1362 Bank_convex_with_edge(it->i1, it->i2, ipt);
1363 if (ipt.size() == 0) ;
1364 else for (
size_type ic = 0; ic < ipt.size(); ++ic)
1365 marked_convexes.insert(edge(ipt[ic], it->i1, it->i2));
1368 it = marked_convexes.begin(); ite = marked_convexes.end();
1369 if (it == ite)
break;
1374 while (it != ite && it->i0 == ic) {
1375 bool found1 =
false, found2 =
false;
1376 for (
size_type j = 0; j < ipt.size(); ++j) {
1377 if (ipt[j] == it->i1) found1 =
true;
1378 if (ipt[j] == it->i2) found2 =
true;
1380 if (!found1) ipt.push_back(it->i1);
1381 if (!found2) ipt.push_back(it->i2);
1386 Bank_test_and_refine_convex(ic, b);
1387 else if (Bank_info->is_green_simplex[ic]) {
1388 size_type icc = Bank_test_and_refine_convex(ic, b,
false);
1389 if (!Bank_is_convex_having_points(icc, ipt)) {
1390 Bank_test_and_refine_convex(icc, b);
1393 else Bank_build_green_simplexes(ic, ipt);
1397 Bank_info->edges.clear();
1400 struct dummy_mesh_ {
1402 dummy_mesh_() : m() {}
1405 const mesh &dummy_mesh()
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.
iterator begin(void)
Iterator on the first element.
size_type size(void) const
Number of allocated elements.
void clear(void)
Clear and desallocate all the elements.
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).
mesh(const std::string name="")
Constructor.
virtual scalar_type convex_radius_estimate(size_type ic) const
Return an estimate of the convex largest dimension.
void sup_convex_from_regions(size_type cv)
Remove all references to a convex from all regions stored in the mesh.
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.
void sup_convex(size_type ic, bool sup_points=false)
Delete the convex of index ic from the mesh.
const dal::bit_vector & points_index() const
Return the points index.
size_type nb_points() const
Give the number of geometrical nodes in the mesh.
void transformation(const base_matrix &)
apply the given matrix transformation to each mesh node.
scalar_type convex_quality_estimate(size_type ic) const
Return an estimate of the convex quality (0 <= Q <= 1).
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.
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.
scalar_type convex_area_estimate(size_type ic, size_type degree=2) const
Return an estimate of the convex area.
void write_to_file(const std::string &name) const
Write the mesh to a file.
void bounding_box(base_node &Pmin, base_node &Pmax) const
Return the bounding box [Pmin - Pmax] of the mesh.
void swap_convex(size_type i, size_type j)
Swap the indexes of the convex of indexes i and j in the whole structure.
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.
size_type add_segment(size_type a, size_type b)
Add a segment to the mesh, given the point id of its vertices.
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.
scalar_type minimal_convex_radius_estimate() const
Return an estimate of the convex smallest dimension.
const mesh_region region(size_type id) const
Return the region of index 'id'.
size_type add_convex(bgeot::pgeometric_trans pgt, ITER ipts)
Add a convex to the mesh.
void read_from_file(const std::string &name)
Load the mesh from a file.
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.
void sup_point(size_type i)
Delete the point of index i from the mesh if it is not linked to a convex.
void swap_points(size_type i, size_type j)
Swap the indexes of points of index i and j in the whole structure.
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.
void copy_from(const mesh &m)
Clone a mesh.
size_type add_simplex(dim_type di, ITER ipts)
Add a simplex to the mesh, given its dimension and point numbers.
scalar_type maximal_convex_radius_estimate() const
Return an estimate of the convex largest dimension.
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.
void clear()
Erase the mesh.
void translation(const base_small_vector &)
Apply the given translation to each mesh node.
indexed array reference (given a container X, and a set of indexes I, this class provides a pseudo-co...
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)
*/
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.
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...
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...
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...
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.
mesh_region APIDECL select_faces_in_ball(const mesh &m, const mesh_region &mr, const base_node ¢er, scalar_type radius)
Select in the region mr the faces of the mesh m lying entirely in the ball delimated by pt1 and radiu...
scalar_type APIDECL convex_area_estimate(bgeot::pgeometric_trans pgt, const base_matrix &pts, pintegration_method pim)
rough estimate of the convex area.
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.
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.
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.
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.
gmm::uint16_type short_type
used as the common short type integer in the library
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...
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
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.
iterator over a gmm::tab_ref_index_ref<ITER,ITER_INDEX>