MeshKit
1.0
|
00001 #include "meshkit/EBMesher.hpp" 00002 #include "meshkit/SCDMesh.hpp" 00003 #include "meshkit/MKCore.hpp" 00004 #include "meshkit/ModelEnt.hpp" 00005 #include "meshkit/SizingFunction.hpp" 00006 #include "moab/ReadUtilIface.hpp" 00007 #include "meshkit/iGeom.hpp" 00008 #include "meshkit/RegisterMeshOp.hpp" 00009 00010 #ifdef HAVE_MOAB 00011 #include "moab/Core.hpp" 00012 #include "MBRange.hpp" 00013 #include "MBCartVect.hpp" 00014 #include "moab/EntityType.hpp" 00015 #include "moab/HomXform.hpp" 00016 #include "moab/GeomTopoTool.hpp" 00017 #endif 00018 00019 #ifdef HAVE_CGM 00020 #include "CubitDefines.h" 00021 #include "GeometryQueryTool.hpp" 00022 #include "RefFace.hpp" 00023 #endif 00024 00025 #define PI 3.14159265 00026 #define ERRORRF(a) {if (iBase_SUCCESS != err) {std::cerr << a << std::endl; return false;}} 00027 00028 double rayDir[3][3] = {{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}; 00029 00030 const bool debug_ebmesh = false; 00031 inline bool less_intersect(const IntersectDist d1, const IntersectDist d2) { 00032 return d1.distance < d2.distance; 00033 } 00034 00035 inline bool equal_intersect(const IntersectDist d1, const IntersectDist d2) { 00036 return abs(d1.distance - d2.distance) < 10e-7; 00037 } 00038 00039 namespace MeshKit 00040 { 00041 // static registration of this mesh scheme 00042 moab::EntityType EBMesher_tps[] = {moab::MBVERTEX, moab::MBHEX, moab::MBMAXTYPE}; 00043 const moab::EntityType* EBMesher::output_types() 00044 { return EBMesher_tps; } 00045 00046 EBMesher::EBMesher(MKCore *mkcore, const MEntVector &me_vec, 00047 double size, bool use_geom, int add_layer) 00048 : MeshScheme(mkcore, me_vec), m_nAddLayer(add_layer), m_dInputSize(size), m_bUseGeom(use_geom) 00049 { 00050 m_mesh = mkcore->imesh_instance()->instance(); 00051 m_hRootSet = mkcore->imesh_instance()->getRootSet(); 00052 m_nStatus = OUTSIDE; 00053 m_iStartHex = 0; 00054 m_hObbTree = NULL; 00055 m_hTreeRoot = 0; 00056 00057 #ifdef HAVE_MOAB 00058 // create tags with MOAB for dense tags 00059 int outside = 1; 00060 const void *out = &outside; 00061 m_elemStatusTag = get_tag("ELEM_STATUS_TAG", 1, 00062 MB_TAG_DENSE, MB_TYPE_INTEGER, out); 00063 00064 int length = 1; 00065 const void *leng = &length; 00066 m_edgeCutFracLengthTag = get_tag("EDGE_CUT_FRAC_LENGTH_TAG", // # of fractions 00067 3, 00068 //MB_TAG_SPARSE, // using dense for hdf5 exporting performance 00069 MB_TAG_DENSE, 00070 MB_TYPE_INTEGER, leng); 00071 00072 m_edgeCutFracTag = get_various_length_tag("EDGE_CUT_FRAC_TAG", 00073 //MB_TAG_SPARSE, 00074 MB_TAG_DENSE, 00075 MB_TYPE_DOUBLE); 00076 00077 int m_id = 1; 00078 const void *id = &m_id; 00079 m_volFracLengthTag = get_tag("VOL_FRAC_LENGTH_TAG", 1, 00080 MB_TAG_SPARSE, MB_TYPE_INTEGER, id); 00081 00082 m_volFracHandleTag = get_various_length_tag("VOL_FRAC_HANDLE_TAG", 00083 MB_TAG_SPARSE, MB_TYPE_INTEGER); 00084 00085 m_volFracTag = get_various_length_tag("VOL_FRAC_TAG", 00086 MB_TAG_SPARSE, MB_TYPE_DOUBLE); 00087 00088 // set bounding box size tag 00089 double bb_default[6] = { 0., 0., 0., 0., 0., 0. }; 00090 m_bbTag = get_tag("BOUNDING_BOX_SIZE", 6, 00091 MB_TAG_SPARSE, MB_TYPE_DOUBLE, bb_default); 00092 00093 m_GeomTopoTool = new moab::GeomTopoTool( moab_instance() ); 00094 #endif 00095 } 00096 00097 EBMesher::~EBMesher() 00098 { 00099 delete m_GeomTopoTool; 00100 } 00101 00102 bool EBMesher::can_mesh(ModelEnt *me) 00103 { 00104 if (me->dimension() == 3) return true; 00105 else return false; 00106 } 00107 00108 bool EBMesher::add_modelent(ModelEnt *model_ent) 00109 { 00110 // make sure this represents geometric volumes 00111 if (3 != model_ent->dimension()) 00112 throw Error(MK_WRONG_DIMENSION, "Wrong dimension entity added to EBMesher."); 00113 00114 return MeshOp::add_modelent(model_ent); 00115 } 00116 00117 MeshOp *EBMesher::get_scd_mesher() 00118 { 00119 MeshOpProxy* proxy = NULL; 00120 proxy = MKCore::meshop_proxy("SCDMesh"); 00121 if (proxy == NULL) throw Error(MK_FAILURE, "Couldn't find a MeshOp capable of producing the given mesh type."); 00122 return mk_core()->construct_meshop(proxy); 00123 } 00124 00125 void EBMesher::setup_this() 00126 { 00127 MeshOp *scd_mesher = NULL; 00128 std::vector<MeshOp*> meshops; 00129 bool inserted = false; 00130 00131 for (MEntSelection::iterator sit = mentSelection.begin(); sit != mentSelection.end(); sit++) { 00132 ModelEnt *me = (*sit).first; 00133 bool found = false; 00134 if (!scd_mesher) scd_mesher = get_scd_mesher(); 00135 meshops.clear(); 00136 me->get_meshops(meshops); 00137 int n_meshops = meshops.size(); 00138 00139 if (n_meshops > 0) { 00140 for (int i = 0; i < n_meshops; i++) { 00141 if (meshops[i] == scd_mesher) { 00142 found = true; 00143 break; 00144 } 00145 } 00146 } 00147 00148 if (!found) { // if no scd meshop 00149 // add this entity to it, and if first, make sure it's added upstream 00150 scd_mesher->add_modelent(me); 00151 if (!inserted) { 00152 mk_core()->insert_node(scd_mesher, this); 00153 inserted = true; 00154 } 00155 } 00156 00157 // no need to traverse all geometry for using whole geometry 00158 if (m_bUseWholeGeom) break; 00159 } 00160 00161 SCDMesh *sm = (SCDMesh*) scd_mesher; 00162 sm->set_interface_scheme(SCDMesh::full); 00163 sm->set_grid_scheme(SCDMesh::cfMesh); 00164 00165 sm->set_axis_scheme(SCDMesh::cartesian); 00166 sm->set_box_increase_ratio(m_boxIncrease); // add some extra layer to box 00167 00168 if (m_bUseWholeGeom) sm->set_geometry_scheme(SCDMesh::all); 00169 else sm->set_geometry_scheme(SCDMesh::individual); 00170 00171 // use mesh based geometry in SCDMesh and make tree to get box dimension 00172 if (m_bUseMeshGeom) { 00173 sm->use_mesh_geometry(true); 00174 sm->set_cart_box_min_max(m_minCoord, m_maxCoord, m_boxIncrease); 00175 } 00176 00177 // set # of intervals for 3 directions 00178 std::vector<int> fine_i (m_nDiv[0], 1); 00179 sm->set_coarse_i_grid(m_nDiv[0]); 00180 sm->set_fine_i_grid(fine_i); 00181 std::vector<int> fine_j (m_nDiv[1], 1); 00182 sm->set_coarse_j_grid(m_nDiv[1]); 00183 sm->set_fine_j_grid(fine_j); 00184 std::vector<int> fine_k (m_nDiv[2], 1); 00185 sm->set_coarse_k_grid(m_nDiv[2]); 00186 sm->set_fine_k_grid(fine_k); 00187 } 00188 00189 void EBMesher::execute_this() 00190 { 00191 iBase_ErrorType err; 00192 GraphNode *scd_node = other_node(in_arcs()); 00193 00194 #ifdef HAVE_MOAB 00195 double obb_time = .0; 00196 double intersection_time = .0; 00197 double set_info_time = .0; 00198 time_t time1, time2, time3, time4; 00199 unsigned long mem1, mem2, mem3, mem4; 00200 moab_instance()->estimated_memory_use(0, 0, 0, &mem1); 00201 moab::ErrorCode rval; 00202 00203 if (debug_ebmesh) { 00204 rval = mk_core()->moab_instance()->write_mesh("input.vtk"); 00205 MBERRCHK(rval, mk_core()->moab_instance()); 00206 } 00207 00208 time(&time1); 00209 if (m_bUseGeom && !m_bUseMeshGeom) { // construct obb tree for geometry surfaces and volumes by GeomTopoTool 00210 rval = m_GeomTopoTool->construct_obb_trees(m_bUseWholeGeom); 00211 MBERRCHK(rval, mk_core()->moab_instance()); 00212 } 00213 time(&time2); 00214 obb_time += difftime(time2, time1); 00215 00216 for (MEntSelection::iterator sit = mentSelection.begin(); sit != mentSelection.end(); sit++) { 00217 // 1. set division 00218 double box_min_max[6]; 00219 if (m_bUseWholeGeom) { 00220 static_cast<SCDMesh*> (scd_node)->get_box_dimension(box_min_max, &box_min_max[3]); 00221 } 00222 else { 00223 err = mk_core()->imesh_instance()->getData(reinterpret_cast< iBase_EntityHandle > 00224 (sit ->first->mesh_handle()), m_bbTag, &box_min_max[0]); 00225 IBERRCHK(err, "Failed to get hexes.\n"); 00226 } 00227 set_division(box_min_max, &box_min_max[3]); 00228 00229 // 2. set or construct obb tree 00230 time(&time1); 00231 set_tree_root(sit->first); 00232 time(&time2); 00233 obb_time += difftime(time2, time1); 00234 00235 // 3. find intersected geometry surfaces by rays 00236 find_intersections(); 00237 time(&time3); 00238 intersection_time += difftime(time3, time2); 00239 moab_instance()->estimated_memory_use(0, 0, 0, &mem3); 00240 00241 // 4. set hex status and boundary hex cut fraction info 00242 set_tag_info(); 00243 time(&time4); 00244 set_info_time += difftime(time4, time3); 00245 moab_instance()->estimated_memory_use(0, 0, 0, &mem4); 00246 00247 if (m_bUseWholeGeom) break; 00248 } 00249 #endif 00250 00251 if (debug_ebmesh) { 00252 std::cout << "OBB_tree_construct_time: " << obb_time 00253 << ", intersection_time: " << intersection_time 00254 << ", set_info_time: " << set_info_time << std::endl; 00255 std::cout << "start_memory: " << mem1 00256 << ", OBB_tree_construct_moemory: " << mem2 00257 << ", intersection_memory: " << mem3 00258 << ", set_info_memory: " << mem4 00259 << std::endl; 00260 } 00261 } 00262 00263 void EBMesher::set_num_interval(int* n_interval) 00264 { 00265 for (int i = 0; i < 3; i++) { 00266 m_nDiv[i] = n_interval[i]; 00267 } 00268 } 00269 00270 #ifdef HAVE_MOAB 00271 void EBMesher::set_tree_root(ModelEnt* me) 00272 { 00273 moab::ErrorCode rval; 00274 if (m_bUseGeom) { 00275 if (m_hObbTree == NULL) { 00276 m_hObbTree = m_GeomTopoTool->obb_tree(); 00277 } 00278 if (m_bUseWholeGeom) { 00279 if (!m_bUseMeshGeom) m_hTreeRoot = m_GeomTopoTool->get_one_vol_root(); 00280 } 00281 else { 00282 rval = m_GeomTopoTool->get_root(me->mesh_handle(), m_hTreeRoot); 00283 MBERRCHK(rval, mk_core()->moab_instance()); 00284 } 00285 } 00286 else { // facet data input case 00287 MBEntityHandle meshset; 00288 if (m_bUseWholeGeom) meshset = 0; 00289 else meshset = me->mesh_handle(); 00290 00291 // get triangles 00292 MBRange tris; 00293 rval = moab_instance()->get_entities_by_dimension(meshset, 2, tris); 00294 MBERRCHK(rval, mk_core()->moab_instance()); 00295 00296 // make tree 00297 if (m_hObbTree == NULL) { 00298 m_hObbTree = new MBOrientedBoxTreeTool( moab_instance() ); 00299 } 00300 rval = m_hObbTree->build(tris, m_hTreeRoot); 00301 MBERRCHK(rval, mk_core()->moab_instance()); 00302 } 00303 } 00304 00305 void EBMesher::find_intersections() 00306 { 00307 std::cout << "starting to find intersections." << std::endl; 00308 int i; 00309 //m_vnHexStatus.resize(m_nHex, 1); // initialize all hex as outside 00310 m_vnHexStatus.resize(m_nHex, 0); // initialize all hex as inside 00311 00312 // fire rays to 3 directions 00313 for (i = 0; i < 3; i++) { 00314 //m_vnEdgeStatus[i].resize(m_nDiv[i]*m_nDiv[(i + 1)%3]*m_nDiv[(i + 2)%3], OUTSIDE); 00315 m_vnEdgeStatus[i].resize(m_nDiv[i]*m_nDiv[(i + 1)%3]*m_nDiv[(i + 2)%3], INSIDE); 00316 fire_rays(i); 00317 } 00318 std::cout << "finished to find intersections." << std::endl; 00319 } 00320 00321 void EBMesher::export_mesh(const char* file_name, bool separate) 00322 { 00323 // get all hexes 00324 time_t time1, time2, time3; 00325 time(&time1); 00326 int i; 00327 iBase_ErrorType err; 00328 std::vector<iBase_EntityHandle> hex_handles; 00329 err = mk_core()->imesh_instance()->getEntities(m_hRootSet, iBase_REGION, 00330 iMesh_HEXAHEDRON, hex_handles); 00331 IBERRCHK(err, "Failed to get hexes.\n"); 00332 /* 00333 int hex_size = hex_handles.size(); 00334 int* hex_status = new int[hex_size]; 00335 int* hex_status = NULL; 00336 std::vector<int> hex_status(hex_size); 00337 err = mk_core()->imesh_instance()->getIntArrData(&hex_handles[0], hex_size, 00338 m_elemStatusTag, &hex_status[0]);*/ 00339 00340 int error; 00341 int hex_size = hex_handles.size(); 00342 int* hex_status = new int[hex_size]; 00343 int hex_status_alloc = sizeof(int)*hex_size; 00344 int hex_status_size = 0; 00345 iMesh_getIntArrData(m_mesh, &hex_handles[0], 00346 hex_size, m_elemStatusTag, 00347 &hex_status, &hex_status_alloc, 00348 &hex_status_size, &error); 00349 IBERRCHK(error, "Failed to get hex status.\n"); 00350 time(&time2); 00351 00352 if (separate) { 00353 int n_inside_hex = 0; 00354 int n_outside_hex = 0; 00355 int n_boundary_hex = 0; 00356 int hex_stat; 00357 (void) hex_stat; 00358 std::vector<iBase_EntityHandle> insideHex, outsideHex, bndrHex; 00359 for (i = 0; i < hex_size; i++) { 00360 if (hex_status[i] == 0) { 00361 n_inside_hex++; 00362 hex_stat = 0; 00363 insideHex.push_back(hex_handles[i]); 00364 } 00365 else if (hex_status[i] == 1) { 00366 n_outside_hex++; 00367 hex_stat = 1; 00368 outsideHex.push_back(hex_handles[i]); 00369 } 00370 else if (hex_status[i] == 2) { 00371 n_boundary_hex++; 00372 hex_stat = 2; 00373 bndrHex.push_back(hex_handles[i]); 00374 } 00375 else { 00376 throw Error(MK_FAILURE, "Hex element status should be inside/outside/boundary."); 00377 } 00378 } 00379 00380 std::cout << "# of exported inside hex:" << n_inside_hex 00381 << ", # of exported outside hex:" << n_outside_hex 00382 << ", # of exported boundary hex:" << n_boundary_hex 00383 << ", geom vol:" 00384 << n_inside_hex*m_dIntervalSize[0]*m_dIntervalSize[1]*m_dIntervalSize[2] 00385 << ", vox vol:" << hex_size*m_dIntervalSize[0]*m_dIntervalSize[1]*m_dIntervalSize[2] 00386 << std::endl; 00387 time(&time3); 00388 00389 // save inside/outside/boundary elements separately 00390 if (n_inside_hex > 0) { 00391 write_mesh(file_name, 0, &insideHex[0], n_inside_hex); 00392 } 00393 if (n_boundary_hex > 0) { 00394 write_mesh(file_name, 2, &bndrHex[0], n_boundary_hex); 00395 } 00396 if (n_outside_hex > 0) { 00397 write_mesh(file_name, 1, &outsideHex[0], n_outside_hex); 00398 } 00399 00400 if (debug_ebmesh) { 00401 std::cout << "hex_handle_get_time: " 00402 << difftime(time2, time1) 00403 << ", separate_write_time: " 00404 << difftime(time3, time2) 00405 << std::endl; 00406 } 00407 } 00408 else { 00409 write_mesh(file_name, 3, &hex_handles[0], hex_size); 00410 time3 = clock(); 00411 if (debug_ebmesh) { 00412 std::cout << "hex_handle_get_time: " 00413 << difftime(time2, time1) 00414 << ", actual_write_time: " 00415 << difftime(time3, time2) 00416 << std::endl; 00417 } 00418 } 00419 delete [] hex_status; 00420 } 00421 00422 void EBMesher::write_mesh(const char* file_name, int type, 00423 iBase_EntityHandle* handles, int& n_elem) 00424 { 00425 time_t time1, time2, time3; 00426 time(&time1); 00427 int is_list = 1; 00428 moab::ErrorCode rval; 00429 iBase_EntitySetHandle set; 00430 iBase_ErrorType err; 00431 00432 err = mk_core()->imesh_instance()->createEntSet(is_list, set); 00433 IBERRCHK(err, "Couldn't create set."); 00434 00435 err = mk_core()->imesh_instance()->addEntArrToSet(handles, n_elem, set); 00436 IBERRCHK(err, "Couldn't add hexes to set."); 00437 time(&time2); 00438 00439 std::string out_name; 00440 std::stringstream ss; 00441 if (type == 0) ss << "inside_"; 00442 else if (type == 1) ss << "outside_"; 00443 else if (type == 2) ss << "boundary_"; 00444 ss << file_name; 00445 ss >> out_name; 00446 00447 rval = moab_instance()->write_mesh(out_name.c_str(), 00448 (const moab::EntityHandle*) &set, 1); 00449 MBERRCHK(rval, mk_core()->moab_instance()); 00450 00451 std::cout << "Elements are exported." << std::endl; 00452 time(&time3); 00453 00454 if (debug_ebmesh) { 00455 std::cout << "set_creation_time: " 00456 << difftime(time2, time1) 00457 << ", write_time: " 00458 << difftime(time3, time2) 00459 << std::endl; 00460 } 00461 } 00462 #endif 00463 00464 EdgeStatus EBMesher::get_edge_status(const double dP, int& iSkip) 00465 { 00466 if (m_nStatus == INSIDE) { // previous inside 00467 if (dP < m_dSecondP) { 00468 m_nMove = 0; 00469 iSkip = m_iSecondP; 00470 return INSIDE; 00471 } 00472 else { 00473 if (is_shared_overlapped_surf(m_iInter - 1)) m_nMove = 1; 00474 else m_nMove = 2; 00475 00476 // skip shared and overlapped interesections 00477 while (m_vIntersection[m_iInter].distance - 00478 m_vIntersection[m_iInter - 1].distance < 1e-7 && 00479 (unsigned int) (m_iInter + 1) < m_vIntersection.size()) m_iInter++; 00480 00481 return BOUNDARY; 00482 } 00483 } 00484 else if (m_nStatus == OUTSIDE) { // previous outside 00485 if (dP < m_dFirstP) { 00486 m_nMove = 0; 00487 return OUTSIDE; 00488 } 00489 else { 00490 if (dP < m_dSecondP) m_nMove = 0; 00491 else if (is_shared_overlapped_surf(m_iInter - 1)) m_nMove = 1; 00492 else m_nMove = 2; 00493 00494 // skip shared and overlapped interesections 00495 while (m_vIntersection[m_iInter].distance - 00496 m_vIntersection[m_iInter - 1].distance < 1e-7 && 00497 (unsigned int) (m_iInter + 1) < m_vIntersection.size()) m_iInter++; 00498 00499 return BOUNDARY; 00500 } 00501 } 00502 else if (m_nStatus == BOUNDARY) { // previous boundary 00503 if (dP < m_dFirstP) { 00504 m_nMove = 0; 00505 iSkip = m_iFirstP; 00506 return OUTSIDE; 00507 } 00508 else { 00509 if (dP < m_dSecondP) { 00510 m_nMove = 0; 00511 if (m_prevPnt < m_dFirstP) return BOUNDARY; 00512 else { 00513 iSkip = m_iSecondP; 00514 return INSIDE; 00515 } 00516 } 00517 else { 00518 if (is_shared_overlapped_surf(m_iInter - 1)) m_nMove = 1; 00519 else m_nMove = 2; 00520 00521 // skip shared and overlapped interesections 00522 while (m_vIntersection[m_iInter].distance - 00523 m_vIntersection[m_iInter - 1].distance < 1e-7 && 00524 (unsigned int) (m_iInter + 1) < m_vIntersection.size()) m_iInter++; 00525 00526 if (m_prevPnt < m_dSecondP) return BOUNDARY; 00527 else return OUTSIDE; 00528 } 00529 } 00530 } 00531 else { 00532 std::cerr << "Couldn't get edge status." << std::endl; 00533 return INSIDE; 00534 } 00535 } 00536 00537 bool EBMesher::set_neighbor_hex_status(int dir, int i, int j, int k) 00538 { 00539 int iElem; 00540 int otherDir1 = (dir + 1)%3; 00541 int otherDir2 = (dir + 2)%3; 00542 00543 if (dir == 0) { // x coordinate ray 00544 m_iElem = j*m_nDiv[0]*m_nDiv[1] + i*m_nDiv[0] + k; 00545 if (!set_hex_status(m_iElem, m_nStatus, dir)) return false; 00546 iElem = m_iElem - m_nDiv[dir]; 00547 if (!set_hex_status(iElem, m_nStatus, dir)) return false; 00548 iElem -= m_nDiv[dir]*m_nDiv[otherDir1]; 00549 if (!set_hex_status(iElem, m_nStatus, dir)) return false; 00550 iElem += m_nDiv[dir]; 00551 if (!set_hex_status(iElem, m_nStatus, dir)) return false; 00552 } 00553 else if (dir == 1) { // y coordinate ray 00554 m_iElem = i*m_nDiv[1]*m_nDiv[0] + k*m_nDiv[0] + j; 00555 if (!set_hex_status(m_iElem, m_nStatus, dir)) return false; 00556 iElem = m_iElem - 1; 00557 if (!set_hex_status(iElem, m_nStatus, dir)) return false; 00558 iElem -= m_nDiv[dir]*m_nDiv[otherDir2]; 00559 if (!set_hex_status(iElem++, m_nStatus, dir)) return false; 00560 if (!set_hex_status(iElem, m_nStatus, dir)) return false; 00561 } 00562 else if (dir == 2) { // z coordinate ray 00563 m_iElem = k*m_nDiv[0]*m_nDiv[1] + j*m_nDiv[0] + i; 00564 if (!set_hex_status(m_iElem, m_nStatus, dir)) return false; 00565 iElem = m_iElem - 1; 00566 if (!set_hex_status(iElem, m_nStatus, dir)) return false; 00567 iElem -= m_nDiv[otherDir1]; 00568 if (!set_hex_status(iElem++, m_nStatus, dir)) return false; 00569 if (!set_hex_status(iElem, m_nStatus, dir)) return false; 00570 } 00571 00572 return true; 00573 } 00574 00575 bool EBMesher::set_hex_status(int index, EdgeStatus value, int dir) 00576 { 00577 if (index < 0 || index > m_nHex - 1) { 00578 return false; 00579 } 00580 00581 if (m_vnHexStatus[index] != 2) { 00582 if (value == INSIDE) { 00583 m_vnHexStatus[index] = 0; 00584 } 00585 else if (value == OUTSIDE) { 00586 m_vnHexStatus[index] = 1; 00587 } 00588 else if (value == BOUNDARY) { 00589 m_vnHexStatus[index] = 2; 00590 } 00591 } 00592 00593 return true; 00594 } 00595 00596 bool EBMesher::set_edge_status(int dir) 00597 { 00598 // set boundary cut information to edge 00599 std::vector<double> vdCutFraction; 00600 if (m_nMove == 0) vdCutFraction.push_back((m_curPnt - m_dFirstP)/m_dIntervalSize[dir] - 1.); 00601 else if (m_nMove == 1) vdCutFraction.push_back(1. - (m_curPnt - m_dSecondP)/m_dIntervalSize[dir]); 00602 else if (m_nMove == 2) { 00603 vdCutFraction.push_back(1. - (m_curPnt - m_dSecondP)/m_dIntervalSize[dir]); 00604 if (m_dFirstP < m_curPnt) { 00605 vdCutFraction.push_back((m_curPnt - m_dFirstP)/m_dIntervalSize[dir] - 1.); 00606 } 00607 } 00608 00609 std::map<int, CutFraction>::iterator iter = m_mdCutFraction.find(m_iElem); 00610 if (iter == m_mdCutFraction.end()) { // not exist 00611 CutFraction cFraction(dir, vdCutFraction); 00612 m_mdCutFraction[m_iElem] = cFraction; 00613 } 00614 else { // exist 00615 iter->second.add(dir, vdCutFraction); 00616 } 00617 00618 //m_nFraction += vdCutFraction.size(); 00619 00620 return true; 00621 } 00622 00623 #ifdef HAVE_MOAB 00624 void EBMesher::set_division() 00625 { 00626 int i, j; 00627 moab::CartVect box_center, box_axis1, box_axis2, box_axis3, 00628 min_cart_box(HUGE_VAL, HUGE_VAL, HUGE_VAL), 00629 max_cart_box(0., 0., 0.); 00630 00631 moab::ErrorCode rval = m_hObbTree->box(m_hTreeRoot, box_center.array(), 00632 box_axis1.array(), box_axis2.array(), 00633 box_axis3.array()); 00634 MBERRCHK(rval, mk_core()->moab_instance()); 00635 00636 // cartesian box corners 00637 moab::CartVect corners[8] = {box_center + box_axis1 + box_axis2 + box_axis3, 00638 box_center + box_axis1 + box_axis2 - box_axis3, 00639 box_center + box_axis1 - box_axis2 + box_axis3, 00640 box_center + box_axis1 - box_axis2 - box_axis3, 00641 box_center - box_axis1 + box_axis2 + box_axis3, 00642 box_center - box_axis1 + box_axis2 - box_axis3, 00643 box_center - box_axis1 - box_axis2 + box_axis3, 00644 box_center - box_axis1 - box_axis2 - box_axis3}; 00645 00646 // get the max, min cartesian box corners 00647 for (i = 0; i < 8; i++) { 00648 for (j = 0; j < 3; j++) { 00649 if (corners[i][j] < min_cart_box[j]) min_cart_box[j] = corners[i][j]; 00650 if (corners[i][j] > max_cart_box[j]) max_cart_box[j] = corners[i][j]; 00651 } 00652 } 00653 moab::CartVect length = max_cart_box - min_cart_box; 00654 00655 // default value is adjusted to large geometry file 00656 // interval_size_estimate : 2*L*sqrt(2*PI*sqrt(2)/# of tris) 00657 if (m_dInputSize < 0.) { 00658 int n_tri; 00659 rval = moab_instance()-> 00660 get_number_entities_by_dimension(reinterpret_cast<MBEntityHandle>(m_hRootSet), 00661 2, n_tri); 00662 MBERRCHK(rval, mk_core()->moab_instance()); 00663 00664 double box_length_ave = (length[0] + length[1] + length[2])/3.; 00665 m_dInputSize = 2.*box_length_ave*sqrt(8.886/n_tri); 00666 } 00667 00668 for (i = 0; i < 3; i++) { 00669 m_nDiv[i] = length[i]/m_dInputSize; 00670 if (m_nDiv[i] < m_nAddLayer) m_nDiv[i] = m_nAddLayer; // make "m_nAddLayer" elements larger than bounding box 00671 m_dIntervalSize[i] = m_dInputSize; 00672 //if (m_nDiv[i]*.07 > m_nAddLayer) m_nDiv[i] += m_nDiv[i]*.07; 00673 //else m_nDiv[i] += m_nAddLayer; 00674 m_nDiv[i] += m_nAddLayer; 00675 m_nNode[i] = m_nDiv[i] + 1; 00676 m_origin_coords[i] = box_center[i] - .5*m_nDiv[i]*m_dIntervalSize[i]; 00677 } 00678 00679 m_nHex = m_nDiv[0]*m_nDiv[1]*m_nDiv[2]; 00680 00681 std::cout << "# of hex: " << m_nHex << ", interval size: " 00682 << m_dInputSize << std::endl; 00683 00684 std::cout << "# of division: " << m_nDiv[0] << "," 00685 << m_nDiv[1] << "," << m_nDiv[2] << std::endl; 00686 } 00687 00688 int EBMesher::set_division(double* min, double* max) 00689 { 00690 for (int i = 0; i < 3; i++) { 00691 m_dIntervalSize[i] = (max[i] - min[i])/m_nDiv[i]; 00692 m_nNode[i] = m_nDiv[i] + 1; 00693 m_origin_coords[i] = min[i]; 00694 } 00695 00696 m_nHex = m_nDiv[0]*m_nDiv[1]*m_nDiv[2]; 00697 00698 std::cout << "# of hex: " << m_nHex << ", interval_size: " 00699 << m_dIntervalSize[0] << ", " << m_dIntervalSize[1] << ", " 00700 << m_dIntervalSize[2] << std::endl; 00701 00702 std::cout << "# of division: " << m_nDiv[0] << "," 00703 << m_nDiv[1] << "," << m_nDiv[2] << std::endl; 00704 00705 return iBase_SUCCESS; 00706 } 00707 00708 int EBMesher::make_scd_hexes() 00709 { 00710 // create vertex and hex sequences 00711 int i; 00712 double max_coords[3]; 00713 (void) max_coords; 00714 for (i = 0; i < 3; i++) { 00715 max_coords[i] = m_origin_coords[i] + m_nDiv[i]*m_dIntervalSize[i]; 00716 } 00717 00718 moab::HomCoord coord_min(0, 0, 0); 00719 moab::HomCoord coord_max(m_nDiv[0], m_nDiv[1], m_nDiv[2]); 00720 moab::EntitySequence* vertex_seq = NULL; 00721 moab::EntitySequence* cell_seq = NULL; 00722 moab::EntityHandle vs, cs; 00723 moab::Core *mbcore = dynamic_cast<moab::Core*>(moab_instance()); 00724 00725 moab::ErrorCode rval = mbcore->create_scd_sequence(coord_min, coord_max, MBVERTEX, 1, vs, vertex_seq); 00726 MBERRCHK(rval, mk_core()->moab_instance()); 00727 00728 mbcore->create_scd_sequence(coord_min, coord_max, MBHEX, 1, cs, cell_seq); 00729 MBERRCHK(rval, mk_core()->moab_instance()); 00730 00731 moab::HomCoord p2(coord_max.i(), coord_min.j(), coord_min.k()); 00732 moab::HomCoord p3(coord_min.i(), coord_max.j(), coord_min.k()); 00733 00734 rval = mbcore->add_vsequence(vertex_seq, cell_seq, coord_min, coord_min, 00735 p2, p2, p3, p3); 00736 MBERRCHK(rval, mk_core()->moab_instance()); 00737 00738 int nTotNode = m_nNode[0]*m_nNode[1]*m_nNode[2]; 00739 int ii, jj, kk; 00740 MBEntityHandle handle; 00741 double dumv[3]; 00742 for (i = 0, handle = vs; i < nTotNode; i++, handle++) { 00743 ii = (i%(m_nNode[0]*m_nNode[1]))%m_nNode[0]; 00744 jj = (i%(m_nNode[0]*m_nNode[1]))/m_nNode[0]; 00745 kk = i/m_nNode[0]/m_nNode[1]; 00746 dumv[0] = m_origin_coords[0] + ii*m_dIntervalSize[0]; 00747 dumv[1] = m_origin_coords[1] + jj*m_dIntervalSize[1]; 00748 dumv[2] = m_origin_coords[2] + kk*m_dIntervalSize[2]; 00749 rval = moab_instance()->set_coords(&handle, 1, dumv); 00750 MBERRCHK(rval, mk_core()->moab_instance()); 00751 } 00752 00753 m_iStartHex = moab_instance()->id_from_handle(cs); 00754 00755 return iBase_SUCCESS; 00756 } 00757 00758 iBase_TagHandle EBMesher::get_tag(const char* name, int size, 00759 unsigned store, MBDataType type, 00760 const void* def_value, 00761 bool create_if_missing) 00762 { 00763 MBTag retval = 0; 00764 /*moab::ErrorCode result = moab_instance()->tag_create(name, size, store, type, 00765 retval, def_value, 00766 create_if_missing);*/ 00767 store = store | moab::MB_TAG_CREAT; 00768 if(!create_if_missing) 00769 store = store | moab::MB_TAG_EXCL; 00770 moab::ErrorCode result = moab_instance()->tag_get_handle(name, size, type, retval, store, 00771 def_value); 00772 if (create_if_missing && MB_SUCCESS != result) { 00773 std::cerr << "Couldn't find nor create tag named " << name << std::endl; 00774 } 00775 00776 return (iBase_TagHandle) retval; 00777 } 00778 00779 iBase_TagHandle EBMesher::get_various_length_tag(const char* name, 00780 unsigned store, MBDataType type) 00781 { 00782 MBTag retval = 0; 00783 store = store | moab::MB_TAG_VARLEN | moab::MB_TAG_CREAT; 00784 moab::ErrorCode result = moab_instance()-> 00785 tag_get_handle( name, 1, type, retval, store); 00786 if (MB_SUCCESS != result) { 00787 std::cerr << "Couldn't find nor create tag named " << name << std::endl; 00788 } 00789 00790 return (iBase_TagHandle) retval; 00791 } 00792 00793 void EBMesher::set_tag_info() 00794 { 00795 // get all hexes 00796 int i, j, k; 00797 iBase_ErrorType err; 00798 std::vector<iBase_EntityHandle> hex_handles; 00799 err = mk_core()->imesh_instance()->getEntities(m_hRootSet, iBase_REGION, 00800 iMesh_HEXAHEDRON, hex_handles); 00801 IBERRCHK(err, "Failed to get hexes.\n"); 00802 00803 err = mk_core()->imesh_instance()->setIntArrData(&hex_handles[0], m_nHex, 00804 m_elemStatusTag, 00805 &m_vnHexStatus[0]); 00806 IBERRCHK(err, "Failed to set hex element status data."); 00807 00808 // set cut fraction info to boundary hexes 00809 int nBndrHex = m_mdCutFraction.size(); 00810 std::vector<iBase_EntityHandle> hvBndrHex(nBndrHex); 00811 int* frac_size = new int[nBndrHex]; 00812 int* frac_leng = new int[3*nBndrHex]; 00813 int nFracSize, nTempSize, iHex, nTolFrac = 0; 00814 int nDoubleSize = sizeof(double); 00815 std::map<int, CutFraction>::iterator iter = m_mdCutFraction.begin(); 00816 std::map<int, CutFraction>::iterator end_iter = m_mdCutFraction.end(); 00817 for (i = 0; iter != end_iter; iter++, i++) { 00818 iHex = iter->first; 00819 hvBndrHex[i] = hex_handles[iHex]; 00820 00821 nFracSize = 0; 00822 for (j = 0; j < 3; j++) { 00823 nTempSize = iter->second.fraction[j].size(); 00824 nFracSize += nTempSize; 00825 frac_leng[3*i + j] = nTempSize; 00826 } 00827 frac_size[i] = nDoubleSize*nFracSize; // sizeof(double)* 00828 nTolFrac += nFracSize; 00829 } 00830 00831 int iFrac = 0; 00832 double* fractions = new double[nTolFrac]; 00833 std::vector<const void*> frac_data_pointer(nBndrHex); 00834 iter = m_mdCutFraction.begin(); 00835 for (i = 0; iter != end_iter; iter++, i++) { 00836 for (j = 0; j < 3; j++) { 00837 nFracSize = iter->second.fraction[j].size(); 00838 frac_data_pointer[i] = &fractions[iFrac]; 00839 for (k = 0; k < nFracSize; k++) { 00840 fractions[iFrac++] = iter->second.fraction[j][k]; 00841 } 00842 } 00843 } 00844 00845 err = mk_core()->imesh_instance()->setIntArrData(&hvBndrHex[0], nBndrHex, 00846 m_edgeCutFracLengthTag, 00847 frac_leng); 00848 IBERRCHK(err, "Failed to set cut fraction sizes to hex."); 00849 00850 moab::ErrorCode rval = moab_instance()->tag_set_by_ptr(reinterpret_cast<MBTag> (m_edgeCutFracTag), 00851 reinterpret_cast<moab::EntityHandle*> (&hvBndrHex[0]), 00852 nBndrHex, &frac_data_pointer[0], frac_size); 00853 MBERRCHK(rval, mk_core()->moab_instance()); 00854 00855 delete [] frac_size; 00856 delete [] frac_leng; 00857 delete [] fractions; 00858 } 00859 00860 void EBMesher::fire_rays(int dir) 00861 { 00862 // ray fire 00863 int i, j, k, l, index[3]; 00864 double tolerance = 1e-12; 00865 double rayLength = m_nDiv[dir]*m_dIntervalSize[dir]; 00866 int iNodeStart, iNodeEnd, nIntersect, nNodeSlice; 00867 double startPnt[3], endPnt[3]; 00868 int otherDir1 = (dir + 1)%3; 00869 int otherDir2 = (dir + 2)%3; 00870 // harmless as this expression (does nothing) so that a compiler sees it is used. 00871 (void) iNodeEnd; 00872 (void) nNodeSlice; 00873 00874 for (j = 1; j < m_nNode[otherDir2] - 1; j++) { 00875 for (i = 1; i < m_nNode[otherDir1] - 1; i++) { 00876 00877 // get ray start and end points 00878 if (dir == 0) { // x coordinate ray 00879 iNodeStart = j*m_nNode[dir]*m_nNode[otherDir1] + i*m_nNode[dir]; 00880 iNodeEnd = iNodeStart + m_nNode[dir] - 1; 00881 nNodeSlice = 1; 00882 index[0] = 0; 00883 index[1] = i; 00884 index[2] = j; 00885 } 00886 else if (dir == 1) { // y coordinate ray 00887 iNodeStart = i*m_nNode[otherDir2]*m_nNode[dir] + j; 00888 iNodeEnd = iNodeStart + m_nNode[otherDir2]*(m_nNode[dir] - 1); 00889 nNodeSlice = m_nNode[otherDir2]; 00890 index[0] = j; 00891 index[1] = 0; 00892 index[2] = i; 00893 } 00894 else if (dir == 2) { // z coordinate ray 00895 iNodeStart = j*m_nNode[otherDir1] + i; 00896 iNodeEnd = iNodeStart + m_nNode[otherDir1]*m_nNode[otherDir2]*(m_nNode[dir] - 1); 00897 nNodeSlice = m_nNode[otherDir1]*m_nNode[otherDir2]; 00898 index[0] = i; 00899 index[1] = j; 00900 index[2] = 0; 00901 } 00902 else IBERRCHK(iBase_FAILURE, "Ray direction should be 0 to 2."); 00903 00904 for (l = 0; l < 3; l++) { 00905 if (l == dir) { 00906 startPnt[l] = m_origin_coords[l]; 00907 endPnt[l] = m_origin_coords[l] + m_nDiv[dir]*m_dIntervalSize[l]; 00908 } 00909 else { 00910 startPnt[l] = m_origin_coords[l] + index[l]*m_dIntervalSize[l]; 00911 endPnt[l] = startPnt[l]; 00912 } 00913 } 00914 00915 k = 0; 00916 m_iInter = 0; 00917 if (!fire_ray(nIntersect, startPnt, endPnt, tolerance, dir, rayLength)) { 00918 IBERRCHK(iBase_FAILURE, "Couldn't fire ray."); 00919 } 00920 00921 if (nIntersect > 0) { 00922 m_iFirstP = m_vIntersection[m_iInter].distance/m_dIntervalSize[dir]; 00923 m_dFirstP = startPnt[dir] + m_vIntersection[m_iInter++].distance; 00924 m_iSecondP = m_vIntersection[m_iInter].distance/m_dIntervalSize[dir]; 00925 m_dSecondP = startPnt[dir] + m_vIntersection[m_iInter++].distance; 00926 00927 // set outside before the first hit 00928 for (k = 0; k < m_iFirstP; k++) { 00929 m_nStatus = OUTSIDE; 00930 00931 if (!set_neighbor_hex_status(dir, i, j, k)) { 00932 IBERRCHK(iBase_FAILURE, "Couldn't set neighbor hex status."); 00933 } 00934 } 00935 00936 for (; k < m_nNode[dir] - 1;) { 00937 int i_skip = 0; 00938 m_curPnt = startPnt[dir] + (k + 1)*m_dIntervalSize[dir]; 00939 EdgeStatus preStat = m_nStatus; 00940 m_nStatus = get_edge_status(m_curPnt, i_skip); 00941 m_vnEdgeStatus[dir][i*m_nDiv[dir] + j*m_nDiv[dir]*m_nDiv[otherDir1] + k] = m_nStatus; 00942 00943 // set status of all hexes sharing the edge 00944 if (!set_neighbor_hex_status(dir, i, j, k)) { 00945 IBERRCHK(iBase_FAILURE, "Couldn't set neighbor hex status."); 00946 } 00947 00948 if (m_nMove > 0) { 00949 if (m_iInter < nIntersect) { 00950 if (!move_intersections(dir, nIntersect, startPnt)) { 00951 IBERRCHK(iBase_FAILURE, "Couldn't move intersections."); 00952 } 00953 } 00954 else { 00955 m_nMove = 1; 00956 if (m_nStatus == BOUNDARY && !set_edge_status(dir)) { 00957 IBERRCHK(iBase_FAILURE, "Couldn't set edge status."); 00958 } 00959 k++; 00960 break; // rest is all outside 00961 } 00962 } 00963 else if (m_nStatus == BOUNDARY && !set_edge_status(dir)) { 00964 IBERRCHK(iBase_FAILURE, "Couldn't set edge status."); 00965 } 00966 else if (m_nStatus == OUTSIDE && preStat == BOUNDARY) { // set outside until next hit 00967 k++; 00968 for (; k < i_skip; k++) { 00969 m_nStatus = OUTSIDE; 00970 if (!set_neighbor_hex_status(dir, i, j, k)) { 00971 IBERRCHK(iBase_FAILURE, "Couldn't set neighbor hex status."); 00972 } 00973 } 00974 } 00975 00976 // set cut-cell edge status 00977 if (i_skip > 0) { 00978 m_prevPnt = startPnt[dir] + i_skip*m_dIntervalSize[dir]; 00979 k = i_skip; 00980 } 00981 else { 00982 m_prevPnt = m_curPnt; 00983 k++; 00984 } 00985 } 00986 } 00987 00988 // the rest are all outside 00989 for (; k < m_nNode[dir] - 1; k++) { 00990 m_nStatus = OUTSIDE; 00991 if (!set_neighbor_hex_status(dir, i, j, k)) { 00992 IBERRCHK(iBase_FAILURE, "Couldn't set neighbor hex status."); 00993 } 00994 } 00995 } 00996 } 00997 } 00998 00999 bool EBMesher::fire_ray(int& nIntersect, double startPnt[3], 01000 double endPnt[3], double tol, int dir, 01001 double rayLength) 01002 { 01003 m_vIntersection.clear(); 01004 m_vhInterSurf.clear(); 01005 m_vhInterFacet.clear(); 01006 m_mhOverlappedSurf.clear(); 01007 std::vector<double> temp_intersects; 01008 moab::ErrorCode rVal; 01009 if (m_bUseGeom) { // geometry input 01010 rVal = m_hObbTree->ray_intersect_sets(temp_intersects, m_vhInterSurf, 01011 m_vhInterFacet, m_hTreeRoot, tol, 01012 -1, startPnt, rayDir[dir], &rayLength); 01013 } 01014 else { // facet input 01015 std::vector<moab::EntityHandle> dum_facets_out; 01016 rVal = m_hObbTree->ray_intersect_triangles(temp_intersects, dum_facets_out, 01017 m_hTreeRoot, tol, 01018 startPnt, rayDir[dir], &rayLength); 01019 } 01020 01021 nIntersect = temp_intersects.size(); 01022 if (MB_SUCCESS != rVal) { 01023 std::cerr << "Failed : ray-triangle intersection." << std::endl; 01024 return false; 01025 } 01026 01027 if (nIntersect > 0) { 01028 m_vIntersection.resize(nIntersect); 01029 01030 for (int l = 0; l < nIntersect; l++) { 01031 IntersectDist temp_inter_dist(temp_intersects[l], l); 01032 m_vIntersection[l] = temp_inter_dist; 01033 } 01034 std::sort(m_vIntersection.begin(), m_vIntersection.end(), less_intersect); 01035 01036 if (nIntersect > 1) { 01037 bool bMoveOnce; 01038 m_nIteration = 0; 01039 m_iOverlap = 0; 01040 01041 if (m_bUseGeom) { // if there are geometry info 01042 remove_intersection_duplicates(); 01043 } 01044 else if (is_ray_move_and_set_overlap_surf(bMoveOnce)) { // facet geom case 01045 if (!move_ray(nIntersect, startPnt, endPnt, tol, dir, bMoveOnce)) { 01046 std::cerr << "Number of Intersection between edges and ray should be even." << std::endl; 01047 return false; 01048 } 01049 } 01050 nIntersect = m_vIntersection.size(); 01051 } 01052 } 01053 01054 return true; 01055 } 01056 01057 bool EBMesher::move_intersections(int n_dir, int n_inter, double start_pnt[3]) 01058 { 01059 if (m_nMove > 0) { 01060 if (m_iInter < n_inter) { 01061 if (m_nMove == 1) { 01062 do { 01063 if (m_nStatus == BOUNDARY && !set_edge_status(n_dir)) return false; 01064 m_iFirstP = m_iSecondP; 01065 m_dFirstP = m_dSecondP; 01066 m_iSecondP = m_vIntersection[m_iInter].distance/m_dIntervalSize[n_dir]; 01067 m_dSecondP = start_pnt[n_dir] + m_vIntersection[m_iInter++].distance; 01068 } 01069 while (m_dSecondP < m_curPnt && m_iInter < n_inter); 01070 } 01071 else if (m_nMove == 2) { 01072 do { 01073 m_iFirstP = m_vIntersection[m_iInter].distance/m_dIntervalSize[n_dir]; 01074 m_dFirstP = start_pnt[n_dir] + m_vIntersection[m_iInter++].distance; 01075 if (m_nStatus == BOUNDARY && !set_edge_status(n_dir)) return false; 01076 if (m_iInter < n_inter) { 01077 m_iSecondP = m_vIntersection[m_iInter].distance/m_dIntervalSize[n_dir]; 01078 m_dSecondP = start_pnt[n_dir] + m_vIntersection[m_iInter++].distance; 01079 } 01080 else { 01081 m_iSecondP = m_iFirstP; 01082 m_dSecondP = m_dFirstP; 01083 } 01084 } 01085 while (m_dSecondP < m_curPnt && m_iInter < n_inter); 01086 } 01087 } 01088 } 01089 01090 return true; 01091 } 01092 01093 bool EBMesher::is_shared_overlapped_surf(int index) 01094 { 01095 int nParent; 01096 iBase_ErrorType err; 01097 moab::EntityHandle hSurf; 01098 if (m_bUseGeom) { 01099 hSurf = m_vhInterSurf[m_vIntersection[index].index]; 01100 err = mk_core()->imesh_instance()->getNumPrnt(reinterpret_cast<iBase_EntitySetHandle> (hSurf), 01101 1, nParent); 01102 IBERRCHK(err, "Failed to get number of surface parents.\n"); 01103 01104 if (nParent > 1) return true; 01105 } 01106 else hSurf = m_vIntersection[index].index; 01107 01108 return m_mhOverlappedSurf.count(hSurf) > 0; 01109 } 01110 01111 void EBMesher::get_grid_and_edges_techX(double* boxMin, double* boxMax, int* nDiv, 01112 std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >& rmdCutCellSurfEdge, 01113 std::vector<int>& rvnInsideCell, bool isCornerExterior) 01114 { 01115 int i, j, err, ii, jj, kk, iHex; 01116 for (i = 0; i < 3; i++) { 01117 boxMin[i] = m_origin_coords[i]; 01118 boxMax[i] = m_origin_coords[i] + m_dIntervalSize[i]*m_nDiv[i]; 01119 nDiv[i] = m_nDiv[i]; 01120 } 01121 01122 // get all hexes 01123 std::vector<iBase_EntityHandle> hex_handles; 01124 err = mk_core()->imesh_instance()->getEntities(m_hRootSet, iBase_REGION, 01125 iMesh_HEXAHEDRON, hex_handles); 01126 IBERRCHK(err, "Failed to get hexes.\n"); 01127 01128 // get hex status 01129 int hex_size = hex_handles.size(); 01130 /* 01131 //int* hex_status = new int[hex_size]; 01132 //int* hex_status; 01133 //std::vector<int> hex_status(hex_size); 01134 int temp = 0; 01135 int* hex_status = &temp; 01136 err = mk_core()->imesh_instance()->getIntArrData(&hex_handles[0], hex_size, 01137 m_elemStatusTag, hex_status); 01138 */ 01139 int error; 01140 int* hex_status = new int[hex_size]; 01141 int hex_status_alloc = sizeof(int)*hex_size; 01142 int hex_status_size = 0; 01143 iMesh_getIntArrData(m_mesh, &hex_handles[0], 01144 hex_size, m_elemStatusTag, 01145 &hex_status, &hex_status_alloc, 01146 &hex_status_size, &error); 01147 IBERRCHK(error, "Failed to get hex status."); 01148 01149 // get inside and boundary hexes 01150 int nInside = 0; 01151 int nOutside = 0; 01152 int nBoundary = 0; 01153 rvnInsideCell.clear(); 01154 for (i = 0; i < hex_size; i++) { 01155 if (hex_status[i] == 0) { // if inside 01156 iHex = moab_instance()->id_from_handle(reinterpret_cast<moab::EntityHandle> 01157 (hex_handles[i])) - m_iStartHex; 01158 rvnInsideCell.push_back((iHex%(m_nDiv[0]*m_nDiv[1]))%m_nDiv[0]); 01159 rvnInsideCell.push_back((iHex%(m_nDiv[0]*m_nDiv[1]))/m_nDiv[0]); 01160 rvnInsideCell.push_back(iHex/m_nDiv[0]/m_nDiv[1]); 01161 nInside++; 01162 } 01163 else if (hex_status[i] == 1) nOutside++; 01164 else if (hex_status[i] == 2) nBoundary++; 01165 else IBERRCHK(err, "Element status should be one of inside/outside/boundary."); 01166 } 01167 std::cout << "# of inside, outside, boundary elem: " << nInside 01168 << ", " << nOutside << ", " << nBoundary << std::endl; 01169 delete [] hex_status; 01170 01171 // get cut-cell fractions 01172 double dFrac[4]; 01173 std::map<int, CutFraction>::iterator iter = m_mdCutFraction.begin(); 01174 std::map<int, CutFraction>::iterator end_iter = m_mdCutFraction.end(); 01175 01176 for (; iter != end_iter; iter++) { // for each cut-cell 01177 // get i, j, k index from handle 01178 iHex = iter->first; 01179 ii = (iHex%(m_nDiv[0]*m_nDiv[1]))%m_nDiv[0]; 01180 jj = (iHex%(m_nDiv[0]*m_nDiv[1]))/m_nDiv[0]; 01181 kk = iHex/m_nDiv[0]/m_nDiv[1]; 01182 01183 // surface 1 01184 CutFraction cutFrac = iter->second; 01185 if (cutFrac.fraction[1].size() > 0) { 01186 dFrac[0] = cutFrac.fraction[1][0]; 01187 if (dFrac[0] < 0.) dFrac[0] *= -1.; 01188 } 01189 else dFrac[0] = -1.; 01190 if (cutFrac.fraction[2].size() > 0) { 01191 dFrac[3] = cutFrac.fraction[2][0]; 01192 if (dFrac[3] < 0.) dFrac[3] *= -1.; 01193 } 01194 else dFrac[3] = -1.; 01195 dFrac[1] = get_edge_fraction(iHex + m_nDiv[0], 2); 01196 dFrac[2] = get_edge_fraction(iHex + m_nDiv[0]*m_nDiv[1], 1); 01197 01198 if (dFrac[0] > 0. || dFrac[1] > 0. || dFrac[2] > 0. || dFrac[3] > 0.) { // if surface is cut 01199 CutCellSurfEdgeKey surfKey(ii, jj, kk, 0); 01200 std::vector<double> edges; 01201 if (dFrac[0] < 0.) dFrac[0] = get_uncut_edge_fraction(ii, jj, kk, 1); 01202 if (dFrac[1] < 0.) dFrac[1] = get_uncut_edge_fraction(ii, jj + 1, kk, 2); 01203 if (dFrac[2] < 0.) dFrac[2] = get_uncut_edge_fraction(ii, jj, kk + 1, 1); 01204 if (dFrac[3] < 0.) dFrac[3] = get_uncut_edge_fraction(ii, jj, kk, 2); 01205 for (j = 0; j < 4; j++) edges.push_back(dFrac[j]); 01206 rmdCutCellSurfEdge[surfKey] = edges; 01207 } 01208 01209 // surface 2 01210 cutFrac = iter->second; 01211 if (cutFrac.fraction[0].size() > 0) { 01212 dFrac[0] = cutFrac.fraction[0][0]; 01213 if (dFrac[0] < 0.) dFrac[0] *= -1.; 01214 } 01215 else dFrac[0] = -1.; 01216 if (cutFrac.fraction[1].size() > 0) { 01217 dFrac[3] = cutFrac.fraction[1][0]; 01218 if (dFrac[3] < 0.) dFrac[3] *= -1.; 01219 } 01220 else dFrac[3] = -1.; 01221 dFrac[1] = get_edge_fraction(iHex + 1, 2); 01222 dFrac[2] = get_edge_fraction(iHex + m_nDiv[0]*m_nDiv[1], 0); 01223 01224 if (dFrac[0] > 0. || dFrac[1] > 0. || dFrac[2] > 0. || dFrac[3] > 0.) { // if surface is cut 01225 CutCellSurfEdgeKey surfKey(ii, jj, kk, 1); 01226 std::vector<double> edges; 01227 if (dFrac[0] < 0.) dFrac[0] = get_uncut_edge_fraction(ii, jj, kk, 0); 01228 if (dFrac[1] < 0.) dFrac[1] = get_uncut_edge_fraction(ii + 1, jj, kk, 2); 01229 if (dFrac[2] < 0.) dFrac[2] = get_uncut_edge_fraction(ii, jj, kk + 1, 0); 01230 if (dFrac[3] < 0.) dFrac[3] = get_uncut_edge_fraction(ii, jj, kk, 2); 01231 for (j = 0; j < 4; j++) edges.push_back(dFrac[j]); 01232 rmdCutCellSurfEdge[surfKey] = edges; 01233 } 01234 01235 // surface 3 01236 cutFrac = iter->second; 01237 if (cutFrac.fraction[0].size() > 0) { 01238 dFrac[0] = cutFrac.fraction[0][0]; 01239 if (dFrac[0] < 0.) dFrac[0] *= -1.; 01240 } 01241 else dFrac[0] = -1.; 01242 if (cutFrac.fraction[1].size() > 0) { 01243 dFrac[3] = cutFrac.fraction[1][0]; 01244 if (dFrac[3] < 0.) dFrac[3] *= -1.; 01245 } 01246 else dFrac[3] = -1.; 01247 dFrac[1] = get_edge_fraction(iHex + 1, 1); 01248 dFrac[2] = get_edge_fraction(iHex + m_nDiv[0], 0); 01249 01250 if (dFrac[0] > 0. || dFrac[1] > 0. || dFrac[2] > 0. || dFrac[3] > 0.) { // if surface is cut 01251 CutCellSurfEdgeKey surfKey(ii, jj, kk, 2); 01252 std::vector<double> edges; 01253 if (dFrac[0] < 0.) dFrac[0] = get_uncut_edge_fraction(ii, jj, kk, 0); 01254 if (dFrac[1] < 0.) dFrac[1] = get_uncut_edge_fraction(ii + 1, jj, kk, 1); 01255 if (dFrac[2] < 0.) dFrac[2] = get_uncut_edge_fraction(ii, jj + 1, kk, 0); 01256 if (dFrac[3] < 0.) dFrac[3] = get_uncut_edge_fraction(ii, jj, kk, 1); 01257 for (j = 0; j < 4; j++) edges.push_back(dFrac[j]); 01258 rmdCutCellSurfEdge[surfKey] = edges; 01259 } 01260 } 01261 01262 if (debug_ebmesh) export_fraction_edges(rmdCutCellSurfEdge); 01263 } 01264 01265 bool EBMesher::get_grid_and_edges(double* boxMin, double* boxMax, int* nDiv, 01266 std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >& rmdCutCellEdge, 01267 std::vector<int>& rvnInsideCell, bool isCornerExterior) 01268 { 01269 int i, ii, jj, kk, iHex; 01270 for (i = 0; i < 3; i++) { 01271 boxMin[i] = m_origin_coords[i]; 01272 boxMax[i] = m_origin_coords[i] + m_dIntervalSize[i]*m_nDiv[i]; 01273 nDiv[i] = m_nDiv[i]; 01274 } 01275 01276 if (!get_inside_hex(rvnInsideCell)) return false; 01277 01278 // get cut-cell fractions 01279 std::map<int, CutFraction>::iterator iter = m_mdCutFraction.begin(); 01280 std::map<int, CutFraction>::iterator end_iter = m_mdCutFraction.end(); 01281 01282 for (; iter != end_iter; iter++) { // for each cut-cell 01283 // get i, j, k index from handle 01284 iHex = iter->first; 01285 ii = (iHex%(m_nDiv[0]*m_nDiv[1]))%m_nDiv[0]; 01286 jj = (iHex%(m_nDiv[0]*m_nDiv[1]))/m_nDiv[0]; 01287 kk = iHex/m_nDiv[0]/m_nDiv[1]; 01288 01289 for (i = 0; i < 3; i++) { 01290 std::vector<double> fractions(iter->second.fraction[i]); 01291 CutCellSurfEdgeKey edgeKey(ii, jj, kk, i); 01292 rmdCutCellEdge[edgeKey] = fractions; 01293 } 01294 } 01295 01296 if (debug_ebmesh) return export_fraction_points(rmdCutCellEdge); 01297 01298 return true; 01299 } 01300 01301 bool EBMesher::get_inside_hex(std::vector<int>& rvnInsideCell) 01302 { 01303 int i, err, iHex; 01304 01305 // get all hexes 01306 std::vector<iBase_EntityHandle> hex_handles; 01307 err = mk_core()->imesh_instance()->getEntities(m_hRootSet, iBase_REGION, 01308 iMesh_HEXAHEDRON, hex_handles); 01309 IBERRCHK(err, "Failed to get hexes.\n"); 01310 01311 // get hex status 01312 int hex_size = hex_handles.size(); 01313 /* 01314 //int* hex_status = new int[hex_size]; 01315 //int* hex_status; 01316 std::vector<int> hex_status(hex_size); 01317 err = mk_core()->imesh_instance()->getIntArrData(&hex_handles[0], hex_size, 01318 m_elemStatusTag, &hex_status[0]); 01319 */ 01320 int error; 01321 int* hex_status = new int[hex_size]; 01322 int hex_status_alloc = sizeof(int)*hex_size; 01323 int hex_status_size = 0; 01324 iMesh_getIntArrData(m_mesh, &hex_handles[0], 01325 hex_size, m_elemStatusTag, 01326 &hex_status, &hex_status_alloc, 01327 &hex_status_size, &error); 01328 ERRORRF("Failed to get hex status.\n"); 01329 01330 // get inside and boundary hexes 01331 int nInside = 0; 01332 int nOutside = 0; 01333 int nBoundary = 0; 01334 rvnInsideCell.clear(); 01335 for (i = 0; i < hex_size; i++) { 01336 if (hex_status[i] == 0) { // if inside 01337 iHex = moab_instance()->id_from_handle(reinterpret_cast<moab::EntityHandle> 01338 (hex_handles[i])) - m_iStartHex; 01339 rvnInsideCell.push_back((iHex%(m_nDiv[0]*m_nDiv[1]))%m_nDiv[0]); 01340 rvnInsideCell.push_back((iHex%(m_nDiv[0]*m_nDiv[1]))/m_nDiv[0]); 01341 rvnInsideCell.push_back(iHex/m_nDiv[0]/m_nDiv[1]); 01342 nInside++; 01343 } 01344 else if (hex_status[i] == 1) nOutside++; 01345 else if (hex_status[i] == 2) nBoundary++; 01346 else ERRORRF("Element status should be one of inside/outside/boundary.\n"); 01347 } 01348 std::cout << "# of inside, outside, boundary elem: " << nInside 01349 << ", " << nOutside << ", " << nBoundary << std::endl; 01350 01351 delete [] hex_status; 01352 return true; 01353 } 01354 01355 bool EBMesher::export_fraction_edges(std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >& mdCutCellSurfEdge) 01356 { 01357 // export fractions as edge 01358 double curPnt[3], ePnt[6]; 01359 std::vector<iBase_EntityHandle> edge_handles; 01360 std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >::iterator itr = mdCutCellSurfEdge.begin(); 01361 std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >::iterator e_itr = mdCutCellSurfEdge.end(); 01362 for (; itr != e_itr; itr++) { 01363 curPnt[0] = m_origin_coords[0] + itr->first.i*m_dIntervalSize[0]; 01364 curPnt[1] = m_origin_coords[1] + itr->first.j*m_dIntervalSize[1]; 01365 curPnt[2] = m_origin_coords[2] + itr->first.k*m_dIntervalSize[2]; 01366 std::vector<double> edges = itr->second; 01367 01368 if (itr->first.l == 0) { 01369 if (edges[0] > 0. && edges[0] < 1.) { 01370 ePnt[0] = curPnt[0]; 01371 ePnt[1] = curPnt[1]; 01372 ePnt[2] = curPnt[2]; 01373 ePnt[3] = ePnt[0]; 01374 ePnt[4] = ePnt[1] + edges[0]*m_dIntervalSize[1]; 01375 ePnt[5] = ePnt[2]; 01376 if (!make_edge(ePnt, edge_handles)) return false; 01377 } 01378 if (edges[1] > 0. && edges[1] < 1.) { 01379 ePnt[0] = curPnt[0]; 01380 ePnt[1] = curPnt[1] + m_dIntervalSize[1]; 01381 ePnt[2] = curPnt[2]; 01382 ePnt[3] = ePnt[0]; 01383 ePnt[4] = ePnt[1]; 01384 ePnt[5] = ePnt[2] + edges[1]*m_dIntervalSize[2]; 01385 if (!make_edge(ePnt, edge_handles)) return false; 01386 } 01387 if (edges[2] > 0. && edges[2] < 1.) { 01388 ePnt[0] = curPnt[0]; 01389 ePnt[1] = curPnt[1]; 01390 ePnt[2] = curPnt[2] + m_dIntervalSize[2]; 01391 ePnt[3] = ePnt[0]; 01392 ePnt[4] = ePnt[1] + edges[2]*m_dIntervalSize[1]; 01393 ePnt[5] = ePnt[2]; 01394 if (!make_edge(ePnt, edge_handles)) return false; 01395 } 01396 if (edges[3] > 0. && edges[3] < 1.) { 01397 ePnt[0] = curPnt[0]; 01398 ePnt[1] = curPnt[1]; 01399 ePnt[2] = curPnt[2]; 01400 ePnt[3] = ePnt[0]; 01401 ePnt[4] = ePnt[1]; 01402 ePnt[5] = ePnt[2] + edges[3]*m_dIntervalSize[2]; 01403 if (!make_edge(ePnt, edge_handles)) return false; 01404 } 01405 } 01406 if (itr->first.l == 1) { 01407 if (edges[0] > 0. && edges[0] < 1.) { 01408 ePnt[0] = curPnt[0]; 01409 ePnt[1] = curPnt[1]; 01410 ePnt[2] = curPnt[2]; 01411 ePnt[3] = ePnt[0] + edges[0]*m_dIntervalSize[0]; 01412 ePnt[4] = ePnt[1]; 01413 ePnt[5] = ePnt[2]; 01414 if (!make_edge(ePnt, edge_handles)) return false; 01415 } 01416 if (edges[1] > 0. && edges[1] < 1.) { 01417 ePnt[0] = curPnt[0] + m_dIntervalSize[0]; 01418 ePnt[1] = curPnt[1]; 01419 ePnt[2] = curPnt[2]; 01420 ePnt[3] = ePnt[0]; 01421 ePnt[4] = ePnt[1]; 01422 ePnt[5] = ePnt[2] + edges[1]*m_dIntervalSize[2]; 01423 if (!make_edge(ePnt, edge_handles)) return false; 01424 } 01425 if (edges[2] > 0. && edges[2] < 1.) { 01426 ePnt[0] = curPnt[0]; 01427 ePnt[1] = curPnt[1]; 01428 ePnt[2] = curPnt[2] + m_dIntervalSize[2]; 01429 ePnt[3] = ePnt[0] + edges[2]*m_dIntervalSize[0]; 01430 ePnt[4] = ePnt[1]; 01431 ePnt[5] = ePnt[2]; 01432 if (!make_edge(ePnt, edge_handles)) return false; 01433 } 01434 if (edges[3] > 0. && edges[3] < 1.) { 01435 ePnt[0] = curPnt[0]; 01436 ePnt[1] = curPnt[1]; 01437 ePnt[2] = curPnt[2]; 01438 ePnt[3] = ePnt[0]; 01439 ePnt[4] = ePnt[1]; 01440 ePnt[5] = ePnt[2] + edges[3]*m_dIntervalSize[2]; 01441 if (!make_edge(ePnt, edge_handles)) return false; 01442 } 01443 } 01444 if (itr->first.l == 2) { 01445 if (edges[0] > 0. && edges[0] < 1.) { 01446 ePnt[0] = curPnt[0]; 01447 ePnt[1] = curPnt[1]; 01448 ePnt[2] = curPnt[2]; 01449 ePnt[3] = ePnt[0] + edges[0]*m_dIntervalSize[0]; 01450 ePnt[4] = ePnt[1]; 01451 ePnt[5] = ePnt[2]; 01452 if (!make_edge(ePnt, edge_handles)) return false; 01453 } 01454 if (edges[1] > 0. && edges[1] < 1.) { 01455 ePnt[0] = curPnt[0] + m_dIntervalSize[0]; 01456 ePnt[1] = curPnt[1]; 01457 ePnt[2] = curPnt[2]; 01458 ePnt[3] = ePnt[0]; 01459 ePnt[4] = ePnt[1] + edges[1]*m_dIntervalSize[1]; 01460 ePnt[5] = ePnt[2]; 01461 if (!make_edge(ePnt, edge_handles)) return false; 01462 } 01463 if (edges[2] > 0. && edges[2] < 1.) { 01464 ePnt[0] = curPnt[0]; 01465 ePnt[1] = curPnt[1] + m_dIntervalSize[2]; 01466 ePnt[2] = curPnt[2]; 01467 ePnt[3] = ePnt[0] + edges[2]*m_dIntervalSize[0]; 01468 ePnt[4] = ePnt[1]; 01469 ePnt[5] = ePnt[2]; 01470 if (!make_edge(ePnt, edge_handles)) return false; 01471 } 01472 if (edges[3] > 0. && edges[3] < 1.) { 01473 ePnt[0] = curPnt[0]; 01474 ePnt[1] = curPnt[1]; 01475 ePnt[2] = curPnt[2]; 01476 ePnt[3] = ePnt[0]; 01477 ePnt[4] = ePnt[1] + edges[3]*m_dIntervalSize[1]; 01478 ePnt[5] = ePnt[2]; 01479 if (!make_edge(ePnt, edge_handles)) return false; 01480 } 01481 } 01482 } 01483 01484 int is_list = 1; 01485 iBase_EntitySetHandle set; 01486 iBase_ErrorType err; 01487 err = mk_core()->imesh_instance()->createEntSet(is_list, set); 01488 IBERRCHK(err, "Couldn't create set."); 01489 01490 err = mk_core()->imesh_instance()->addEntArrToSet(&edge_handles[0], 01491 edge_handles.size(), set); 01492 IBERRCHK(err, "Couldn't add edges to set."); 01493 01494 moab::ErrorCode rval = moab_instance()->write_mesh("edges.vtk", 01495 (const moab::EntityHandle*) &set, 1); 01496 MBERRCHK(rval, mk_core()->moab_instance()); 01497 01498 return true; 01499 } 01500 01501 bool EBMesher::export_fraction_points(std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >& mdCutCellEdge) 01502 { 01503 // export fractions as edge 01504 int i, j, dir, nFrc; 01505 iBase_ErrorType err; 01506 double curPnt[3], fracPnt[3], frac; 01507 iBase_EntityHandle v_handle; 01508 std::vector<iBase_EntityHandle> vertex_handles; 01509 std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >::iterator itr = mdCutCellEdge.begin(); 01510 std::map< CutCellSurfEdgeKey, std::vector<double>, LessThan >::iterator e_itr = mdCutCellEdge.end(); 01511 for (; itr != e_itr; itr++) { 01512 curPnt[0] = m_origin_coords[0] + itr->first.i*m_dIntervalSize[0]; 01513 curPnt[1] = m_origin_coords[1] + itr->first.j*m_dIntervalSize[1]; 01514 curPnt[2] = m_origin_coords[2] + itr->first.k*m_dIntervalSize[2]; 01515 dir = itr->first.l; 01516 nFrc = itr->second.size(); 01517 01518 for (i = 0; i < nFrc; i++) { 01519 frac = itr->second[i]; 01520 if (frac > 0. && frac < 1.) { 01521 for (j = 0; j < 3; j++) { 01522 if (j == dir) fracPnt[j] = curPnt[j] + frac*m_dIntervalSize[j]; 01523 else fracPnt[j] = curPnt[j]; 01524 } 01525 err = mk_core()->imesh_instance()->createVtx(fracPnt[0], fracPnt[1], 01526 fracPnt[2], v_handle); 01527 IBERRCHK(err, "Couldn't create vertex."); 01528 vertex_handles.push_back(v_handle); 01529 } 01530 } 01531 } 01532 01533 int is_list = 1; 01534 moab::ErrorCode result; 01535 iBase_EntitySetHandle set; 01536 err = mk_core()->imesh_instance()->createEntSet(is_list, set); 01537 IBERRCHK(err, "Couldn't create set."); 01538 01539 err = mk_core()->imesh_instance()->addEntArrToSet(&vertex_handles[0], 01540 vertex_handles.size(), set); 01541 IBERRCHK(err, "Couldn't add vertices to set."); 01542 01543 result = moab_instance()->write_mesh("frac_vertices.vtk", 01544 (const moab::EntityHandle*) &set, 1); 01545 if (MB_SUCCESS != result) { 01546 std::cerr << "Failed to write fraction vertices." << std::endl; 01547 return false; 01548 } 01549 01550 return true; 01551 } 01552 01553 bool EBMesher::make_edge(double ePnt[6], std::vector<iBase_EntityHandle>& edge_handles) 01554 { 01555 iBase_ErrorType err; 01556 iBase_EntityHandle vertex_handle[2], edge_handle; 01557 iBase_EntityHandle* pVertexHandle = &vertex_handle[0]; 01558 err = mk_core()->imesh_instance()->createVtxArr(2, iBase_INTERLEAVED, 01559 ePnt, pVertexHandle); 01560 IBERRCHK(err, "Failed to create vertices.\n"); 01561 01562 err = mk_core()->imesh_instance()->createEnt(iMesh_LINE_SEGMENT, 01563 &vertex_handle[0], 2, 01564 edge_handle); 01565 IBERRCHK(err, "Failed to create edge.\n"); 01566 01567 edge_handles.push_back(edge_handle); 01568 01569 return true; 01570 } 01571 01572 double EBMesher::get_edge_fraction(int idHex, int dir) 01573 { 01574 std::map<int, CutFraction>::iterator end_iter = m_mdCutFraction.end(); 01575 std::map<int, CutFraction>::iterator iter = m_mdCutFraction.find(idHex); 01576 if (iter != end_iter && iter->second.fraction[dir].size() > 0) { 01577 double frac = iter->second.fraction[dir][0]; 01578 if (frac < 0.) frac *= -1.; 01579 return frac; 01580 } 01581 else return -1.; 01582 } 01583 #endif 01584 01585 double EBMesher::get_uncut_edge_fraction(int i, int j, int k, int dir) 01586 { 01587 int iEdge; 01588 01589 if (dir == 0) { 01590 if (j == m_nDiv[1] || k == m_nDiv[2]) return 0.; // return outside 01591 iEdge = k*m_nDiv[0]*m_nDiv[1] + j*m_nDiv[0] + i; 01592 } 01593 else if (dir == 1) { 01594 if (i == m_nDiv[0] || k == m_nDiv[2]) return 0.; // return outside 01595 iEdge = i*m_nDiv[1]*m_nDiv[2] + k*m_nDiv[1] + j; 01596 } 01597 else if (dir == 2) { 01598 if (i == m_nDiv[0] || j == m_nDiv[1]) return 0.; // return outside 01599 iEdge = j*m_nDiv[0]*m_nDiv[2] + i*m_nDiv[2] + k; 01600 } 01601 else return -1.; 01602 01603 EdgeStatus edgeStatus = m_vnEdgeStatus[dir][iEdge]; 01604 if (edgeStatus == INSIDE) return 1.; 01605 else if (edgeStatus == OUTSIDE) return 0.; 01606 else return -1.; 01607 } 01608 01609 #ifdef HAVE_MOAB 01610 bool EBMesher::move_ray(int& nIntersect, double* startPnt, double* endPnt, 01611 double tol, int dir, bool bSpecialCase) 01612 { 01613 //int i, nIteration; 01614 int i; 01615 bool bMove = true; 01616 01617 if (bSpecialCase) m_iOverlap = 0; 01618 01619 while (bMove) { 01620 if (m_nIteration > 10) { 01621 if (bSpecialCase) return true; // special case 01622 else if (m_bUseGeom) { // shared/overlapped, faceting case 01623 m_mhOverlappedSurf[m_iOverlap] = 0; 01624 m_mhOverlappedSurf[m_iOverlap + 1] = 0; 01625 return true; 01626 } 01627 else { 01628 return false; 01629 } 01630 } 01631 01632 for (i = 0; i < 3; i++) { 01633 if (i != dir) { 01634 startPnt[i] += tol; 01635 endPnt[i] += tol; 01636 } 01637 } 01638 01639 MBCartVect ray(endPnt[0] - startPnt[0], endPnt[1] - startPnt[1], endPnt[2] - startPnt[2]); 01640 double rayLength = ray.length(); 01641 moab::ErrorCode rVal; 01642 ray.normalize(); 01643 m_vIntersection.clear(); 01644 m_vhInterSurf.clear(); 01645 m_vhInterFacet.clear(); 01646 01647 std::vector<double> temp_intersects; 01648 if (m_bUseGeom) { 01649 rVal = m_hObbTree->ray_intersect_sets(temp_intersects, m_vhInterSurf, 01650 m_vhInterFacet, m_hTreeRoot, tol, 01651 -1, startPnt, ray.array(), &rayLength); 01652 } 01653 else { // facet input 01654 std::vector<moab::EntityHandle> dum_facets_out; 01655 rVal = m_hObbTree->ray_intersect_triangles(temp_intersects, dum_facets_out, 01656 m_hTreeRoot, tol, 01657 startPnt, ray.array(), &rayLength); 01658 m_vhInterSurf.resize(temp_intersects.size()); 01659 } 01660 01661 if (MB_SUCCESS != rVal) { 01662 std::cerr << "Failed : ray-triangle intersection." << std::endl; 01663 return false; 01664 } 01665 01666 nIntersect = temp_intersects.size(); 01667 m_vIntersection.resize(nIntersect); 01668 for (i = 0; i < nIntersect; i++) { 01669 IntersectDist temp_inter_dist(temp_intersects[i], i); 01670 m_vIntersection[i] = temp_inter_dist; 01671 } 01672 std::sort(m_vIntersection.begin(), m_vIntersection.end(), less_intersect); 01673 bMove = is_ray_move_and_set_overlap_surf(bSpecialCase); 01674 m_nIteration++; 01675 } 01676 01677 std::cout << "ray is moved successfully." << std::endl; 01678 01679 return true; 01680 } 01681 #endif 01682 01683 bool EBMesher::is_ray_move_and_set_overlap_surf(bool& bSpecialCase) 01684 { 01685 int nInter = m_vIntersection.size() - 1; 01686 01687 while (m_iOverlap < nInter) { 01688 if (m_vIntersection[m_iOverlap + 1].distance - m_vIntersection[m_iOverlap].distance < 1e-7) { 01689 if (m_bUseGeom) { 01690 moab::EntityHandle h1 = m_vhInterSurf[m_vIntersection[m_iOverlap].index]; 01691 moab::EntityHandle h2 = m_vhInterSurf[m_vIntersection[m_iOverlap + 1].index]; 01692 01693 if (h1 == h2) { // remove too close case 01694 bSpecialCase = false; 01695 return true; 01696 } 01697 else if (m_nIteration < 10) { // when ray intesect shared edge by 2 triangles 01698 bSpecialCase = true; 01699 return true; 01700 } 01701 else { // overlapped surfaces 01702 m_mhOverlappedSurf[h1] = 0; 01703 m_mhOverlappedSurf[h2] = 0; 01704 m_nIteration = 0; 01705 m_iOverlap++; 01706 } 01707 } 01708 else { 01709 if (m_nIteration < 10) { // when ray intesect shared edge by 2 triangles 01710 bSpecialCase = true; 01711 return true; 01712 } 01713 else { // overlapped surfaces 01714 //bSpecialCase = false; 01715 //m_nIteration = 0; 01716 //m_iOverlap++; 01717 m_vIntersection.erase(m_vIntersection.begin() + m_iOverlap + 1); 01718 nInter = m_vIntersection.size(); 01719 m_vhInterSurf.resize(nInter); 01720 //m_nIteration = 0; 01721 } 01722 } 01723 } 01724 else m_iOverlap++; 01725 } 01726 01727 return false; 01728 } 01729 01730 void EBMesher::remove_intersection_duplicates() 01731 { 01732 int ind = 0; 01733 int nInter = m_vIntersection.size() - 1; 01734 01735 while (ind < nInter) { 01736 if (m_vIntersection[ind + 1].distance - m_vIntersection[ind].distance < 1e-7) { 01737 moab::EntityHandle h1 = m_vhInterSurf[m_vIntersection[ind].index]; 01738 moab::EntityHandle h2 = m_vhInterSurf[m_vIntersection[ind + 1].index]; 01739 01740 if (h1 != h2) { // overlapped/shared surfaces 01741 std::vector<iBase_EntitySetHandle> parents_out1, parents_out2; 01742 int err = mk_core()->imesh_instance()->getPrnts(reinterpret_cast<iBase_EntitySetHandle> (h1), 1, parents_out1); 01743 IBERRCHK(err, "Failed to get number of surface parents.\n"); 01744 err = mk_core()->imesh_instance()->getPrnts(reinterpret_cast<iBase_EntitySetHandle> (h2), 1, parents_out2); 01745 IBERRCHK(err, "Failed to get number of surface parents.\n"); 01746 if (parents_out1.size() == 1 && parents_out2.size() == 1) { 01747 if (parents_out1[0] != parents_out2[0]) { // parent volues are also different 01748 m_mhOverlappedSurf[h1] = 0; 01749 m_mhOverlappedSurf[h2] = 0; 01750 } 01751 } 01752 } 01753 m_vIntersection.erase(m_vIntersection.begin() + ind + 1); 01754 nInter--; 01755 } 01756 else ind++; 01757 } 01758 } 01759 01760 bool EBMesher::get_volume_fraction(int vol_frac_div) 01761 { 01762 std::cout << "starting get_volume_fraction." << std::endl; 01763 int i, j, k, l, n, iHex, dir, nIntersect, rayIndex[3], index[3], 01764 otherDir1, otherDir2, err, nParent; 01765 (void) otherDir1; 01766 (void) otherDir2; 01767 double tolerance = 1e-12, dDistance, elem_origin[3], 01768 elem_interval_size[3], startPnt[3], endPnt[3], rayMaxEnd[3]; 01769 moab::ErrorCode rval; 01770 bool bOverlapSecond, bClosed; 01771 std::vector<iBase_EntityHandle> edge_handles; 01772 01773 double dTotEdgeElem = 0.; 01774 for (i = 0; i < 3; i++) { 01775 rayMaxEnd[i] = m_origin_coords[i] + m_nDiv[i]*m_dIntervalSize[i]; 01776 dTotEdgeElem += m_dIntervalSize[i]*(vol_frac_div + 1)*(vol_frac_div + 1); 01777 } 01778 01779 // get all hexes 01780 std::vector<iBase_EntityHandle> hex_handles; 01781 err = mk_core()->imesh_instance()->getEntities(m_hRootSet, iBase_REGION, 01782 iMesh_HEXAHEDRON, hex_handles); 01783 IBERRCHK(err, "Failed to get hexes.\n"); 01784 01785 int hex_size = hex_handles.size(); 01786 /* 01787 std::vector<int> hex_status(hex_size); 01788 //int* hex_status = NULL; 01789 err = mk_core()->imesh_instance()->getIntArrData(&hex_handles[0], hex_size, 01790 m_elemStatusTag, &hex_status[0]); 01791 */ 01792 int error; 01793 std::vector<int> frac_length; 01794 int* hex_status = new int[hex_size]; 01795 int hex_status_alloc = sizeof(int)*hex_size; 01796 int hex_status_size = 0; 01797 iMesh_getIntArrData(m_mesh, &hex_handles[0], 01798 hex_size, m_elemStatusTag, 01799 &hex_status, &hex_status_alloc, 01800 &hex_status_size, &error); 01801 ERRORRF("Failed to get hex status.\n"); 01802 01803 for (n = 0; n < hex_size; n++) { 01804 if (hex_status[n] == 2) { // just boundary 01805 std::map<moab::EntityHandle, VolFrac> vol_fraction; 01806 std::map<moab::EntityHandle, VolFrac>::iterator vf_iter; 01807 std::map<moab::EntityHandle, VolFrac>::iterator vf_end_iter; 01808 iHex = moab_instance()->id_from_handle(reinterpret_cast<moab::EntityHandle> 01809 (hex_handles[n])) - m_iStartHex; 01810 index[0] = (iHex%(m_nDiv[0]*m_nDiv[1]))%m_nDiv[0]; 01811 index[1] = (iHex%(m_nDiv[0]*m_nDiv[1]))/m_nDiv[0]; 01812 index[2] = iHex/m_nDiv[0]/m_nDiv[1]; 01813 01814 for (i = 0; i < 3; i++) { 01815 elem_origin[i] = m_origin_coords[i] + index[i]*m_dIntervalSize[i]; 01816 elem_interval_size[i] = m_dIntervalSize[i]/vol_frac_div; 01817 } 01818 01819 for (dir = 0; dir < 3; dir++) { // x, y, z directions 01820 otherDir1 = (dir + 1)%3; 01821 otherDir2 = (dir + 2)%3; 01822 01823 for (j = 0; j < vol_frac_div + 1; j++) { 01824 for (i = 0; i < vol_frac_div + 1; i++) { 01825 // get ray start and end points 01826 if (dir == 0) { // x coordinate ray 01827 rayIndex[0] = 0; 01828 rayIndex[1] = i; 01829 rayIndex[2] = j; 01830 } 01831 else if (dir == 1) { // y coordinate ray 01832 rayIndex[0] = j; 01833 rayIndex[1] = 0; 01834 rayIndex[2] = i; 01835 } 01836 else if (dir == 2) { // z coordinate ray 01837 rayIndex[0] = i; 01838 rayIndex[1] = j; 01839 rayIndex[2] = 0; 01840 } 01841 else IBERRCHK(iBase_FAILURE, "Ray direction should be from 0 to 2."); 01842 01843 for (k = 0; k < 3; k++) { 01844 if (k == dir) { 01845 startPnt[k] = elem_origin[k]; 01846 endPnt[k] = startPnt[k] + m_dIntervalSize[k]; 01847 } 01848 else { 01849 startPnt[k] = elem_origin[k] + rayIndex[k]*elem_interval_size[k]; 01850 endPnt[k] = startPnt[k]; 01851 } 01852 } 01853 01854 // ray-tracing 01855 if (!fire_ray(nIntersect, startPnt, endPnt, 01856 tolerance, dir, m_dIntervalSize[dir])) return iBase_FAILURE; 01857 01858 if (nIntersect > 0) { // ray is intersected 01859 bOverlapSecond = false; 01860 bClosed = true; 01861 for (k = 0; k < nIntersect; k++) { 01862 std::vector<moab::EntityHandle> parents; 01863 //MBRange parents; 01864 rval = moab_instance()->get_parent_meshsets(m_vhInterSurf[m_vIntersection[k].index], 01865 parents); 01866 if (rval != MB_SUCCESS) { 01867 std::cerr << "Couldn't get parents." << std::endl; 01868 return false; 01869 } 01870 01871 nParent = parents.size(); 01872 dDistance = m_vIntersection[k].distance; 01873 01874 if (is_shared_overlapped_surf(k)) { 01875 if (nParent == 2) { // shared surface 01876 for (l = 0; l < 2; l++) { 01877 if (l == 1) { 01878 dDistance *= -1.; 01879 bClosed = false; 01880 } 01881 else bClosed = true; 01882 01883 vf_iter = vol_fraction.find(parents[l]); 01884 if (vf_iter == vol_fraction.end()) { 01885 VolFrac temp_vf(dDistance, bClosed); 01886 vol_fraction[parents[l]] = temp_vf; 01887 //std::cout << "iHex=" << iHex << ", vh=" 01888 // << parents[l] << ", dir=" << dir << ", dDistance1=" 01889 // << dDistance << ", vol=" 01890 // << temp_vf.vol << std::endl; 01891 } 01892 else { 01893 vf_iter->second.vol += dDistance; 01894 vf_iter->second.closed = bClosed; 01895 //std::cout << "iHex=" << iHex << ", vh=" 01896 // << vf_iter->first << ", dir=" << dir << ", dDistance1=" 01897 // << dDistance << ", vol=" 01898 // << vf_iter->second.vol << std::endl; 01899 } 01900 } 01901 } 01902 else if (nParent == 1) { // overlapped surface 01903 if (bOverlapSecond) { // second intersection 01904 /* 01905 for (int m = 0; m < 3; m++) { 01906 ePnt[m] = startPnt[m]; 01907 } 01908 ePnt[dir] += dDistance; 01909 */ 01910 dDistance *= -1.; 01911 bClosed = false; 01912 bOverlapSecond = false; 01913 } 01914 else { 01915 /* 01916 // make edge 01917 for (int m = 0; m < 3; m++) { 01918 if (bClosed) ePnt[m] = startPnt[m]; 01919 ePnt[m + 3] = ePnt[m]; 01920 } 01921 ePnt[dir + 3] += dDistance; 01922 if (!make_edge(ePnt, edge_handles)) return iBase_FAILURE; 01923 */ 01924 bOverlapSecond = true;// first intersection 01925 bClosed = true; 01926 } 01927 01928 vf_iter = vol_fraction.find(parents[0]); 01929 if (vf_iter == vol_fraction.end()) { 01930 VolFrac temp_vf(dDistance, bClosed); 01931 vol_fraction[parents[0]] = temp_vf; 01932 //std::cout << "iHex=" << iHex << ", vh=" 01933 // << parents[0] << ", dDistance2=" 01934 // << dDistance << ", vol=" 01935 // << temp_vf.vol << std::endl; 01936 } 01937 else { 01938 vf_iter->second.vol += dDistance; 01939 vf_iter->second.closed = bClosed; 01940 //std::cout << "iHex=" << iHex << ", vh=" 01941 // << vf_iter->first << ", dir=" << dir << ", dDistance2=" 01942 // << dDistance << ", vol=" 01943 // << vf_iter->second.vol << std::endl; 01944 } 01945 } 01946 else return iBase_FAILURE; 01947 } 01948 else { // normal case 01949 if (nParent != 1) return iBase_FAILURE; 01950 01951 if (!is_same_direct_to_ray(k, dir)) { 01952 dDistance *= -1.; // outside 01953 bClosed = false; 01954 } 01955 else bClosed = true; 01956 01957 vf_iter = vol_fraction.find(parents[0]); 01958 if (vf_iter == vol_fraction.end()) { 01959 VolFrac temp_vf(dDistance, bClosed); 01960 vol_fraction[parents[0]] = temp_vf; 01961 //std::cout << "iHex=" << iHex << ", vh=" 01962 // << parents[0] << ", dir=" << dir << ", dDistance3=" 01963 // << dDistance << ", vol=" 01964 // << temp_vf.vol << std::endl; 01965 } 01966 else { 01967 vf_iter->second.vol += dDistance; 01968 vf_iter->second.closed = bClosed; 01969 //std::cout << "iHex=" << iHex << ", vh=" 01970 // << vf_iter->first << ", dir=" << dir << ", dDistance3=" 01971 // << dDistance << ", vol=" 01972 // << vf_iter->second.vol << std::endl; 01973 } 01974 } 01975 } 01976 01977 // if fraction is not closed, add interval size to close 01978 vf_iter = vol_fraction.begin(); 01979 vf_end_iter = vol_fraction.end(); 01980 for (; vf_iter != vf_end_iter; vf_iter++) { 01981 if (!vf_iter->second.closed) { 01982 vf_iter->second.vol += m_dIntervalSize[dir]; 01983 vf_iter->second.closed = true; 01984 /* 01985 for (int m = 0; m < 3; m++) { 01986 ePnt[m + 3] = startPnt[m]; 01987 } 01988 ePnt[dir + 3] += m_dIntervalSize[dir]; 01989 if (!make_edge(ePnt, edge_handles)) return iBase_FAILURE; 01990 */ 01991 //std::cout << "iHex=" << iHex << ", vh=" 01992 // << vf_iter->first << ", dir=" << dir << ", dDistance4=" 01993 // << m_dIntervalSize[dir] << ", vol=" 01994 // << vf_iter->second.vol << std::endl; 01995 } 01996 } 01997 } 01998 else { // decide if it is fully inside 01999 if (!fire_ray(nIntersect, startPnt, rayMaxEnd, 02000 tolerance, dir, m_nDiv[dir]*m_dIntervalSize[dir])) return iBase_FAILURE; 02001 02002 if (nIntersect > 0) { // fully inside 02003 if (is_shared_overlapped_surf(0) || // shared or overlapped 02004 is_same_direct_to_ray(0, dir)) { // other inside case 02005 MBRange parents; 02006 rval = moab_instance()->get_parent_meshsets(m_vhInterSurf[m_vIntersection[0].index], 02007 parents); 02008 if (rval != MB_SUCCESS) { 02009 std::cerr << "Couldn't get parents." << std::endl; 02010 return false; 02011 } 02012 02013 moab::EntityHandle parent_entity = parents.pop_front(); 02014 vf_iter = vol_fraction.find(parent_entity); 02015 if (vf_iter == vf_end_iter) { 02016 VolFrac temp_vf(m_dIntervalSize[dir], true); 02017 vol_fraction[parent_entity] = temp_vf; 02018 //std::cout << "iHex=" << iHex << ", vh=" 02019 // << parents[0] << ", dir=" << dir << ", dDistance5=" 02020 // << dDistance << ", vol=" 02021 // << temp_vf.vol << std::endl; 02022 } 02023 else { 02024 vf_iter->second.vol += m_dIntervalSize[dir]; 02025 vf_iter->second.closed = bClosed; 02026 //std::cout << "iHex=" << iHex << ", vh=" 02027 // << vf_iter->first << ", dir=" << dir << ", dDistance5=" 02028 // << dDistance << ", vol=" 02029 // << vf_iter->second.vol << std::endl; 02030 } 02031 } 02032 } 02033 } 02034 } 02035 } 02036 } 02037 02038 int vol_frac_length = vol_fraction.size(); 02039 std::vector<int> vol_frac_id(vol_frac_length); 02040 std::vector<double> vol_frac(vol_frac_length); 02041 int vol_frac_id_size = vol_frac_length*sizeof(int); 02042 int vol_frac_size = vol_frac_length*sizeof(double); 02043 vf_iter = vol_fraction.begin(); 02044 vf_end_iter = vol_fraction.end(); 02045 for (int m = 0; vf_iter != vf_end_iter; vf_iter++, m++) { 02046 vol_frac_id[m] = vf_iter->first; 02047 vol_frac[m] = vf_iter->second.vol/dTotEdgeElem; 02048 //std::cout << "iHex=" << iHex << ", i=" << index[0] 02049 // << ", j=" << index[1] << ", k=" << index[2] 02050 // << ", vol_handle=" << vf_iter->first 02051 // << ", vol=" << vf_iter->second.vol 02052 // << ", vol_fraction=" << vf_iter->second.vol/dTotEdgeElem 02053 // << std::endl; 02054 } 02055 const void* vol_frac_ids = &vol_frac_id[0]; 02056 const void* vol_fracs = &vol_frac[0]; 02057 02058 // set volume fraction information as tag 02059 rval = moab_instance()->tag_set_data(reinterpret_cast<MBTag> (m_volFracLengthTag), 02060 reinterpret_cast<moab::EntityHandle*> (&hex_handles[n]), 02061 1, &vol_frac_length); 02062 MBERRCHK(rval, mk_core()->moab_instance()); 02063 02064 rval = moab_instance()->tag_set_by_ptr(reinterpret_cast<MBTag> (m_volFracHandleTag), 02065 reinterpret_cast<moab::EntityHandle*> (&hex_handles[n]), 02066 1, &vol_frac_ids, &vol_frac_id_size); 02067 MBERRCHK(rval, mk_core()->moab_instance()); 02068 02069 rval = moab_instance()->tag_set_by_ptr(reinterpret_cast<MBTag> (m_volFracTag), 02070 reinterpret_cast<moab::EntityHandle*> (&hex_handles[n]), 02071 1, &vol_fracs, &vol_frac_size); 02072 MBERRCHK(rval, mk_core()->moab_instance()); 02073 02074 if (debug_ebmesh) { 02075 for (int v = 0; v < vol_frac_length; v++) { 02076 std::cout << "#_boundary_hex_handles=" << hex_handles[n] 02077 << ",vol_frac_handle[" << v << "]=" << vol_frac_id[v] 02078 << ",vol_fracs[" << v << "]=" << vol_frac[v] 02079 << std::endl; 02080 } 02081 } 02082 } 02083 } 02084 02085 std::cout << "end get_volume_fraction." << std::endl; 02086 delete [] hex_status; 02087 02088 return true; 02089 } 02090 02091 #ifdef HAVE_MOAB 02092 bool EBMesher::is_same_direct_to_ray(int i, int dir) 02093 { 02094 MBCartVect coords[3], normal(0.0), ray_dir(rayDir[dir]); 02095 const moab::EntityHandle *conn; 02096 int len; 02097 02098 // get triangle normal vector 02099 moab::ErrorCode rval = moab_instance()->get_connectivity(m_vhInterFacet[m_vIntersection[i].index], 02100 conn, len); 02101 assert(MB_SUCCESS == rval && 3 == len); 02102 02103 rval = moab_instance()->get_coords(conn, 3, coords[0].array()); 02104 assert(MB_SUCCESS == rval); 02105 02106 coords[1] -= coords[0]; 02107 coords[2] -= coords[0]; 02108 normal += coords[1] * coords[2]; 02109 normal.normalize(); 02110 02111 return angle(normal, ray_dir) < .5*PI; 02112 } 02113 02114 void EBMesher::set_obb_tree_box_dimension() 02115 { 02116 std::cout << "starting to construct obb tree." << std::endl; 02117 moab::ErrorCode rval = m_GeomTopoTool->construct_obb_trees(m_bUseWholeGeom); 02118 MBERRCHK(rval, mk_core()->moab_instance()); 02119 02120 m_hObbTree = m_GeomTopoTool->obb_tree(); 02121 m_hTreeRoot = m_GeomTopoTool->get_one_vol_root(); 02122 02123 moab::CartVect box_center, box_axis1, box_axis2, box_axis3; 02124 for (int i = 0; i < 3; i++) { 02125 m_minCoord[i] = HUGE_VAL; 02126 m_maxCoord[i] = 0.; 02127 } 02128 rval = m_hObbTree->box(m_hTreeRoot, box_center.array(), 02129 box_axis1.array(), box_axis2.array(), 02130 box_axis3.array()); 02131 MBERRCHK(rval, mk_core()->moab_instance()); 02132 02133 // cartesian box corners 02134 moab::CartVect corners[8] = {box_center + box_axis1 + box_axis2 + box_axis3, 02135 box_center + box_axis1 + box_axis2 - box_axis3, 02136 box_center + box_axis1 - box_axis2 + box_axis3, 02137 box_center + box_axis1 - box_axis2 - box_axis3, 02138 box_center - box_axis1 + box_axis2 + box_axis3, 02139 box_center - box_axis1 + box_axis2 - box_axis3, 02140 box_center - box_axis1 - box_axis2 + box_axis3, 02141 box_center - box_axis1 - box_axis2 - box_axis3}; 02142 02143 // get the max, min cartesian box corners 02144 for (int i = 0; i < 8; i++) { 02145 for (int j = 0; j < 3; j++) { 02146 if (corners[i][j] < m_minCoord[j]) m_minCoord[j] = corners[i][j]; 02147 if (corners[i][j] > m_maxCoord[j]) m_maxCoord[j] = corners[i][j]; 02148 } 02149 } 02150 std::cout << "finished to construct obb tree." << std::endl; 02151 } 02152 #endif 02153 } // namespace MeshKit