MOAB: Mesh Oriented datABase  (version 5.2.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) 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, 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" );
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines