MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2006 Lawrence Livermore National Laboratory. Under 00005 the terms of Contract B545069 with the University of Wisconsin -- 00006 Madison, Lawrence Livermore National Laboratory retains certain 00007 rights in this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2006) kraftche@cae.wisc.edu 00024 00025 ***************************************************************** */ 00026 00027 #include "Mesquite.hpp" 00028 #include "VertexPatches.hpp" 00029 #include "GlobalPatch.hpp" 00030 #include "MeshInterface.hpp" 00031 #include "Instruction.hpp" 00032 #include "MsqError.hpp" 00033 #include "UnitUtil.hpp" 00034 00035 #include <cassert> 00036 #include <vector> 00037 #include <algorithm> 00038 #include <set> 00039 #include <numeric> 00040 #include <iostream> 00041 using namespace std; 00042 00043 // Define a fake implementation of MBMesquite::Mesh to pass 00044 // to the PatchSet implementations. This implementation 00045 // provides only the four methods required by the PatchSet 00046 // implementations. 00047 00048 #define NI( A ) MSQ_SETERR( A )( MsqError::NOT_IMPLEMENTED ) 00049 00050 using namespace MBMesquite; 00051 00052 class FakeMesh : public MBMesquite::Mesh 00053 { 00054 public: 00055 FakeMesh( size_t num_verts ); 00056 ~FakeMesh(); 00057 00058 // Specify whether or not calls should fail, to test error behavior 00059 void should_fail( bool yesno ) 00060 { 00061 doError = yesno; 00062 } 00063 00064 void get_all_elements( vector< ElementHandle >& elems, MsqError& err ); 00065 00066 void get_all_vertices( vector< VertexHandle >& verts, MsqError& err ); 00067 00068 void vertices_get_fixed_flag( const VertexHandle* verts, std::vector< bool >& fixed, size_t n, MsqError& err ); 00069 00070 void vertices_get_slaved_flag( const VertexHandle* verts, std::vector< bool >& fixed, size_t n, MsqError& err ); 00071 00072 void vertices_get_attached_elements( const VertexHandle* array, 00073 size_t len, 00074 vector< ElementHandle >& elems, 00075 vector< size_t >& offsets, 00076 MsqError& err ); 00077 00078 int get_geometric_dimension( MsqError& err ) 00079 { 00080 NI( err ); 00081 return 3; 00082 } 00083 VertexIterator* vertex_iterator( MsqError& err ) 00084 { 00085 NI( err ); 00086 return 0; 00087 } 00088 ElementIterator* element_iterator( MsqError& err ) 00089 { 00090 NI( err ); 00091 return 0; 00092 } 00093 void vertices_get_coordinates( const VertexHandle*, MsqVertex*, size_t, MsqError& err ) 00094 { 00095 NI( err ); 00096 } 00097 void vertex_set_coordinates( VertexHandle, const Vector3D&, MsqError& err ) 00098 { 00099 NI( err ); 00100 } 00101 void vertex_set_byte( VertexHandle h, unsigned char b, MsqError& err ) 00102 { 00103 vertices_get_byte( &h, &b, 1, err ); 00104 } 00105 void vertices_set_byte( const VertexHandle*, const unsigned char*, size_t, MsqError& err ); 00106 void vertex_get_byte( const VertexHandle h, unsigned char* b, MsqError& err ) 00107 { 00108 vertices_get_byte( &h, b, 1, err ); 00109 } 00110 void vertices_get_byte( const VertexHandle*, unsigned char*, size_t, MsqError& err ); 00111 00112 void elements_get_attached_vertices( const ElementHandle*, 00113 size_t, 00114 vector< VertexHandle >&, 00115 vector< size_t >&, 00116 MsqError& err ) 00117 { 00118 NI( err ); 00119 } 00120 void elements_get_topologies( const ElementHandle*, EntityTopology*, size_t, MsqError& err ) 00121 { 00122 NI( err ); 00123 } 00124 TagHandle tag_create( const string&, TagType, unsigned, const void*, MsqError& err ) 00125 { 00126 NI( err ); 00127 return 0; 00128 } 00129 void tag_delete( TagHandle, MsqError& err ) 00130 { 00131 NI( err ); 00132 } 00133 TagHandle tag_get( const string&, MsqError& err ) 00134 { 00135 NI( err ); 00136 return 0; 00137 } 00138 void tag_properties( TagHandle, string&, TagType&, unsigned&, MsqError& err ) 00139 { 00140 NI( err ); 00141 } 00142 void tag_set_element_data( TagHandle, size_t, const ElementHandle*, const void*, MsqError& err ) 00143 { 00144 NI( err ); 00145 } 00146 void tag_set_vertex_data( TagHandle, size_t, const VertexHandle*, const void*, MsqError& err ) 00147 { 00148 NI( err ); 00149 } 00150 void tag_get_element_data( TagHandle, size_t, const ElementHandle*, void*, MsqError& err ) 00151 { 00152 NI( err ); 00153 } 00154 void tag_get_vertex_data( TagHandle, size_t, const VertexHandle*, void*, MsqError& err ) 00155 { 00156 NI( err ); 00157 } 00158 void release_entity_handles( const EntityHandle*, size_t, MsqError& err ) 00159 { 00160 NI( err ); 00161 } 00162 void release() {} 00163 00164 private: 00165 std::vector< VertexHandle > vertHandles; 00166 std::vector< ElementHandle > elemHandles; 00167 std::vector< size_t > vertOffsets; 00168 std::vector< bool > fixedFlags; 00169 std::vector< unsigned char > vertexBytes; 00170 bool doError; 00171 }; 00172 00173 FakeMesh::FakeMesh( size_t num_vtx ) : doError( false ) 00174 { 00175 vertHandles.resize( num_vtx ); 00176 vertOffsets.resize( num_vtx + 1 ); 00177 fixedFlags.resize( num_vtx ); 00178 elemHandles.clear(); 00179 for( size_t i = 0; i < num_vtx; ++i ) 00180 { 00181 vertHandles[i] = (Mesh::VertexHandle)i; 00182 vertOffsets[i] = elemHandles.size(); 00183 for( size_t j = 0; j < ( num_vtx % 5 ); ++j ) 00184 elemHandles.push_back( ( Mesh::ElementHandle )( i * num_vtx + j ) ); 00185 fixedFlags[i] = !( i % 2 ); 00186 } 00187 vertOffsets[vertOffsets.size() - 1] = elemHandles.size(); 00188 vertexBytes.resize( num_vtx, 0 ); 00189 } 00190 00191 FakeMesh::~FakeMesh() {} 00192 00193 void FakeMesh::get_all_elements( vector< ElementHandle >& elems, MsqError& err ) 00194 { 00195 if( doError ) 00196 { 00197 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00198 return; 00199 } 00200 00201 elems = elemHandles; 00202 } 00203 00204 void FakeMesh::get_all_vertices( vector< Mesh::VertexHandle >& verts, MsqError& err ) 00205 { 00206 if( doError ) 00207 { 00208 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00209 return; 00210 } 00211 00212 verts = vertHandles; 00213 } 00214 00215 void FakeMesh::vertices_get_fixed_flag( const VertexHandle* verts, std::vector< bool >& fixed, size_t n, MsqError& err ) 00216 { 00217 if( doError ) 00218 { 00219 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00220 return; 00221 } 00222 00223 if( !verts ) 00224 { 00225 MSQ_SETERR( err )( MsqError::INVALID_STATE, "NULL array pointer" ); 00226 return; 00227 } 00228 00229 fixed.resize( n ); 00230 for( size_t i = 0; i < n; ++i ) 00231 { 00232 size_t vert = (size_t)verts[i]; 00233 if( vert >= vertHandles.size() ) 00234 { 00235 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00236 return; 00237 } 00238 fixed[i] = fixedFlags[vert]; 00239 } 00240 } 00241 00242 void FakeMesh::vertices_get_slaved_flag( const VertexHandle*, std::vector< bool >&, size_t, MsqError& ) 00243 { 00244 CPPUNIT_ASSERT( false ); 00245 } 00246 00247 void FakeMesh::vertices_get_attached_elements( const VertexHandle* verts, 00248 size_t n, 00249 vector< ElementHandle >& elems, 00250 vector< size_t >& offsets, 00251 MsqError& err ) 00252 { 00253 if( doError ) 00254 { 00255 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00256 return; 00257 } 00258 00259 if( !verts ) 00260 { 00261 MSQ_SETERR( err )( MsqError::INVALID_STATE, "NULL array pointer" ); 00262 return; 00263 } 00264 00265 elems.clear(); 00266 offsets.clear(); 00267 for( size_t i = 0; i < n; ++i ) 00268 { 00269 size_t vert = (size_t)verts[i]; 00270 if( vert >= vertHandles.size() ) 00271 { 00272 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00273 return; 00274 } 00275 offsets.push_back( elems.size() ); 00276 size_t s = vertOffsets[vert]; 00277 size_t e = vertOffsets[vert + 1]; 00278 for( size_t j = s; j < e; ++j ) 00279 elems.push_back( elemHandles[j] ); 00280 } 00281 offsets.push_back( elems.size() ); 00282 } 00283 00284 void FakeMesh::vertices_get_byte( const VertexHandle* handles, unsigned char* bytes, size_t count, MsqError& err ) 00285 { 00286 for( size_t i = 0; i < count; ++i ) 00287 { 00288 size_t vert = (size_t)handles[i]; 00289 if( vert >= vertHandles.size() ) 00290 { 00291 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00292 return; 00293 } 00294 bytes[i] = vertexBytes[vert]; 00295 } 00296 } 00297 00298 void FakeMesh::vertices_set_byte( const VertexHandle* handles, const unsigned char* bytes, size_t count, MsqError& err ) 00299 { 00300 for( size_t i = 0; i < count; ++i ) 00301 { 00302 size_t vert = (size_t)handles[i]; 00303 if( vert >= vertHandles.size() ) 00304 { 00305 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00306 return; 00307 } 00308 vertexBytes[vert] = bytes[i]; 00309 } 00310 } 00311 00312 class PatchSetTest : public CppUnit::TestFixture 00313 { 00314 private: 00315 CPPUNIT_TEST_SUITE( PatchSetTest ); 00316 00317 CPPUNIT_TEST( test_vertex_patches ); 00318 CPPUNIT_TEST( test_vertex_patches_bad_handle ); 00319 CPPUNIT_TEST( test_vertex_patches_fail_handles ); 00320 CPPUNIT_TEST( test_vertex_patches_fail_entities ); 00321 00322 CPPUNIT_TEST( test_global_patch ); 00323 CPPUNIT_TEST( test_global_patch_fail_entities ); 00324 00325 CPPUNIT_TEST_SUITE_END(); 00326 00327 FakeMesh myMesh; 00328 00329 // make sure methods fail if passed a bad handle 00330 void test_bad_handle( PatchSet& ps ); 00331 00332 // test that get_patch_handles propogates failure from Mesh 00333 void test_fail_handles( PatchSet& ps ); 00334 00335 // test that get_patch propogates failures from Mesh 00336 void test_fail_entities( PatchSet& ps ); 00337 00338 public: 00339 PatchSetTest() : myMesh( 10 ) {} 00340 00341 void setUp() 00342 { 00343 myMesh.should_fail( false ); 00344 } 00345 void tearDown() {} 00346 00347 // test that VertexPatches returns expected data 00348 void test_vertex_patches(); 00349 00350 // call failure tests for VertexPatches 00351 void test_vertex_patches_bad_handle(); 00352 void test_vertex_patches_fail_handles(); 00353 void test_vertex_patches_fail_entities(); 00354 00355 // test that GlobalPatch returns expected data 00356 void test_global_patch(); 00357 00358 // call failure tests for GlobalPatch 00359 void test_global_patch_fail_entities(); 00360 }; 00361 00362 void PatchSetTest::test_vertex_patches() 00363 { 00364 size_t i; 00365 VertexPatches vp; 00366 MsqPrintError err( std::cout ); 00367 vp.set_mesh( &myMesh ); 00368 MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &myMesh, 0 ); 00369 Instruction::initialize_vertex_byte( &mesh_and_domain, 0, err ); 00370 ASSERT_NO_ERROR( err ); 00371 00372 // Get data from myMesh to compare to 00373 00374 vector< Mesh::VertexHandle > vertex_handles, patch_verts; 00375 vector< Mesh::ElementHandle > element_handles, patch_elems; 00376 myMesh.get_all_vertices( vertex_handles, err ); 00377 ASSERT_NO_ERROR( err ); 00378 CPPUNIT_ASSERT( !vertex_handles.empty() ); 00379 00380 std::vector< bool > fixed; 00381 myMesh.vertices_get_fixed_flag( arrptr( vertex_handles ), fixed, vertex_handles.size(), err ); 00382 ASSERT_NO_ERROR( err ); 00383 00384 set< Mesh::VertexHandle > free_verts; 00385 for( i = 0; i < vertex_handles.size(); ++i ) 00386 if( !fixed[i] ) free_verts.insert( vertex_handles[i] ); 00387 00388 // Get list of patch handles 00389 00390 vector< PatchSet::PatchHandle > patch_handles; 00391 vp.get_patch_handles( patch_handles, err ); 00392 ASSERT_NO_ERROR( err ); 00393 CPPUNIT_ASSERT_EQUAL( free_verts.size(), patch_handles.size() ); 00394 00395 // Check each patch handle 00396 vector< size_t > offsets; 00397 for( i = 0; i < patch_handles.size(); ++i ) 00398 { 00399 vp.get_patch( patch_handles[i], patch_elems, patch_verts, err ); 00400 ASSERT_NO_ERROR( err ); 00401 00402 // Check that each patch contains exactly 1 free vertex 00403 // and that it is always a different free vertex. 00404 CPPUNIT_ASSERT( patch_verts.size() == 1 ); 00405 set< Mesh::VertexHandle >::iterator i = free_verts.find( patch_verts[0] ); 00406 CPPUNIT_ASSERT( i != free_verts.end() ); 00407 free_verts.erase( i ); 00408 00409 // Get adjacent elements from myMesh to compare with 00410 element_handles.clear(); 00411 myMesh.vertices_get_attached_elements( arrptr( patch_verts ), 1, element_handles, offsets, err ); 00412 ASSERT_NO_ERROR( err ); 00413 00414 // Compare element handle lists 00415 sort( element_handles.begin(), element_handles.end() ); 00416 sort( patch_elems.begin(), patch_elems.end() ); 00417 CPPUNIT_ASSERT( element_handles == patch_elems ); 00418 } 00419 } 00420 00421 void PatchSetTest::test_global_patch() 00422 { 00423 GlobalPatch gp; 00424 MsqPrintError err( std::cout ); 00425 gp.set_mesh( &myMesh ); 00426 00427 // Get data from myMesh to compare to 00428 vector< Mesh::VertexHandle > vertex_handles, patch_verts; 00429 vector< Mesh::ElementHandle > element_handles, patch_elems; 00430 myMesh.get_all_vertices( vertex_handles, err ); 00431 CPPUNIT_ASSERT( !err ); 00432 myMesh.get_all_elements( element_handles, err ); 00433 CPPUNIT_ASSERT( !err ); 00434 00435 // Get list of patch handles 00436 vector< PatchSet::PatchHandle > patch_handles; 00437 gp.get_patch_handles( patch_handles, err ); 00438 CPPUNIT_ASSERT( !err ); 00439 CPPUNIT_ASSERT( 1 == patch_handles.size() ); 00440 00441 // Get mesh data from GlobalPatch 00442 gp.get_patch( patch_handles[0], patch_elems, patch_verts, err ); 00443 CPPUNIT_ASSERT( !err ); 00444 00445 // compare element list 00446 sort( element_handles.begin(), element_handles.end() ); 00447 sort( patch_elems.begin(), patch_elems.end() ); 00448 CPPUNIT_ASSERT( patch_elems == element_handles ); 00449 00450 // compare vertex list 00451 sort( vertex_handles.begin(), vertex_handles.end() ); 00452 sort( patch_verts.begin(), patch_verts.end() ); 00453 CPPUNIT_ASSERT( patch_verts.empty() || patch_verts == vertex_handles ); 00454 } 00455 00456 void PatchSetTest::test_bad_handle( PatchSet& ps ) 00457 { 00458 MsqPrintError err( std::cout ); 00459 ps.set_mesh( &myMesh ); 00460 00461 // Get list of patch handles 00462 vector< PatchSet::PatchHandle > patch_handles; 00463 ps.get_patch_handles( patch_handles, err ); 00464 CPPUNIT_ASSERT( !err ); 00465 00466 // create an invalid handle 00467 size_t max_handle = (size_t)*max_element( patch_handles.begin(), patch_handles.end() ); 00468 size_t bad_handle = max_handle + 1; 00469 00470 // try to get patch for invalid handle 00471 vector< Mesh::VertexHandle > patch_verts; 00472 vector< Mesh::ElementHandle > patch_elems; 00473 ps.get_patch( (PatchSet::PatchHandle)bad_handle, patch_elems, patch_verts, err ); 00474 CPPUNIT_ASSERT( err ); 00475 err.clear(); 00476 } 00477 00478 void PatchSetTest::test_fail_handles( PatchSet& ps ) 00479 { 00480 MsqPrintError err( std::cout ); 00481 ps.set_mesh( &myMesh ); 00482 00483 myMesh.should_fail( true ); 00484 vector< PatchSet::PatchHandle > patch_handles; 00485 ps.get_patch_handles( patch_handles, err ); 00486 myMesh.should_fail( false ); 00487 CPPUNIT_ASSERT( err ); 00488 err.clear(); 00489 } 00490 00491 void PatchSetTest::test_fail_entities( PatchSet& ps ) 00492 { 00493 MsqPrintError err( std::cout ); 00494 ps.set_mesh( &myMesh ); 00495 00496 // Get list of patch handles 00497 vector< PatchSet::PatchHandle > patch_handles; 00498 ps.get_patch_handles( patch_handles, err ); 00499 CPPUNIT_ASSERT( !err ); 00500 00501 // try to get patch for invalid handle 00502 vector< Mesh::VertexHandle > patch_verts; 00503 vector< Mesh::ElementHandle > patch_elems; 00504 myMesh.should_fail( true ); 00505 ps.get_patch( patch_handles[0], patch_elems, patch_verts, err ); 00506 myMesh.should_fail( false ); 00507 CPPUNIT_ASSERT( err ); 00508 err.clear(); 00509 } 00510 00511 void PatchSetTest::test_vertex_patches_bad_handle() 00512 { 00513 VertexPatches ps; 00514 test_bad_handle( ps ); 00515 } 00516 00517 void PatchSetTest::test_vertex_patches_fail_handles() 00518 { 00519 VertexPatches ps; 00520 test_fail_handles( ps ); 00521 } 00522 00523 void PatchSetTest::test_vertex_patches_fail_entities() 00524 { 00525 VertexPatches ps; 00526 test_fail_entities( ps ); 00527 } 00528 00529 void PatchSetTest::test_global_patch_fail_entities() 00530 { 00531 GlobalPatch ps; 00532 test_fail_entities( ps ); 00533 } 00534 00535 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PatchSetTest, "PatchSetTest" ); 00536 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PatchSetTest, "Unit" );