MOAB: Mesh Oriented datABase
(version 5.2.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 <assert.h> 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, size_t len, vector< ElementHandle >& elems, 00073 vector< size_t >& offsets, MsqError& err ); 00074 00075 int get_geometric_dimension( MsqError& err ) 00076 { 00077 NI( err ); 00078 return 3; 00079 } 00080 VertexIterator* vertex_iterator( MsqError& err ) 00081 { 00082 NI( err ); 00083 return 0; 00084 } 00085 ElementIterator* element_iterator( MsqError& err ) 00086 { 00087 NI( err ); 00088 return 0; 00089 } 00090 void vertices_get_coordinates( const VertexHandle*, MsqVertex*, size_t, MsqError& err ) 00091 { 00092 NI( err ); 00093 } 00094 void vertex_set_coordinates( VertexHandle, const Vector3D&, MsqError& err ) 00095 { 00096 NI( err ); 00097 } 00098 void vertex_set_byte( VertexHandle h, unsigned char b, MsqError& err ) 00099 { 00100 vertices_get_byte( &h, &b, 1, err ); 00101 } 00102 void vertices_set_byte( const VertexHandle*, const unsigned char*, size_t, MsqError& err ); 00103 void vertex_get_byte( const VertexHandle h, unsigned char* b, MsqError& err ) 00104 { 00105 vertices_get_byte( &h, b, 1, err ); 00106 } 00107 void vertices_get_byte( const VertexHandle*, unsigned char*, size_t, MsqError& err ); 00108 00109 void elements_get_attached_vertices( const ElementHandle*, size_t, vector< VertexHandle >&, vector< size_t >&, 00110 MsqError& err ) 00111 { 00112 NI( err ); 00113 } 00114 void elements_get_topologies( const ElementHandle*, EntityTopology*, size_t, MsqError& err ) 00115 { 00116 NI( err ); 00117 } 00118 TagHandle tag_create( const string&, TagType, unsigned, const void*, MsqError& err ) 00119 { 00120 NI( err ); 00121 return 0; 00122 } 00123 void tag_delete( TagHandle, MsqError& err ) 00124 { 00125 NI( err ); 00126 } 00127 TagHandle tag_get( const string&, MsqError& err ) 00128 { 00129 NI( err ); 00130 return 0; 00131 } 00132 void tag_properties( TagHandle, string&, TagType&, unsigned&, MsqError& err ) 00133 { 00134 NI( err ); 00135 } 00136 void tag_set_element_data( TagHandle, size_t, const ElementHandle*, const void*, MsqError& err ) 00137 { 00138 NI( err ); 00139 } 00140 void tag_set_vertex_data( TagHandle, size_t, const VertexHandle*, const void*, MsqError& err ) 00141 { 00142 NI( err ); 00143 } 00144 void tag_get_element_data( TagHandle, size_t, const ElementHandle*, void*, MsqError& err ) 00145 { 00146 NI( err ); 00147 } 00148 void tag_get_vertex_data( TagHandle, size_t, const VertexHandle*, void*, MsqError& err ) 00149 { 00150 NI( err ); 00151 } 00152 void release_entity_handles( const EntityHandle*, size_t, MsqError& err ) 00153 { 00154 NI( err ); 00155 } 00156 void release() {} 00157 00158 private: 00159 std::vector< VertexHandle > vertHandles; 00160 std::vector< ElementHandle > elemHandles; 00161 std::vector< size_t > vertOffsets; 00162 std::vector< bool > fixedFlags; 00163 std::vector< unsigned char > vertexBytes; 00164 bool doError; 00165 }; 00166 00167 FakeMesh::FakeMesh( size_t num_vtx ) : doError( false ) 00168 { 00169 vertHandles.resize( num_vtx ); 00170 vertOffsets.resize( num_vtx + 1 ); 00171 fixedFlags.resize( num_vtx ); 00172 elemHandles.clear(); 00173 for( size_t i = 0; i < num_vtx; ++i ) 00174 { 00175 vertHandles[i] = (Mesh::VertexHandle)i; 00176 vertOffsets[i] = elemHandles.size(); 00177 for( size_t j = 0; j < ( num_vtx % 5 ); ++j ) 00178 elemHandles.push_back( ( Mesh::ElementHandle )( i * num_vtx + j ) ); 00179 fixedFlags[i] = !( i % 2 ); 00180 } 00181 vertOffsets[vertOffsets.size() - 1] = elemHandles.size(); 00182 vertexBytes.resize( num_vtx, 0 ); 00183 } 00184 00185 FakeMesh::~FakeMesh() {} 00186 00187 void FakeMesh::get_all_elements( vector< ElementHandle >& elems, MsqError& err ) 00188 { 00189 if( doError ) 00190 { 00191 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00192 return; 00193 } 00194 00195 elems = elemHandles; 00196 } 00197 00198 void FakeMesh::get_all_vertices( vector< Mesh::VertexHandle >& verts, MsqError& err ) 00199 { 00200 if( doError ) 00201 { 00202 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00203 return; 00204 } 00205 00206 verts = vertHandles; 00207 } 00208 00209 void FakeMesh::vertices_get_fixed_flag( const VertexHandle* verts, std::vector< bool >& fixed, size_t n, MsqError& err ) 00210 { 00211 if( doError ) 00212 { 00213 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00214 return; 00215 } 00216 00217 if( !verts ) 00218 { 00219 MSQ_SETERR( err )( MsqError::INVALID_STATE, "NULL array pointer" ); 00220 return; 00221 } 00222 00223 fixed.resize( n ); 00224 for( size_t i = 0; i < n; ++i ) 00225 { 00226 size_t vert = (size_t)verts[i]; 00227 if( vert >= vertHandles.size() ) 00228 { 00229 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00230 return; 00231 } 00232 fixed[i] = fixedFlags[vert]; 00233 } 00234 } 00235 00236 void FakeMesh::vertices_get_slaved_flag( const VertexHandle*, std::vector< bool >&, size_t, MsqError& ) 00237 { 00238 CPPUNIT_ASSERT( false ); 00239 } 00240 00241 void FakeMesh::vertices_get_attached_elements( const VertexHandle* verts, size_t n, vector< ElementHandle >& elems, 00242 vector< size_t >& offsets, MsqError& err ) 00243 { 00244 if( doError ) 00245 { 00246 MSQ_SETERR( err )( MsqError::UNKNOWN_ERROR, "Expected error" ); 00247 return; 00248 } 00249 00250 if( !verts ) 00251 { 00252 MSQ_SETERR( err )( MsqError::INVALID_STATE, "NULL array pointer" ); 00253 return; 00254 } 00255 00256 elems.clear(); 00257 offsets.clear(); 00258 for( size_t i = 0; i < n; ++i ) 00259 { 00260 size_t vert = (size_t)verts[i]; 00261 if( vert >= vertHandles.size() ) 00262 { 00263 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00264 return; 00265 } 00266 offsets.push_back( elems.size() ); 00267 size_t s = vertOffsets[vert]; 00268 size_t e = vertOffsets[vert + 1]; 00269 for( size_t j = s; j < e; ++j ) 00270 elems.push_back( elemHandles[j] ); 00271 } 00272 offsets.push_back( elems.size() ); 00273 } 00274 00275 void FakeMesh::vertices_get_byte( const VertexHandle* handles, unsigned char* bytes, size_t count, MsqError& err ) 00276 { 00277 for( size_t i = 0; i < count; ++i ) 00278 { 00279 size_t vert = (size_t)handles[i]; 00280 if( vert >= vertHandles.size() ) 00281 { 00282 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00283 return; 00284 } 00285 bytes[i] = vertexBytes[vert]; 00286 } 00287 } 00288 00289 void FakeMesh::vertices_set_byte( const VertexHandle* handles, const unsigned char* bytes, size_t count, MsqError& err ) 00290 { 00291 for( size_t i = 0; i < count; ++i ) 00292 { 00293 size_t vert = (size_t)handles[i]; 00294 if( vert >= vertHandles.size() ) 00295 { 00296 MSQ_SETERR( err )( MsqError::INVALID_STATE, "Vertex handle out of range" ); 00297 return; 00298 } 00299 vertexBytes[vert] = bytes[i]; 00300 } 00301 } 00302 00303 class PatchSetTest : public CppUnit::TestFixture 00304 { 00305 private: 00306 CPPUNIT_TEST_SUITE( PatchSetTest ); 00307 00308 CPPUNIT_TEST( test_vertex_patches ); 00309 CPPUNIT_TEST( test_vertex_patches_bad_handle ); 00310 CPPUNIT_TEST( test_vertex_patches_fail_handles ); 00311 CPPUNIT_TEST( test_vertex_patches_fail_entities ); 00312 00313 CPPUNIT_TEST( test_global_patch ); 00314 CPPUNIT_TEST( test_global_patch_fail_entities ); 00315 00316 CPPUNIT_TEST_SUITE_END(); 00317 00318 FakeMesh myMesh; 00319 00320 // make sure methods fail if passed a bad handle 00321 void test_bad_handle( PatchSet& ps ); 00322 00323 // test that get_patch_handles propogates failure from Mesh 00324 void test_fail_handles( PatchSet& ps ); 00325 00326 // test that get_patch propogates failures from Mesh 00327 void test_fail_entities( PatchSet& ps ); 00328 00329 public: 00330 PatchSetTest() : myMesh( 10 ) {} 00331 00332 void setUp() 00333 { 00334 myMesh.should_fail( false ); 00335 } 00336 void tearDown() {} 00337 00338 // test that VertexPatches returns expected data 00339 void test_vertex_patches(); 00340 00341 // call failure tests for VertexPatches 00342 void test_vertex_patches_bad_handle(); 00343 void test_vertex_patches_fail_handles(); 00344 void test_vertex_patches_fail_entities(); 00345 00346 // test that GlobalPatch returns expected data 00347 void test_global_patch(); 00348 00349 // call failure tests for GlobalPatch 00350 void test_global_patch_fail_entities(); 00351 }; 00352 00353 void PatchSetTest::test_vertex_patches() 00354 { 00355 size_t i; 00356 VertexPatches vp; 00357 MsqPrintError err( std::cout ); 00358 vp.set_mesh( &myMesh ); 00359 MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &myMesh, 0 ); 00360 Instruction::initialize_vertex_byte( &mesh_and_domain, 0, err ); 00361 ASSERT_NO_ERROR( err ); 00362 00363 // Get data from myMesh to compare to 00364 00365 vector< Mesh::VertexHandle > vertex_handles, patch_verts; 00366 vector< Mesh::ElementHandle > element_handles, patch_elems; 00367 myMesh.get_all_vertices( vertex_handles, err ); 00368 ASSERT_NO_ERROR( err ); 00369 CPPUNIT_ASSERT( !vertex_handles.empty() ); 00370 00371 std::vector< bool > fixed; 00372 myMesh.vertices_get_fixed_flag( arrptr( vertex_handles ), fixed, vertex_handles.size(), err ); 00373 ASSERT_NO_ERROR( err ); 00374 00375 set< Mesh::VertexHandle > free_verts; 00376 for( i = 0; i < vertex_handles.size(); ++i ) 00377 if( !fixed[i] ) free_verts.insert( vertex_handles[i] ); 00378 00379 // Get list of patch handles 00380 00381 vector< PatchSet::PatchHandle > patch_handles; 00382 vp.get_patch_handles( patch_handles, err ); 00383 ASSERT_NO_ERROR( err ); 00384 CPPUNIT_ASSERT_EQUAL( free_verts.size(), patch_handles.size() ); 00385 00386 // Check each patch handle 00387 vector< size_t > offsets; 00388 for( i = 0; i < patch_handles.size(); ++i ) 00389 { 00390 vp.get_patch( patch_handles[i], patch_elems, patch_verts, err ); 00391 ASSERT_NO_ERROR( err ); 00392 00393 // Check that each patch contains exactly 1 free vertex 00394 // and that it is always a different free vertex. 00395 CPPUNIT_ASSERT( patch_verts.size() == 1 ); 00396 set< Mesh::VertexHandle >::iterator i = free_verts.find( patch_verts[0] ); 00397 CPPUNIT_ASSERT( i != free_verts.end() ); 00398 free_verts.erase( i ); 00399 00400 // Get adjacent elements from myMesh to compare with 00401 element_handles.clear(); 00402 myMesh.vertices_get_attached_elements( arrptr( patch_verts ), 1, element_handles, offsets, err ); 00403 ASSERT_NO_ERROR( err ); 00404 00405 // Compare element handle lists 00406 sort( element_handles.begin(), element_handles.end() ); 00407 sort( patch_elems.begin(), patch_elems.end() ); 00408 CPPUNIT_ASSERT( element_handles == patch_elems ); 00409 } 00410 } 00411 00412 void PatchSetTest::test_global_patch() 00413 { 00414 GlobalPatch gp; 00415 MsqPrintError err( std::cout ); 00416 gp.set_mesh( &myMesh ); 00417 00418 // Get data from myMesh to compare to 00419 vector< Mesh::VertexHandle > vertex_handles, patch_verts; 00420 vector< Mesh::ElementHandle > element_handles, patch_elems; 00421 myMesh.get_all_vertices( vertex_handles, err ); 00422 CPPUNIT_ASSERT( !err ); 00423 myMesh.get_all_elements( element_handles, err ); 00424 CPPUNIT_ASSERT( !err ); 00425 00426 // Get list of patch handles 00427 vector< PatchSet::PatchHandle > patch_handles; 00428 gp.get_patch_handles( patch_handles, err ); 00429 CPPUNIT_ASSERT( !err ); 00430 CPPUNIT_ASSERT( 1 == patch_handles.size() ); 00431 00432 // Get mesh data from GlobalPatch 00433 gp.get_patch( patch_handles[0], patch_elems, patch_verts, err ); 00434 CPPUNIT_ASSERT( !err ); 00435 00436 // compare element list 00437 sort( element_handles.begin(), element_handles.end() ); 00438 sort( patch_elems.begin(), patch_elems.end() ); 00439 CPPUNIT_ASSERT( patch_elems == element_handles ); 00440 00441 // compare vertex list 00442 sort( vertex_handles.begin(), vertex_handles.end() ); 00443 sort( patch_verts.begin(), patch_verts.end() ); 00444 CPPUNIT_ASSERT( patch_verts.empty() || patch_verts == vertex_handles ); 00445 } 00446 00447 void PatchSetTest::test_bad_handle( PatchSet& ps ) 00448 { 00449 MsqPrintError err( std::cout ); 00450 ps.set_mesh( &myMesh ); 00451 00452 // Get list of patch handles 00453 vector< PatchSet::PatchHandle > patch_handles; 00454 ps.get_patch_handles( patch_handles, err ); 00455 CPPUNIT_ASSERT( !err ); 00456 00457 // create an invalid handle 00458 size_t max_handle = (size_t)*max_element( patch_handles.begin(), patch_handles.end() ); 00459 size_t bad_handle = max_handle + 1; 00460 00461 // try to get patch for invalid handle 00462 vector< Mesh::VertexHandle > patch_verts; 00463 vector< Mesh::ElementHandle > patch_elems; 00464 ps.get_patch( (PatchSet::PatchHandle)bad_handle, patch_elems, patch_verts, err ); 00465 CPPUNIT_ASSERT( err ); 00466 err.clear(); 00467 } 00468 00469 void PatchSetTest::test_fail_handles( PatchSet& ps ) 00470 { 00471 MsqPrintError err( std::cout ); 00472 ps.set_mesh( &myMesh ); 00473 00474 myMesh.should_fail( true ); 00475 vector< PatchSet::PatchHandle > patch_handles; 00476 ps.get_patch_handles( patch_handles, err ); 00477 myMesh.should_fail( false ); 00478 CPPUNIT_ASSERT( err ); 00479 err.clear(); 00480 } 00481 00482 void PatchSetTest::test_fail_entities( PatchSet& ps ) 00483 { 00484 MsqPrintError err( std::cout ); 00485 ps.set_mesh( &myMesh ); 00486 00487 // Get list of patch handles 00488 vector< PatchSet::PatchHandle > patch_handles; 00489 ps.get_patch_handles( patch_handles, err ); 00490 CPPUNIT_ASSERT( !err ); 00491 00492 // try to get patch for invalid handle 00493 vector< Mesh::VertexHandle > patch_verts; 00494 vector< Mesh::ElementHandle > patch_elems; 00495 myMesh.should_fail( true ); 00496 ps.get_patch( patch_handles[0], patch_elems, patch_verts, err ); 00497 myMesh.should_fail( false ); 00498 CPPUNIT_ASSERT( err ); 00499 err.clear(); 00500 } 00501 00502 void PatchSetTest::test_vertex_patches_bad_handle() 00503 { 00504 VertexPatches ps; 00505 test_bad_handle( ps ); 00506 } 00507 00508 void PatchSetTest::test_vertex_patches_fail_handles() 00509 { 00510 VertexPatches ps; 00511 test_fail_handles( ps ); 00512 } 00513 00514 void PatchSetTest::test_vertex_patches_fail_entities() 00515 { 00516 VertexPatches ps; 00517 test_fail_entities( ps ); 00518 } 00519 00520 void PatchSetTest::test_global_patch_fail_entities() 00521 { 00522 GlobalPatch ps; 00523 test_fail_entities( ps ); 00524 } 00525 00526 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PatchSetTest, "PatchSetTest" ); 00527 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PatchSetTest, "Unit" );