branch: cleanup-mesh-import commit 69884dd486e8e68d7bcdb502f2843c5131c5a91e Author: Konstantinos Poulios <logar...@gmail.com> AuthorDate: Wed Aug 2 23:14:40 2023 +0200
Change default treatment of overlapping nodes and cleanup of mesh import --- src/getfem/getfem_import.h | 62 ++++--- src/getfem_import.cc | 439 ++++++++++++++++++++++----------------------- 2 files changed, 248 insertions(+), 253 deletions(-) diff --git a/src/getfem/getfem_import.h b/src/getfem/getfem_import.h index 10210207..cad32fd0 100644 --- a/src/getfem/getfem_import.h +++ b/src/getfem/getfem_import.h @@ -76,9 +76,9 @@ namespace getfem { parametrization of the mesh in Gmsh .geo file must assign a different number to each region, the problem exists because in Gmsh can coexist, for example, "Physical Surface (200)" and - "Physical Line (200)", as they are different "types of regions" - in Gmsh, that which does not occur in GetFEM since there is - only one "type of region". + "Physical Line (200)", as they are different types of regions + in Gmsh, which cannot occur in GetFEM since there is only one + type of region. - "cdb" for meshes generated by ANSYS (in blocked format). @@ -103,11 +103,19 @@ namespace getfem { - "am_fmt" for 2D meshes from emc2 [http://pauillac.inria.fr/cdrom/prog/unix/emc2/eng.htm] + + For all mesh formats, overlapping nodes are preserved by default. + In order to merge overlapping nodes during the import, add + ":merge_overlapping_nodes" to the format specifier. + For example: + "gmsh:merge_overlapping_nodes" + "cdb:merge_overlapping_nodes" + "cdb:3:merge_overlapping_nodes" */ void import_mesh(const std::string& filename, const std::string& format, - mesh& m); + mesh& m); void import_mesh(std::istream& f, const std::string& format, - mesh& m); + mesh& m); void import_mesh(const std::string& filename, mesh& m); /** Import a mesh file in format generated by Gmsh. @@ -140,38 +148,42 @@ namespace getfem { be tested. */ void import_mesh_gmsh(const std::string& filename, mesh& m, - std::map<std::string, size_type> ®ion_map, + bool add_all_element_type = false, + std::set<size_type> *lower_dim_convex_rg = nullptr, + std::map<std::string, size_type> *region_map = nullptr, bool remove_last_dimension = true, - std::map<size_type, std::set<size_type>> *nodal_map = NULL, - bool remove_duplicated_nodes = true); - - void import_mesh_gmsh(std::istream& f, mesh& m, + std::map<size_type, std::set<size_type>> *nodal_map = nullptr, + bool merge_overlapping_nodes = false); + void import_mesh_gmsh(const std::string& filename, mesh& m, std::map<std::string, size_type> ®ion_map, bool remove_last_dimension = true, - std::map<size_type, std::set<size_type>> *nodal_map = NULL, - bool remove_duplicated_nodes = true); - - void import_mesh_gmsh(const std::string& filename, mesh& m, + std::map<size_type, std::set<size_type>> *nodal_map = nullptr, + bool merge_overlapping_nodes = false) { + import_mesh_gmsh(filename, m, false, nullptr, ®ion_map, + remove_last_dimension, nodal_map, merge_overlapping_nodes); + } + void import_mesh_gmsh(std::istream& f, mesh& m, bool add_all_element_type = false, - std::set<size_type> *lower_dim_convex_rg = NULL, - std::map<std::string, size_type> *region_map = NULL, + std::set<size_type> *lower_dim_convex_rg = nullptr, + std::map<std::string, size_type> *region_map = nullptr, bool remove_last_dimension = true, - std::map<size_type, std::set<size_type>> *nodal_map = NULL, - bool remove_duplicated_nodes = true); - + std::map<size_type, std::set<size_type>> *nodal_map = nullptr, + bool merge_overlapping_nodes = false); void import_mesh_gmsh(std::istream& f, mesh& m, - bool add_all_element_type = false, - std::set<size_type> *lower_dim_convex_rg = NULL, - std::map<std::string, size_type> *region_map = NULL, + std::map<std::string, size_type> ®ion_map, bool remove_last_dimension = true, - std::map<size_type, std::set<size_type>> *nodal_map = NULL, - bool remove_duplicated_nodes = true); + std::map<size_type, std::set<size_type>> *nodal_map = nullptr, + bool merge_overlapping_nodes = false) { + import_gmsh_mesh(f, m, false, nullptr, ®ion_map, + remove_last_dimension, nodal_map, merge_overlapping_nodes); + } /** for gmsh and gid meshes, the mesh nodes are always 3D, so for a 2D mesh the z-component of nodes should be removed */ void maybe_remove_last_dimension(mesh &msh); /** for gmsh meshes, create table linking region name to region_id. */ - std::map<std::string, size_type> read_region_names_from_gmsh_mesh_file(std::istream& f); + std::map<std::string, size_type> + read_region_names_from_gmsh_mesh_file(std::istream& f); } #endif /* GETFEM_IMPORT_H__ */ diff --git a/src/getfem_import.cc b/src/getfem_import.cc index 7056697c..13cf1414 100644 --- a/src/getfem_import.cc +++ b/src/getfem_import.cc @@ -1,6 +1,7 @@ /*=========================================================================== - Copyright (C) 2000-2020 Julien Pommier + Copyright (C) 2000-2023 Julien Pommier + 2012-2023 Konstantinos Poulios This file is a part of GetFEM @@ -29,6 +30,58 @@ namespace getfem { + // Main mesh import function, dispatches between native GetFEM mesh + // file format and all other formats + void import_mesh(const std::string& filename, mesh& m) { + size_type pos = filename.find_last_of(":"); + if (pos != std::string::npos) + getfem::import_mesh(filename.substr(pos+1), filename.substr(0,pos), m); + else + m.read_from_file(filename); + } + + // Deals with all other options than native GetFEM mesh file format + // Dispatches between structured meshes to be generated by GetFEM + // and all supported file formats + void import_mesh(const std::string& filename, const std::string& format, + mesh& m) { + m.clear(); + try { + if (bgeot::casecmp(format,"structured")==0) + regular_mesh(m, filename); + else if (bgeot::casecmp(format,"structured_ball")==0) + regular_ball_mesh(m, filename); + else if (bgeot::casecmp(format,"structured_ball_shell")==0) + regular_ball_shell_mesh(m, filename); + else { + std::ifstream f(filename.c_str()); + GMM_ASSERT1(f.good(), "can't open file " << filename); + /* throw exceptions when an error occurs */ + f.exceptions(std::ifstream::badbit | std::ifstream::failbit); + import_mesh(f, format, m); // main dispatcher between all supported + f.close(); // file formats is in this function + } + } + catch (std::logic_error& exc) { + m.clear(); + throw exc; + } + catch (std::ios_base::failure& exc) { + m.clear(); + GMM_ASSERT1(false, "error while importing " << format + << " mesh file \"" << filename << "\" : " << exc.what()); + } + catch (std::runtime_error& exc) { + m.clear(); + throw exc; + } + } + + + + // Specific mesh file format implementations + + /* mesh file from gmsh [http://www.geuz.org/gmsh/]*/ struct gmsh_cv_info { @@ -176,8 +229,8 @@ namespace getfem { } }; - std::map<std::string, size_type> read_region_names_from_gmsh_mesh_file(std::istream& f) - { + std::map<std::string, size_type> + read_region_names_from_gmsh_mesh_file(std::istream& f) { std::map<std::string, size_type> region_map; bgeot::read_until(f, "$PhysicalNames"); size_type nb_regions; @@ -200,6 +253,22 @@ namespace getfem { return region_map; } + void maybe_remove_last_dimension(mesh &m) { + unsigned N = m.dim(); + if (N >= 1) { + bool is_flat = true; + for (const base_node &pt : m.points()) + if (pt[N-1] != 0) + is_flat = false; + if (is_flat) { + base_matrix M(N-1,N); + for (unsigned i=0; i < N-1; ++i) + M(i,i) = 1; + m.transformation(M); + } + } + } + /* Format version 1 [for gmsh version < 2.0]. structure: $NOD list_of_nodes $ENDNOD $ELT list_of_elt $ENDELT @@ -220,31 +289,18 @@ namespace getfem { for gmsh and gid meshes, the mesh nodes are always 3D, so for a 2D mesh if remove_last_dimension == true the z-component of nodes will be removed */ - static void import_gmsh_mesh_file - (std::istream& f, mesh& m, int deprecate=0, - std::map<std::string, size_type> *region_map=NULL, - std::set<size_type> *lower_dim_convex_rg=NULL, - bool add_all_element_type = false, - bool remove_last_dimension = true, - std::map<size_type, std::set<size_type>> *nodal_map = NULL, - bool remove_duplicated_nodes = true) { + static void import_gmsh_mesh(std::istream& f, mesh& m, + bool add_all_element_type, + std::set<size_type> *lower_dim_convex_rg, + std::map<std::string, size_type> *region_map, + bool remove_last_dimension, + std::map<size_type, std::set<size_type>> *nodal_map, + bool merge_overlapping_nodes) + { gmm::stream_standard_locale sl(f); // /* print general warning */ // GMM_WARNING3(" All regions must have different number!"); - /* print deprecate warning */ - if (deprecate!=0){ - GMM_WARNING4("" << endl - << " deprecate: " << endl - << " static void" << endl - << " import_gmsh_mesh_file(std::istream& f," - << " mesh& , int version)" << endl - << " replace with:" << endl - << " static void" << endl - << " import_gmsh_mesh_file(std::istream& f," - << " mesh&)"); - } - /* read the version */ double version; std::string header; @@ -257,7 +313,7 @@ namespace getfem { GMM_ASSERT1(false, "can't read Gmsh format: " << header); /* read the region names */ - if (region_map != NULL) { + if (region_map != nullptr) { if (version >= 2.) { *region_map = read_region_names_from_gmsh_mesh_file(f); } @@ -288,18 +344,18 @@ namespace getfem { inds.resize(nb_node); if (version >= 4.05) { - for (size_type node_cnt=0; node_cnt < nb_node; ++node_cnt) - f >> inds[node_cnt]; + for (size_type node_cnt=0; node_cnt < nb_node; ++node_cnt) + f >> inds[node_cnt]; } for (size_type node_cnt=0; node_cnt < nb_node; ++node_cnt) { size_type node_id; base_node n{0,0,0}; - if (version < 4.05) f >> node_id; else node_id = inds[node_cnt]; + if (version < 4.05) f >> node_id; else node_id = inds[node_cnt]; - f >> n[0] >> n[1] >> n[2]; + f >> n[0] >> n[1] >> n[2]; msh_node_2_getfem_node[node_id] - = m.add_point(n, remove_duplicated_nodes ? 0. : -1.); + = m.add_point(n, merge_overlapping_nodes ? 0. : -1.); } } @@ -334,7 +390,8 @@ namespace getfem { if (reg.is_in(region)) { GMM_WARNING2("Two regions share the same number, " "the region numbering is modified"); - while (reg.is_in(region)) region += 5; + while (reg.is_in(region)) + region += 5; } reg.add(region); } @@ -569,73 +626,101 @@ namespace getfem { size_type ic = m.add_convex(ci.pgt, ci.nodes.begin()); cvok = true; m.region(ci.region).add(ic); - - //convexes with lower dimensions - } - else { + } else { //convexes with lower dimensions //convex that lies within the regions of lower_dim_convex_rg //is imported explicitly as a convex. - if (lower_dim_convex_rg != NULL && + if (lower_dim_convex_rg != nullptr && lower_dim_convex_rg->find(ci.region) != lower_dim_convex_rg->end() && !is_node) { - size_type ic = m.add_convex(ci.pgt, ci.nodes.begin()); - cvok = true; m.region(ci.region).add(ic); - } - //find if the convex is part of a face of higher dimension convex - else{ + size_type ic = m.add_convex(ci.pgt, ci.nodes.begin()); + cvok = true; + m.region(ci.region).add(ic); + } else { //find if the convex is part of a face of higher dimension convex bgeot::mesh_structure::ind_cv_ct ct=m.convex_to_point(ci.nodes[0]); for (bgeot::mesh_structure::ind_cv_ct::const_iterator - it = ct.begin(); it != ct.end(); ++it) { - if (m.structure_of_convex(*it)->dim() == ci_dim + 1) { + it = ct.begin(); it != ct.end(); ++it) + if (m.structure_of_convex(*it)->dim() == ci_dim + 1) for (short_type face=0; - face < m.structure_of_convex(*it)->nb_faces(); ++face) { + face < m.structure_of_convex(*it)->nb_faces(); ++face) if (m.is_convex_face_having_points(*it, face, short_type(ci.nodes.size()), - ci.nodes.begin())) { + ci.nodes.begin())) + { m.region(ci.region).add(*it,face); cvok = true; } - } - } - } - if (is_node && (nodal_map != NULL)) { - for (auto i : ci.nodes) (*nodal_map)[ci.region].insert(i); - } - // if the convex is not part of the face of others - if (!cvok) { - if (is_node) { - if (nodal_map == NULL){ + if (is_node && (nodal_map != nullptr)) + for (auto i : ci.nodes) + (*nodal_map)[ci.region].insert(i); + if (!cvok) { // if the convex is not part of the face of others + if (is_node) + if (nodal_map == nullptr) GMM_WARNING2("gmsh import ignored a node id: " << ci.id << " region :" << ci.region << " point is not added explicitly as an element."); - } - } else if (add_all_element_type) { size_type ic = m.add_convex(ci.pgt, ci.nodes.begin()); m.region(ci.region).add(ic); cvok = true; - } else { + } else GMM_WARNING2("gmsh import ignored an element of type " << bgeot::name_of_geometric_trans(ci.pgt) << " as it does not belong to the face of another element"); - } } } } } } - if (remove_last_dimension) maybe_remove_last_dimension(m); + if (remove_last_dimension) + maybe_remove_last_dimension(m); + } + + // Just opens the file with the given filename and passes the ifstream + void import_mesh_gmsh(const std::string& filename, mesh& m, + bool add_all_element_type, + std::set<size_type> *lower_dim_convex_rg, + std::map<std::string, size_type> *region_map, + bool remove_last_dimension, + std::map<size_type, std::set<size_type>> *nodal_map, + bool merge_overlapping_nodes) + { + m.clear(); + try { + std::ifstream f(filename.c_str()); + GMM_ASSERT1(f.good(), "can't open file " << filename); + /* throw exceptions when an error occurs */ + f.exceptions(std::ifstream::badbit | std::ifstream::failbit); + import_gmsh_mesh(f, m, add_all_element_type, lower_dim_convex_rg, region_map, + remove_last_dimension, nodal_map, merge_overlapping_nodes); + f.close(); + } + catch (std::logic_error& exc) { + m.clear(); + throw exc; + } + catch (std::ios_base::failure& exc) { + m.clear(); + GMM_ASSERT1(false, "error while importing " << "gmsh" + << " mesh file \"" << filename << "\" : " << exc.what()); + } + catch (std::runtime_error& exc) { + m.clear(); + throw exc; + } } + + /* mesh file from GiD [http://gid.cimne.upc.es/] supports linear and quadratic elements (quadrilaterals, use 9(or 27)-noded elements) */ - static void import_gid_mesh_file(std::istream& f, mesh& m) { + static void import_gid_mesh(std::istream& f, mesh& m, + bool merge_overlapping_nodes=false) { gmm::stream_standard_locale sl(f); /* read the node list */ size_type dim; - enum { LIN,TRI,QUAD,TETR, PRISM, HEX,BADELTYPE } eltype=BADELTYPE; + enum { LIN,TRI,QUAD,TETR, PRISM, HEX, BADELTYPE } eltype=BADELTYPE; size_type nnode = 0; std::map<size_type, size_type> msh_node_2_getfem_node; std::vector<size_type> cv_nodes, getfem_cv_nodes; @@ -691,12 +776,13 @@ namespace getfem { for (dal::bv_visitor ip(gid_nodes_used); !ip.finished(); ++ip) { base_node n(dim2); for (size_type j=0, cnt=0; j < dim; ++j) if (!direction_useless[j]) n[cnt++]=gid_nodes[ip][j]; - msh_node_2_getfem_node[ip] = m.add_point(n); + msh_node_2_getfem_node[ip] + = m.add_point(n, merge_overlapping_nodes ? 0. : -1.); } } bgeot::read_until(f, "ELEMENTS"); - bgeot::pgeometric_trans pgt = NULL; + bgeot::pgeometric_trans pgt = nullptr; std::vector<size_type> order(nnode); // ordre de GiD cf http://gid.cimne.upc.es/support/gid_11.subst#SEC160 for (size_type i=0; i < nnode; ++i) order[i]=i; //cerr << "reading elements " << std::streamoff(f.tellg()) << "\n"; @@ -747,7 +833,7 @@ namespace getfem { } break; default: GMM_ASSERT1(false, ""); break; } - GMM_ASSERT1(pgt != NULL, "unknown element type " << selemtype + GMM_ASSERT1(pgt != nullptr, "unknown element type " << selemtype << " with " << nnode << "nodes"); do { std::string ls; @@ -780,6 +866,7 @@ namespace getfem { } while (!f.eof()); } + /* mesh file from ANSYS Supports solid structural elements stored with cdwrite in blocked format. @@ -787,9 +874,9 @@ namespace getfem { cdwrite,db,filename,cdb */ - static void import_cdb_mesh_file(std::istream& f, mesh& m, - size_type imat_filt=size_type(-1)) { - + static void import_cdb_mesh(std::istream& f, mesh& m, + size_type imat_filt=size_type(-1), + bool merge_overlapping_nodes=false) { std::map<size_type, size_type> cdb_node_2_getfem_node; std::vector<size_type> getfem_cv_nodes; std::vector<std::string> elt_types; @@ -894,7 +981,8 @@ namespace getfem { else pt[j] = 0; - cdb_node_2_getfem_node[nodeid] = m.add_point(pt, -1.); + cdb_node_2_getfem_node[nodeid] + = m.add_point(pt, merge_overlapping_nodes ? 0. : -1.); } while (bgeot::casecmp(line.substr(0,6),"EBLOCK") != 0) { @@ -952,7 +1040,7 @@ namespace getfem { if (nodesno >= 8) PP = std::stol(line.substr(7*fieldwidth,fieldwidth)); if (nodesno >= 9) { std::getline(f,line); - if (nodesno >= 9) QQ = std::stol(line.substr(0,fieldwidth)); + QQ = std::stol(line.substr(0,fieldwidth)); if (nodesno >= 10) RR = std::stol(line.substr(1*fieldwidth,fieldwidth)); if (nodesno >= 11) SS = std::stol(line.substr(2*fieldwidth,fieldwidth)); if (nodesno >= 12) TT = std::stol(line.substr(3*fieldwidth,fieldwidth)); @@ -1253,8 +1341,8 @@ namespace getfem { } int nonempty_regions=0; - for (size_type i=0; i < regions.size(); ++i) - if (regions[i].card() > 0) + for (const dal::bit_vector ®ion : regions) + if (region.card() > 0) ++nonempty_regions; if (nonempty_regions > 1) @@ -1270,23 +1358,10 @@ namespace getfem { } - static double round_to_nth_significant_number(double x, int ndec) { - double p = 1.; - double s = (x < 0 ? -1 : 1); - double pdec = pow(10.,double(ndec)); - if (x == 0) return 0.; - x = gmm::abs(x); - while (x > 1) { x /= 10.0; p*=10; } - while (x < 0.1) { x *= 10.0; p/=10; } - //cerr << "x=" << x << ", p=" << p << ", pdec=" << pdec << "\n"; - x = s * (floor(x * pdec + 0.5) / pdec) * p; - return x; - } - /* mesh file from noboite [http://www.distene.com/fr/corp/newsroom16.html] */ - static void import_noboite_mesh_file(std::istream& f, mesh& m) { - + static void import_noboite_mesh(std::istream& f, mesh& m) + { using namespace std; gmm::stream_standard_locale sl(f); @@ -1369,19 +1444,35 @@ namespace getfem { else // sinon cerr << "Erreur à l'ouverture !" << endl; - // appeler sunroutine import_gid_mesh_file + // appeler subroutine import_gid_mesh //import_mesh(const std::string& "noboite_to_GiD.gid", mesh& msh) - ifstream fichier1_GiD("noboite_to_GiD.gid", ios::in); - import_gid_mesh_file(fichier1_GiD, m); + ifstream file1_GiD("noboite_to_GiD.gid", ios::in); + import_gid_mesh(file1_GiD, m); // return 0; } + + /* mesh file from emc2 [http://pauillac.inria.fr/cdrom/prog/unix/emc2/eng.htm], am_fmt format (only triangular 2D meshes) */ - static void import_am_fmt_mesh_file(std::istream& f, mesh& m) { + + static double round_to_nth_significant_number(double x, int ndec) { + double p = 1.; + double s = (x < 0 ? -1 : 1); + double pdec = pow(10.,double(ndec)); + if (x == 0) return 0.; + x = gmm::abs(x); + while (x > 1) { x /= 10.0; p*=10; } + while (x < 0.1) { x *= 10.0; p/=10; } + //cerr << "x=" << x << ", p=" << p << ", pdec=" << pdec << "\n"; + x = s * (floor(x * pdec + 0.5) / pdec) * p; + return x; + } + + static void import_am_fmt_mesh(std::istream& f, mesh& m) { gmm::stream_standard_locale sl(f); /* read the node list */ std::vector<size_type> tri; @@ -1395,18 +1486,19 @@ namespace getfem { cerr.precision(16); P[0]=round_to_nth_significant_number(P[0],6); // force 9.999999E-1 to be converted to 1.0 P[1]=round_to_nth_significant_number(P[1],6); - size_type jj = m.add_point(P); + size_type jj = m.add_point(P, -1.); GMM_ASSERT1(jj == j, "ouch"); } for (size_type i=0; i < nbt*3; i+=3) m.add_triangle(tri[i]-1,tri[i+1]-1,tri[i+2]-1); } + /* mesh file from emc2 [http://pauillac.inria.fr/cdrom/prog/unix/emc2/eng.htm], am_fmt format triangular/quadrangular 2D meshes */ - static void import_emc2_mesh_file(std::istream& f, mesh& m) { + static void import_emc2_mesh(std::istream& f, mesh& m) { gmm::stream_standard_locale sl(f); /* read the node list */ std::vector<size_type> tri; @@ -1416,7 +1508,7 @@ namespace getfem { f >> nbs; for (size_type j=0; j < nbs; ++j) { f >> P[0] >> P[1] >> dummy; - size_type jj = m.add_point(P); + size_type jj = m.add_point(P, -1.); GMM_ASSERT1(jj == j, "ouch"); } while (!f.eof()) { @@ -1439,122 +1531,33 @@ namespace getfem { } } - void import_mesh(const std::string& filename, const std::string& format, - mesh& m) { - m.clear(); - try { - - if (bgeot::casecmp(format,"structured")==0) - { regular_mesh(m, filename); return; } - else if (bgeot::casecmp(format,"structured_ball")==0) - { regular_ball_mesh(m, filename); return; } - else if (bgeot::casecmp(format,"structured_ball_shell")==0) - { regular_ball_shell_mesh(m, filename); return; } - std::ifstream f(filename.c_str()); - GMM_ASSERT1(f.good(), "can't open file " << filename); - /* throw exceptions when an error occurs */ - f.exceptions(std::ifstream::badbit | std::ifstream::failbit); - import_mesh(f, format, m); - f.close(); - } - catch (std::logic_error& exc) { - m.clear(); - throw exc; - } - catch (std::ios_base::failure& exc) { - m.clear(); - GMM_ASSERT1(false, "error while importing " << format - << " mesh file \"" << filename << "\" : " << exc.what()); - } - catch (std::runtime_error& exc) { - m.clear(); - throw exc; - } - } - - void import_mesh_gmsh(std::istream& f, mesh &m, - std::map<std::string, size_type> ®ion_map, - bool remove_last_dimension, - std::map<size_type, std::set<size_type>> *nodal_map, - bool remove_duplicated_nodes) + // Main dispatcher to all supported file formats + void import_mesh(std::istream& f, const std::string& format, mesh& m) { - import_gmsh_mesh_file(f, m, 0, ®ion_map, nullptr, false, remove_last_dimension, nodal_map, - remove_duplicated_nodes); - } - - void import_mesh_gmsh(std::istream& f, mesh& m, - bool add_all_element_type, - std::set<size_type> *lower_dim_convex_rg, - std::map<std::string, size_type> *region_map, - bool remove_last_dimension, - std::map<size_type, std::set<size_type>> *nodal_map, - bool remove_duplicated_nodes) - { - import_gmsh_mesh_file(f, m, 0, region_map, lower_dim_convex_rg, add_all_element_type, - remove_last_dimension, nodal_map, remove_duplicated_nodes); - } - - void import_mesh_gmsh(const std::string& filename, mesh& m, - bool add_all_element_type, - std::set<size_type> *lower_dim_convex_rg, - std::map<std::string, size_type> *region_map, - bool remove_last_dimension, - std::map<size_type, std::set<size_type>> *nodal_map, - bool remove_duplicated_nodes) - { - m.clear(); - try { - std::ifstream f(filename.c_str()); - GMM_ASSERT1(f.good(), "can't open file " << filename); - /* throw exceptions when an error occurs */ - f.exceptions(std::ifstream::badbit | std::ifstream::failbit); - import_gmsh_mesh_file(f, m, 0, region_map, lower_dim_convex_rg, add_all_element_type, - remove_last_dimension, nodal_map, remove_duplicated_nodes); - f.close(); - } - catch (std::logic_error& exc) { - m.clear(); - throw exc; - } - catch (std::ios_base::failure& exc) { - m.clear(); - GMM_ASSERT1(false, "error while importing " << "gmsh" - << " mesh file \"" << filename << "\" : " << exc.what()); + std::string fmt(format); + bool merge_overlapping_nodes = false; + size_type pos = format.find(":merge_overlapping_nodes"); + if (pos != std::string::npos) { + merge_overlapping_nodes = true; + fmt = format.substr(0,pos) + format.substr(pos+24); + GMM_ASSERT2(fmt.find(":merge_overlapping_nodes") == std::string::npos, + "Invalid mesh format syntax: "+format); } - catch (std::runtime_error& exc) { - m.clear(); - throw exc; - } - } - - void import_mesh_gmsh(const std::string& filename, - mesh& m, std::map<std::string, size_type> ®ion_map, - bool remove_last_dimension, - std::map<size_type, std::set<size_type>> *nodal_map, - bool remove_duplicated_nodes) { - import_mesh_gmsh(filename, m, false, NULL, ®ion_map, remove_last_dimension, nodal_map, - remove_duplicated_nodes); - } - - void import_mesh(std::istream& f, const std::string& format, - mesh& m) { - if (bgeot::casecmp(format,"gmsh")==0) - import_gmsh_mesh_file(f,m); - else if (bgeot::casecmp(format,"gmsh_with_lower_dim_elt")==0) - import_gmsh_mesh_file(f,m,0,NULL,NULL,true); - else if (bgeot::casecmp(format,"gmshv2")==0)/* deprecate */ - import_gmsh_mesh_file(f,m,2); - else if (bgeot::casecmp(format,"gid")==0) - import_gid_mesh_file(f,m); - else if (bgeot::casecmp(format,"noboite")==0) - import_noboite_mesh_file(f,m); - else if (bgeot::casecmp(format,"am_fmt")==0) - import_am_fmt_mesh_file(f,m); - else if (bgeot::casecmp(format,"emc2_mesh")==0) - import_emc2_mesh_file(f,m); - else if (bgeot::casecmp(format,"cdb")==0) - import_cdb_mesh_file(f,m); + if (bgeot::casecmp(fmt,"gmsh")==0) + import_gmsh_mesh(f,m); + else if (bgeot::casecmp(fmt,"gmsh_with_lower_dim_elt")==0) + import_gmsh_mesh(f,m,true,nullptr,nullptr); + else if (bgeot::casecmp(fmt,"gid")==0) + import_gid_mesh(f,m); + else if (bgeot::casecmp(fmt,"noboite")==0) + import_noboite_mesh(f,m); + else if (bgeot::casecmp(fmt,"am_fmt")==0) + import_am_fmt_mesh(f,m); + else if (bgeot::casecmp(fmt,"emc2_mesh")==0) + import_emc2_mesh(f,m); + else if (bgeot::casecmp(fmt,"cdb")==0) + import_cdb_mesh(f,m); else if (bgeot::casecmp(format.substr(0,4),"cdb:")==0) { size_type imat(-1); bool success(true); @@ -1568,7 +1571,7 @@ namespace getfem { success = false; } if (success) - import_cdb_mesh_file(f,m,imat); + import_cdb_mesh(f,m,imat); else GMM_ASSERT1(false, "cannot import " << format << " mesh type : wrong cdb mesh type input"); } @@ -1576,24 +1579,4 @@ namespace getfem { << format << " mesh type : unknown mesh type"); } - void import_mesh(const std::string& filename, mesh& msh) { - size_type pos = filename.find_last_of(":"); - if (pos != std::string::npos) - getfem::import_mesh(filename.substr(pos+1), filename.substr(0,pos), msh); - else - msh.read_from_file(filename); - } - - void maybe_remove_last_dimension(mesh &m) { - bool is_flat = true; - unsigned N = m.dim(); if (N < 1) return; - for (dal::bv_visitor i(m.points().index()); !i.finished(); ++i) - if (m.points()[i][N-1] != 0) is_flat = 0; - if (is_flat) { - base_matrix M(N-1,N); - for (unsigned i=0; i < N-1; ++i) M(i,i) = 1; - m.transformation(M); - } - } - }