MeshKit  1.0
NGTetMesher.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines