MeshKit
1.0
|
00001 00007 #include "meshkit/MKCore.hpp" 00008 #include "meshkit/ModelEnt.hpp" 00009 #include "meshkit/MesquiteOpt.hpp" 00010 #include "meshkit/iGeom.hpp" 00011 #include "meshkit/iMesh.hpp" 00012 #include "meshkit/Matrix.hpp" 00013 #include "TestUtil.hpp" 00014 00015 using namespace MeshKit; 00016 00017 void test_fixed_smooth_surf(); 00018 void test_free_smooth_surf(); 00019 void test_smooth_spherical_surf(); 00020 //void test_fixed_smooth_vol(); 00021 //void test_free_smooth_vol(); 00022 00023 ModelEnt* create_surface_mesh( moab::EntityHandle vertices[4][4] ); 00024 //ModelEnt* create_volume_mesh( moab::EntityHandle vertices[4][4][4] ); 00025 ModelEnt* get_model_ent( iBase_EntityHandle geom ); 00026 00027 bool verbose = false; 00028 bool write_vtk = false; 00029 MKCore* core; 00030 int main(int argc, char* argv[]) 00031 { 00032 for (int i = 1; i < argc; ++i) { 00033 if (!strcmp(argv[i],"-v")) 00034 verbose = true; 00035 else if (!strcmp(argv[i],"-w")) 00036 write_vtk = true; 00037 else if (!strcmp(argv[i],"-h")) 00038 std::cout << argv[0] << " [-v] [-w]" << std::endl; 00039 else 00040 std::cerr << "Invalid option: \"" << argv[i] << '"' << std::endl; 00041 } 00042 00043 MKCore my_core; 00044 core = &my_core; 00045 00046 int result = 0; 00047 result += RUN_TEST( test_fixed_smooth_surf ); 00048 result += RUN_TEST( test_free_smooth_surf ); 00049 result += RUN_TEST( test_smooth_spherical_surf ); 00050 //result += RUN_TEST( test_fixed_smooth_vol ); 00051 //result += RUN_TEST( test_free_smooth_vol ); 00052 00053 return result; 00054 } 00055 00056 struct PointSort 00057 { 00058 bool operator()(ModelEnt* pt1, ModelEnt* pt2) 00059 { 00060 double c1[3], c2[3]; 00061 pt1->evaluate( 0, 0, 0, c1 ); 00062 pt2->evaluate( 0, 0, 0, c2 ); 00063 if (fabs(c1[2] - c2[2]) > 1e-6) 00064 return c1[2] < c2[2]; 00065 else if (fabs(c1[1] - c2[1]) > 1e-6) 00066 return c1[1] < c2[1]; 00067 else if (fabs(c1[0] - c2[0]) > 1e-6) 00068 return c1[0] < c2[0]; 00069 else 00070 return false; 00071 } 00072 }; 00073 00074 // Generate meshed square face such that positions of the vertices 00075 // passed back at each index are (values below are indices into 00076 // passed back 'vertices' array, not coordinates): 00077 // 00078 // (0,3), (1,3), (2,3), (3,3) Y 00079 // (0,2), (1,2), (2,2), (3,2) ^ 00080 // (0,1), (1,1), (2,1), (3,1) | 00081 // (0,0), (1,0), (2,0), (3,0) | 00082 // +---->X 00083 ModelEnt* create_surface_mesh( moab::EntityHandle vertices[4][4] ) 00084 { 00085 // create a 3x3x3 brick 00086 iGeom* geom = core->igeom_instance(); 00087 iBase_EntityHandle brick; 00088 iGeom::Error err = geom->createBrick( 3, 3, 3, brick ); 00089 CHECK_EQUAL( iBase_SUCCESS, err ); 00090 00091 // find ModelEnt for a surface parallel to the Z-plane and normal 00092 // in positive-Z direction 00093 ModelEnt* ent = get_model_ent( brick ); 00094 MEntVector surfaces; 00095 ent->get_adjacencies( 2, surfaces ); 00096 double normal[3]; 00097 double point[3]; 00098 size_t i; 00099 for (i = 0; i < surfaces.size(); ++i) 00100 { 00101 surfaces[i]->evaluate( 0, 0, 0, point, normal ); 00102 if (fabs(normal[0]) < 1e-6 && 00103 fabs(normal[1]) < 1e-6 && 00104 normal[2] > 1e-6) 00105 break; 00106 } 00107 CHECK( i != surfaces.size() ); 00108 ModelEnt* surf = surfaces[i]; 00109 00110 // find sub-entities such that indices are: 00111 // 2-----3-----3 Y 00112 // | | ^ 00113 // | | | 00114 // 1 2 | 00115 // | | +---->X 00116 // | | 00117 // 0-----0-----1 00118 00119 MEntVector curves, points; 00120 surf->get_adjacencies( 1, curves ); 00121 surf->get_adjacencies( 0, points ); 00122 CHECK_EQUAL( (size_t)4, curves.size() ); 00123 CHECK_EQUAL( (size_t)4, points.size() ); 00124 std::sort( points.begin(), points.end(), PointSort() ); 00125 00126 int ends[4][2] = { { 0, 1 }, {0, 2}, {1, 3}, {2, 3} }; 00127 bool reversed[4]; 00128 MEntVector endpts; 00129 for (i = 0; i < curves.size(); ++i) { 00130 ModelEnt* exp1 = points[ends[i][0]]; 00131 ModelEnt* exp2 = points[ends[i][1]]; 00132 size_t j; 00133 for (j = i; j < curves.size(); ++j) { 00134 endpts.clear(); 00135 curves[j]->get_adjacencies( 0, endpts ); 00136 CHECK_EQUAL( (size_t)2, endpts.size() ); 00137 if (endpts[0] == exp1 && endpts[1] == exp2) { 00138 reversed[i] = false; 00139 break; 00140 } 00141 else if (endpts[0] == exp2 && endpts[1] == exp1) { 00142 reversed[i] = true; 00143 break; 00144 } 00145 } 00146 CHECK(j != 4); 00147 if (j != i) 00148 std::swap( curves[i], curves[j] ); 00149 } 00150 00151 // create mesh vertices 00152 00153 // first get corner coords 00154 Vector<3> corners[4]; 00155 for (i = 0; i < 4; ++i) 00156 points[i]->evaluate( 0, 0, 0, corners[i].data() ); 00157 00158 // now create all vertices 00159 moab::ErrorCode rval; 00160 for (int u = 0; u < 4; ++u) { 00161 for (int v = 0; v < 4; ++v) { 00162 const double u3 = u/3.0; 00163 const double v3 = v/3.0; 00164 Vector<3> coords = (1-u3)*(1-v3)*corners[0] + 00165 ( u3)*(1-v3)*corners[1] + 00166 (1-u3)*( v3)*corners[2] + 00167 ( u3)*( v3)*corners[3]; 00168 rval = core->moab_instance()->create_vertex( coords.data(), vertices[u][v] ); 00169 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00170 } 00171 } 00172 00173 // assign mesh vertices to geometric vertices 00174 moab::EntityHandle verts[] = { vertices[0][0], vertices[3][0], 00175 vertices[0][3], vertices[3][3] }; 00176 for (i = 0; i < 4; ++i) { 00177 // check that we created vertices with correct coords 00178 Vector<3> coords, vcoords; 00179 points[i]->evaluate( 0, 0, 0, coords.data() ); 00180 rval = core->moab_instance()->get_coords( &verts[i], 1, vcoords.data() ); 00181 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00182 CHECK( length(coords - vcoords) < 1e-6 ); 00183 // assign to vertex 00184 points[i]->commit_mesh( &verts[i], 1, COMPLETE_MESH ); 00185 } 00186 00187 // mesh edges 00188 for (int i = 0; i < 4; ++i) { 00189 // get list of four vertices 00190 int u, v, u_stride, v_stride; 00191 if (i < 2) { 00192 u = v = 0; 00193 u_stride = 1-i; 00194 v_stride = i; 00195 } 00196 else { 00197 u_stride = i-2; 00198 v_stride = 3-i; 00199 v = u_stride; 00200 u = v_stride; 00201 } 00202 moab::EntityHandle verts[4]; 00203 for (int j = 0; j < 4; ++j) 00204 verts[j] = vertices[3*u + j*u_stride][3*v + j*v_stride]; 00205 if (reversed[i]) { 00206 std::swap( verts[0], verts[3] ); 00207 std::swap( verts[1], verts[2] ); 00208 } 00209 00210 moab::EntityHandle curve_mesh[5]; // three edges and two interior vertices 00211 curve_mesh[1] = verts[1]; 00212 curve_mesh[3] = verts[2]; 00213 rval = core->moab_instance()->create_element( moab::MBEDGE, &verts[0], 2, curve_mesh[0] ); 00214 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00215 rval = core->moab_instance()->create_element( moab::MBEDGE, &verts[1], 2, curve_mesh[2] ); 00216 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00217 rval = core->moab_instance()->create_element( moab::MBEDGE, &verts[2], 2, curve_mesh[4] ); 00218 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00219 00220 curves[i]->commit_mesh( curve_mesh, 5, COMPLETE_MESH ); 00221 } 00222 00223 // mesh surface 00224 moab::Range surf_mesh; 00225 for (int u = 0; u < 3; ++u) { 00226 for (int v = 0; v < 3; ++v) { 00227 moab::EntityHandle conn[4] = { vertices[u ][v ], 00228 vertices[u+1][v ], 00229 vertices[u+1][v+1], 00230 vertices[u ][v+1] }; 00231 moab::EntityHandle quad; 00232 rval = core->moab_instance()->create_element( moab::MBQUAD, conn, 4, quad ); 00233 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00234 surf_mesh.insert(quad); 00235 } 00236 } 00237 // add interior vertices to range 00238 for (int u = 1; u < 3; ++u) 00239 for (int v = 1; v < 3; ++v) 00240 surf_mesh.insert( vertices[u][v] ); 00241 surf->commit_mesh( surf_mesh, COMPLETE_MESH ); 00242 00243 return surf; 00244 } 00245 00246 ModelEnt* get_model_ent( iBase_EntityHandle geom ) 00247 { 00248 core->populate_model_ents(); 00249 iBase_EntityType type; 00250 iGeom::Error err = core->igeom_instance()->getEntType( geom, type ); 00251 CHECK_EQUAL(iBase_SUCCESS,err); 00252 CHECK(type < 4); 00253 MEntVector ents; 00254 core->get_entities_by_dimension(type, ents); 00255 for (MEntVector::iterator i = ents.begin(); i != ents.end(); ++i) 00256 if ((*i)->geom_handle() == geom) 00257 return *i; 00258 return 0; 00259 } 00260 00261 void check_surf_coords( Vector<3> coords[4][4], moab::EntityHandle verts[4][4], double epsilon ) 00262 { 00263 for (int i = 0; i < 4; ++i) { 00264 for (int j = 0; j < 4; ++j) { 00265 Vector<3> new_coords; 00266 moab::ErrorCode rval = core->moab_instance()->get_coords( &verts[i][j], 1, new_coords.data() ); 00267 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00268 CHECK_REAL_EQUAL( 0.0, length(new_coords - coords[i][j]), epsilon ); 00269 } 00270 } 00271 } 00272 00273 void test_fixed_smooth_surf() 00274 { 00275 //get a mesh 00276 moab::EntityHandle vertices[4][4]; 00277 ModelEnt* surf = create_surface_mesh( vertices ); 00278 moab::EntityHandle surf_set = surf->mesh_handle(); 00279 if (write_vtk) 00280 core->moab_instance()->write_file( "test_fixed_smooth_surf-init.vtk", "VTK", 0, &surf_set, 1 ); 00281 00282 // get all coordinates 00283 moab::ErrorCode rval; 00284 Vector<3> coords[4][4]; 00285 rval = core->moab_instance()->get_coords( &vertices[0][0], 4*4, coords[0][0].data() ); 00286 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00287 00288 // run smoother on optimal mesh 00289 MEntVector v; 00290 v.push_back(surf); 00291 MesquiteOpt op( core, v ); 00292 op.print_quality(verbose); 00293 op.smooth_with_fixed_boundary(); 00294 if (verbose) 00295 std::cout << std::endl << "Fixed smooth of optimal surface mesh" << std::endl << std::endl; 00296 op.setup_this(); 00297 op.execute_this(); 00298 if (write_vtk) 00299 core->moab_instance()->write_file( "test_fixed_smooth_surf-opt.vtk", "VTK", 0, &surf_set, 1 ); 00300 00301 // verify that vertices did not move 00302 check_surf_coords( coords, vertices, 1e-3 ); 00303 00304 // perturb interior vertices 00305 Vector<3> new_coord; 00306 const double f = 1.3; 00307 Vector<3> mean = 0.25*(coords[1][1]+coords[2][1]+coords[1][2]+coords[2][2]); 00308 for (int i = 1; i < 3; ++i) { 00309 for (int j = 1; j < 3; ++j) { 00310 new_coord = f*coords[i][j] + (1-f)*mean; 00311 rval = core->moab_instance()->set_coords( &vertices[i][j], 1, new_coord.data() ); 00312 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00313 } 00314 } 00315 if (write_vtk) 00316 core->moab_instance()->write_file( "test_fixed_smooth_surf-perturb.vtk", "VTK", 0, &surf_set, 1 ); 00317 00318 // run smoother and verify that coords at optimal positions 00319 if (verbose) 00320 std::cout << std::endl << "Fixed smooth of sub-optimal surface mesh" << std::endl << std::endl; 00321 op.setup_this(); 00322 op.execute_this(); 00323 if (write_vtk) 00324 core->moab_instance()->write_file( "test_fixed_smooth_surf-smooth.vtk", "VTK", 0, &surf_set, 1 ); 00325 check_surf_coords( coords, vertices, 1e-3 ); 00326 00327 // perturb an edge vertex and verify that it did not move 00328 Vector<3> mid_coord = 0.5*(coords[1][0] + coords[2][0]); 00329 rval = core->moab_instance()->set_coords( &vertices[1][0], 1, mid_coord.data() ); 00330 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00331 if (verbose) 00332 std::cout << std::endl << "Fixed smooth of surface with sub-optimal edge mesh" << std::endl << std::endl; 00333 op.setup_this(); 00334 op.execute_this(); 00335 if (write_vtk) 00336 core->moab_instance()->write_file( "test_fixed_smooth_surf-fixed.vtk", "VTK", 0, &surf_set, 1 ); 00337 rval = core->moab_instance()->get_coords( &vertices[1][0], 1, new_coord.data() ); 00338 CHECK_REAL_EQUAL( 0.0, length(new_coord - mid_coord), 1e-6 ); 00339 } 00340 00341 void test_free_smooth_surf() 00342 { 00343 //get a mesh 00344 moab::EntityHandle vertices[4][4]; 00345 ModelEnt* surf = create_surface_mesh( vertices ); 00346 moab::EntityHandle surf_set = surf->mesh_handle(); 00347 if (write_vtk) 00348 core->moab_instance()->write_file( "test_free_smooth_surf-init.vtk", "VTK", 0, &surf_set, 1 ); 00349 00350 // get all coordinates 00351 moab::ErrorCode rval; 00352 Vector<3> coords[4][4]; 00353 rval = core->moab_instance()->get_coords( &vertices[0][0], 4*4, coords[0][0].data() ); 00354 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00355 00356 // run smoother on optimal mesh 00357 MEntVector v; 00358 v.push_back(surf); 00359 MesquiteOpt op( core, v ); 00360 op.smooth_with_free_boundary(); 00361 op.print_quality(verbose); 00362 if (verbose) 00363 std::cout << std::endl << "Free smooth of optimal surface mesh" << std::endl << std::endl; 00364 op.setup_this(); 00365 op.execute_this(); 00366 if (write_vtk) 00367 core->moab_instance()->write_file( "test_free_smooth_surf-opt.vtk", "VTK", 0, &surf_set, 1 ); 00368 00369 // verify that vertices did not move 00370 check_surf_coords( coords, vertices, 1e-3 ); 00371 00372 // perturb interior vertices 00373 Vector<3> new_coord; 00374 const double f = 1.3; 00375 Vector<3> mean = 0.25*(coords[1][1]+coords[2][1]+coords[1][2]+coords[2][2]); 00376 for (int i = 1; i < 3; ++i) { 00377 for (int j = 1; j < 3; ++j) { 00378 new_coord = f*coords[i][j] + (1-f)*mean; 00379 rval = core->moab_instance()->set_coords( &vertices[i][j], 1, new_coord.data() ); 00380 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00381 } 00382 } 00383 // perturb edge vertices 00384 Vector<3> mid_coord = 0.5*(coords[1][0] + coords[2][0]); 00385 rval = core->moab_instance()->set_coords( &vertices[1][0], 1, mid_coord.data() ); 00386 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00387 if (write_vtk) 00388 core->moab_instance()->write_file( "test_free_smooth_surf-perturb.vtk", "VTK", 0, &surf_set, 1 ); 00389 00390 // run smoother and verify that coords at optimal positions 00391 if (verbose) 00392 std::cout << std::endl << "Free smooth of sub-optimal surface mesh" << std::endl << std::endl; 00393 op.setup_this(); 00394 op.execute_this(); 00395 if (write_vtk) 00396 core->moab_instance()->write_file( "test_free_smooth_surf-smooth.vtk", "VTK", 0, &surf_set, 1 ); 00397 check_surf_coords( coords, vertices, 1e-2 ); 00398 } 00399 00400 void test_smooth_spherical_surf() 00401 { 00402 // create sphere 00403 const double rad = std::sqrt(3.0); 00404 iGeom* geom = core->igeom_instance(); 00405 iBase_EntityHandle vol_handle; 00406 iGeom::Error err = geom->createSphere( rad, vol_handle ); 00407 CHECK_EQUAL( iBase_SUCCESS, err ); 00408 ModelEnt* vol = get_model_ent( vol_handle ); 00409 00410 // check expected topology and get surface pointer 00411 MEntVector list; 00412 vol->get_adjacencies( 2, list ); 00413 CHECK_EQUAL( (size_t)1, list.size() ); 00414 ModelEnt* surf = list.front(); 00415 //list.clear(); 00416 //surf->get_adjacencies( 1, list ); 00417 //CHECK( list.empty() ); 00418 00419 // define quad faces of a single hex circumscribed by the sphere 00420 const double xp = 0.5; 00421 const double yp = std::sqrt( 2 - xp * xp ); 00422 const double coords[][3] = { { -1, -1, -1 }, 00423 { 1, -1, -1 }, 00424 { xp, yp, -1 }, // perturb one vertex 00425 { -1, 1, -1 }, 00426 { -1, -1, 1 }, 00427 { 1, -1, 1 }, 00428 { 1, 1, 1 }, 00429 { -1, 1, 1 } }; 00430 const int conn[][4] = { { 0, 1, 5, 4 }, 00431 { 1, 2, 6, 5 }, 00432 { 2, 3, 7, 6 }, 00433 { 3, 0, 4, 7 }, 00434 { 3, 2, 1, 0 }, 00435 { 4, 5, 6, 7 } }; 00436 00437 // create mesh entities 00438 moab::ErrorCode rval; 00439 moab::EntityHandle mesh[8+6], *verts=mesh, *quads=verts+8; 00440 for (int i = 0; i < 8; ++i) { 00441 rval = core->moab_instance()->create_vertex( coords[i], verts[i] ); 00442 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00443 } 00444 for (int i = 0; i < 6; ++i) { 00445 moab::EntityHandle mconn[4]; 00446 for (int j = 0; j < 4; ++j) 00447 mconn[j] = verts[conn[i][j]]; 00448 rval = core->moab_instance()->create_element( moab::MBQUAD, mconn, 4, quads[i] ); 00449 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00450 } 00451 surf->commit_mesh( mesh, 8+6, COMPLETE_MESH ); 00452 moab::EntityHandle set = surf->mesh_handle(); 00453 if (write_vtk) 00454 core->moab_instance()->write_file( "test_smooth_spherical_surf-init.vtk", "VTK", 0, &set, 1 ); 00455 00456 list.clear(); 00457 list.push_back(surf); 00458 MesquiteOpt op( core, list ); 00459 op.print_quality(verbose); 00460 op.smooth_with_fixed_boundary(); 00461 if (verbose) 00462 std::cout << std::endl << "Fixed smooth of mesh of spherical surface" << std::endl << std::endl; 00463 op.setup_this(); 00464 op.execute_this(); 00465 if (write_vtk) 00466 core->moab_instance()->write_file( "test_smooth_spherical_surf-opt.vtk", "VTK", 0, &set, 1 ); 00467 00468 // check that all vertices lie on sphere 00469 for (int i = 0; i < 8; ++i) { 00470 Vector<3> c; 00471 rval = core->moab_instance()->get_coords( &verts[i], 1, c.data() ); 00472 CHECK_REAL_EQUAL( rad, length(c), 1e-3 ); 00473 } 00474 00475 // check that all quad faces are squares 00476 for (int i = 0; i < 6; ++i) { 00477 Vector<3> c[4]; 00478 moab::EntityHandle mconn[4]; 00479 for (int j = 0; j < 4; ++j) 00480 mconn[j] = verts[conn[i][j]]; 00481 rval = core->moab_instance()->get_coords( mconn, 4, c[0].data() ); 00482 CHECK_EQUAL( moab::MB_SUCCESS, rval ); 00483 for (int j = 0; j < 4; ++j) { 00484 Vector<3> e1 = c[(j+1)%4] - c[j]; 00485 Vector<3> e2 = c[(j+2)%4] - c[(j+1)%4]; 00486 CHECK_REAL_EQUAL( 2.0, length(e1), 5e-2 ); 00487 CHECK_REAL_EQUAL( 4.0, length(e1*e2), 5e-2 ); 00488 } 00489 } 00490 } 00491