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