MOAB: Mesh Oriented datABase  (version 5.4.1)
PatchSetTest.cpp
Go to the documentation of this file.
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) [email protected]
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" );
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines