MeshKit
1.0
|
00001 #include "meshkit/CAMALPaver.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 #include "CAMALSurfEval.hpp" 00009 #include "CAMALSizeEval.hpp" 00010 #include "CMLPaver.hpp" 00011 #include <vector> 00012 00013 namespace MeshKit 00014 { 00015 00016 moab::EntityType CAMALPaver::meshTps[] = {moab::MBVERTEX, moab::MBQUAD, moab::MBMAXTYPE}; 00017 00018 CAMALPaver::CAMALPaver(MKCore *mk_core, const MEntVector &me_vec) 00019 : MeshScheme(mk_core, me_vec) 00020 { 00021 } 00022 00023 CAMALPaver::~CAMALPaver() 00024 { 00025 } 00026 00027 void CAMALPaver::setup_this() 00028 { 00029 // need to constrain all edges to be even 00030 constrain_even(); 00031 00032 // then call setup_boundary, to set up edge meshers 00033 setup_boundary(); 00034 00035 // then ensure that this depends on all bounding edges being meshed, 00036 // even if the edge meshers were already set up before setup_boundary 00037 ensure_facet_dependencies(false); 00038 } 00039 00040 void CAMALPaver::execute_this() 00041 { 00042 00043 #ifdef HAVE_FBIGEOM 00044 if (mentSelection.empty()) 00045 { 00046 // create model ents from previous op 00047 create_model_ents_from_previous_ops(); 00048 // now look at the latest SizingFunction, and set it or each model ent 00049 int latestIndexSF = 0; // maybe we would need to set it right 00050 for (MEntSelection::iterator sit = mentSelection.begin(); 00051 sit != mentSelection.end(); sit++) { 00052 // make a me, for convenience 00053 ModelEnt *me = (*sit).first; 00054 me->sizing_function_index(latestIndexSF); // need to work on this one; how do we know? 00055 } 00056 // now, force setup of this node again, as we have added model entities to it 00057 setup_called(false); 00058 mk_core()->setup(false); 00059 // debug 00060 mk_core()->print_graph(); 00061 // it may not be enough, we may have to execute the previous ops, that were just 00062 // created during setup... not very clean code; 00063 mk_core()->execute_before((GraphNode *) this); 00064 } 00065 #endif 00066 for (MEntSelection::iterator sit = mentSelection.begin(); sit != mentSelection.end(); sit++) { 00067 // make a me, for convenience 00068 ModelEnt *me = (*sit).first; 00069 00070 if(me->get_meshed_state()>=COMPLETE_MESH) 00071 continue; 00072 // create a surface evaluator for this modelent, and a size evaluator 00073 CAMALSurfEval cse(me); 00074 00075 SizingFunction * sz = mk_core()->sizing_function(me->sizing_function_index()); 00076 if (!sz->variable()) 00077 sz = NULL; // no function variable 00078 00079 CAMALSizeEval mesize(me->mesh_interval_size(), sz); 00080 // make sure the size isn't negative 00081 // make sure the size isn't negative 00082 if (mesize.get_size() == -1) mesize.set_size(1.0); 00083 00084 // assemble bounding mesh 00085 std::vector<moab::EntityHandle> bdy; 00086 std::vector<int> group_sizes, bdy_ids; 00087 me->boundary(0, bdy, NULL, &group_sizes); 00088 00089 // convert the handles to integers for input to Paver 00090 moab::Range bdy_vrange; 00091 std::vector<double> coords; 00092 me->get_indexed_connect_coords(bdy, NULL, NULL, bdy_ids, coords, &bdy_vrange); 00093 00094 // now construct the CAMAL mesher, and pass it initial conditions 00095 CMLPaver paver(&cse, &mesize); 00096 bool success = paver.set_boundary_mesh(bdy_vrange.size(), &coords[0], group_sizes.size(), &group_sizes[0], &bdy_ids[0]); 00097 if (!success) 00098 ECERRCHK(MK_FAILURE, "Trouble setting boundary mesh."); 00099 00100 // ok, now generate the mesh 00101 int num_pts, num_quads; 00102 success = paver.generate_mesh(num_pts, num_quads); 00103 if (!success) 00104 ECERRCHK(MK_FAILURE, "Trouble generating quad mesh."); 00105 00106 moab::Range &new_ents = (*sit).second; 00107 moab::ErrorCode rval; 00108 00109 // resize the coords array, then get the coords of the new points 00110 assert(num_pts >= (int)bdy_vrange.size()); 00111 if (num_pts > (int)bdy_vrange.size()) { 00112 coords.resize(3*(num_pts-bdy_vrange.size())); 00113 int pts_returned = paver.get_points_buf(coords.size(), &coords[0], bdy_vrange.size()); 00114 if (pts_returned != num_pts-(int)bdy_vrange.size()) 00115 ECERRCHK(MK_FAILURE, "Number of new points returned from Paver doesn't agree with previous value output."); 00116 00117 // create the new vertices' entities on the face 00118 rval = mk_core()->moab_instance()->create_vertices(&coords[0], pts_returned, new_ents); 00119 MBERRCHK(rval, mk_core()->moab_instance()); 00120 } 00121 00122 // for quads, pre-allocate connectivity 00123 moab::ReadUtilIface *iface; 00124 rval = mk_core()-> moab_instance() -> query_interface(iface); 00125 MBERRCHK(rval, mk_core()->moab_instance()); 00126 00127 //create the quads, get a direct ptr to connectivity 00128 moab::EntityHandle starth, *connect; 00129 rval = iface->get_element_connect(num_quads, 4, moab::MBQUAD, 1, starth, connect); 00130 MBERRCHK(rval, mk_core()->moab_instance()); 00131 00132 // read connectivity directly into that array, as int's 00133 int *connecti = (int*) connect; 00134 int quads_returned = paver.get_quads_buf(4*num_quads, connecti); 00135 if (quads_returned != num_quads) 00136 ECERRCHK(MK_FAILURE, "Number of new quads returned from Paver doesn't agree with previous value output."); 00137 00138 // put vertex handles into an indexible array 00139 std::vector<moab::EntityHandle> bdy_vvec; 00140 std::copy(bdy_vrange.begin(), bdy_vrange.end(), std::back_inserter(bdy_vvec)); 00141 std::copy(new_ents.begin(), new_ents.end(), std::back_inserter(bdy_vvec)); 00142 00143 // now convert vertex indices into handles in-place, working from the back 00144 for (int i = 4*num_quads-1; i >= 0; i--) { 00145 assert(connecti[i] >= 0 && connecti[i] < (int)bdy_vvec.size()); 00146 connect[i] = bdy_vvec[connecti[i]]; 00147 } 00148 00149 // put new quads into new entity range, then commit the mesh 00150 new_ents.insert(starth, starth+num_quads-1); 00151 me->commit_mesh(new_ents, COMPLETE_MESH); 00152 } 00153 } 00154 00155 } // namespace MeshKit