MeshKit
1.0
|
00001 #include "meshkit/NGTetMesher.hpp" 00002 #include "meshkit/MeshScheme.hpp" 00003 #include "meshkit/ModelEnt.hpp" 00004 #include "moab/Interface.hpp" 00005 #include "moab/ReadUtilIface.hpp" 00006 #include "moab/Range.hpp" 00007 #include "meshkit/RegisterMeshOp.hpp" 00008 namespace nglib 00009 { 00010 #include "nglib.h" 00011 } 00012 00013 #include <vector> 00014 00015 namespace MeshKit 00016 { 00017 00018 moab::EntityType NGTetMesher::meshTps[] = {moab::MBVERTEX, moab::MBTET, moab::MBMAXTYPE}; 00019 00020 NGTetMesher::NGTetMesher(MKCore *mk_core, const MEntVector &me_vec) 00021 : MeshScheme(mk_core, me_vec) 00022 { 00023 } 00024 00025 NGTetMesher::~NGTetMesher() 00026 { 00027 } 00028 00029 MeshOp *NGTetMesher::get_tri_mesher() 00030 { 00031 std::vector<MeshOpProxy *> proxies; 00032 mk_core()->meshop_by_mesh_type(moab::MBTRI, proxies); 00033 if (proxies.empty()) throw Error(MK_FAILURE, "Couldn't find a MeshOp capable of producing triangles."); 00034 return mk_core()->construct_meshop("AF2DfltTriangleMeshOp"); 00035 } 00036 00037 void NGTetMesher::setup_this() 00038 { 00039 MeshOp *tri_mesher = NULL; 00040 MEntVector surfs; 00041 00042 for (MEntSelection::iterator sit = mentSelection.begin(); sit != mentSelection.end(); sit++) { 00043 ModelEnt *me = (*sit).first; 00044 if (me->dimension() != 3) throw Error(MK_BAD_INPUT, "Tet mesher assigned to an entity with dimension != 3."); 00045 00046 // get the bounding faces 00047 surfs.clear(); 00048 me->get_adjacencies(2, surfs); 00049 00050 // check the mesh scheme on each one; if there is one, verify it can generate tris; if there 00051 // isn't one, make one 00052 bool inserted = false; 00053 00054 for (MEntVector::iterator vit = surfs.begin(); vit != surfs.end(); vit++) { 00055 if ((*vit)->is_meshops_list_empty()) { 00056 // get a tri mesher if we haven't already 00057 if (!tri_mesher) tri_mesher = get_tri_mesher(); 00058 00059 // add this surface to it, and if first for the volume, make sure it's added upstream 00060 tri_mesher->add_modelent(*vit); 00061 if (!inserted) { 00062 mk_core()->insert_node(tri_mesher, this); 00063 inserted = true; 00064 } 00065 } // if no meshops 00066 } // over surfs 00067 } // over vols 00068 } 00069 00070 void NGTetMesher::execute_this() 00071 { 00072 nglib::Ng_Init(); 00073 00074 for (MEntSelection::iterator sit = mentSelection.begin(); sit != mentSelection.end(); sit++) { 00075 // make a me, for convenience 00076 ModelEnt *me = (*sit).first; 00077 00078 // assemble bounding mesh 00079 std::vector<moab::EntityHandle> bdy; 00080 std::vector<int> group_sizes, senses, bdy_ids; 00081 me->boundary(2, bdy, &senses, &group_sizes); 00082 00083 // get connectivity 00084 00085 // convert the handles to integers for input to CMLTetMesher 00086 moab::Range bdy_vrange; 00087 std::vector<double> coords; 00088 me->get_indexed_connect_coords(bdy, &senses, NULL, bdy_ids, coords, &bdy_vrange, 1); 00089 00090 nglib::Ng_Mesh *ngmesh = nglib::Ng_NewMesh(); 00091 unsigned int numvs = bdy_vrange.size(); 00092 00093 // add the points 00094 for (unsigned int i = 0; i < numvs; i++) 00095 nglib::Ng_AddPoint(ngmesh, &coords[3*i]); 00096 00097 // add the tris 00098 unsigned int numtris = bdy.size(); 00099 for (unsigned int i = 0; i < numtris; i++) 00100 nglib::Ng_AddSurfaceElement(ngmesh, nglib::NG_TRIG, &bdy_ids[3*i]); 00101 00102 double my_size = me->mesh_interval_size(); 00103 if (0 > my_size) my_size = 1.0; 00104 nglib::Ng_RestrictMeshSizeGlobal(ngmesh, my_size); 00105 00106 nglib::Ng_Meshing_Parameters ngp; 00107 ngp.maxh = my_size; 00108 ngp.fineness = 0.5; 00109 00110 // Use variable name second_order if using newer version of NetGen 00111 //ngp.secondorder = 0; 00112 ngp.second_order = 0; 00113 // nglib.h Rev. 663 http://netgen-mesher.svn.sourceforge.net/viewvc/netgen-mesher/netgen/nglib/nglib.h?revision=663&view=markup 00114 //uses: second_order instead of secondorder(4.9.13) 00115 00116 00117 nglib::Ng_Result result = nglib::Ng_GenerateVolumeMesh(ngmesh, &ngp); 00118 if (nglib::NG_OK != result) ECERRCHK(MK_FAILURE, "Netgen mesher returned !ok."); 00119 00120 moab::ErrorCode rval; 00121 moab::Range new_ents; 00122 int num_pts = nglib::Ng_GetNP(ngmesh); 00123 assert(num_pts >= (int)numvs); 00124 if (num_pts > (int)numvs) { 00125 coords.resize(3*(num_pts-numvs)); 00126 00127 for (unsigned int i = (unsigned int) numvs; i < (unsigned int) num_pts; i++) 00128 nglib::Ng_GetPoint(ngmesh, i, &coords[3*(i-numvs)]); 00129 00130 // create the new vertices' entities 00131 rval = mk_core()->moab_instance()->create_vertices(&coords[0], num_pts-numvs, new_ents); 00132 MBERRCHK(rval, mk_core()->moab_instance()); 00133 } 00134 00135 // for tets, pre-allocate connectivity 00136 moab::ReadUtilIface *iface; 00137 rval = mk_core()-> moab_instance() -> query_interface(iface); 00138 MBERRCHK(rval, mk_core()->moab_instance()); 00139 00140 //create the tris, get a direct ptr to connectivity 00141 int num_tets = (int) nglib::Ng_GetNE(ngmesh); 00142 moab::EntityHandle starth, *connect; 00143 rval = iface->get_element_connect(num_tets, 4, moab::MBTET, 1, starth, connect); 00144 MBERRCHK(rval, mk_core()->moab_instance()); 00145 00146 // read connectivity directly into that array, as int's 00147 int *connecti = (int*) connect; 00148 for (unsigned int i = 0; i < (unsigned int) num_tets; i++) 00149 nglib::Ng_GetVolumeElement(ngmesh, i+1, connecti+4*i); 00150 00151 // put vertex handles into an indexible array 00152 std::vector<moab::EntityHandle> bdy_vvec; 00153 std::copy(bdy_vrange.begin(), bdy_vrange.end(), std::back_inserter(bdy_vvec)); 00154 std::copy(new_ents.begin(), new_ents.end(), std::back_inserter(bdy_vvec)); 00155 00156 // now convert vertex indices into handles in-place, working from the back 00157 for (int i = 4*num_tets-1; i >= 0; i--) { 00158 assert(connecti[i] > 0 && connecti[i] <= (int)bdy_vvec.size()); 00159 connect[i] = bdy_vvec[connecti[i]-1]; 00160 } 00161 00162 // put new tris into new entity range, then commit the mesh 00163 new_ents.insert(starth, starth+num_tets-1); 00164 me->commit_mesh(new_ents, COMPLETE_MESH); 00165 00166 nglib::Ng_DeleteMesh(ngmesh); 00167 } 00168 00169 nglib::Ng_Exit(); 00170 } 00171 00172 } // namespace MeshKit