MOAB: Mesh Oriented datABase  (version 5.2.1)
MeshInterfaceTest.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2004 Sandia Corporation and Argonne National
00005     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
00006     with Sandia Corporation, the U.S. Government 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     diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov,
00024     pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov
00025 
00026   ***************************************************************** */
00027 // -*- Mode : c++; tab-width: 2; c-tab-always-indent: t; indent-tabs-mode: nil; c-basic-offset: 2
00028 // -*-
00029 //
00030 /*!
00031   \file   MeshInterface.hpp
00032   \brief
00033 
00034   \author Thomas Leurent
00035   \date   2003-04-17
00036 */
00037 
00038 #include "meshfiles.h"
00039 
00040 #include "Mesquite.hpp"
00041 #include "MsqError.hpp"
00042 #include "PatchData.hpp"
00043 #include "MeshImpl.hpp"
00044 #include "Vector3D.hpp"
00045 
00046 #include "cppunit/extensions/HelperMacros.h"
00047 
00048 #include <iostream>
00049 #include <algorithm>
00050 
00051 using MBMesquite::arrptr;
00052 using std::cerr;
00053 using std::cout;
00054 using std::endl;
00055 
00056 class MeshInterfaceTest : public CppUnit::TestFixture
00057 {
00058   private:
00059     CPPUNIT_TEST_SUITE( MeshInterfaceTest );
00060     CPPUNIT_TEST( test_get_geometric_dimension );
00061     CPPUNIT_TEST( test_vertices );
00062     // CPPUNIT_TEST (test_vertices_are_on_boundary);
00063     /* Not implemented yet
00064     CPPUNIT_TEST (test_vertex_is_fixed);
00065     */
00066     CPPUNIT_TEST( test_vertex_byte );
00067     CPPUNIT_TEST( test_vertex_get_attached_elements );
00068     CPPUNIT_TEST( test_elements );
00069     CPPUNIT_TEST( test_elements_get_attached_vertices );
00070     CPPUNIT_TEST( test_elements_get_topology );
00071     CPPUNIT_TEST( test_element_get_attached_vertex_indices );
00072     CPPUNIT_TEST_SUITE_END();
00073 
00074   private:
00075     MBMesquite::MeshImpl* mMesh;
00076     std::vector< MBMesquite::Mesh::VertexHandle > mConnectivity;
00077     std::vector< MBMesquite::Mesh::VertexHandle > mVertices;
00078     std::vector< MBMesquite::Mesh::ElementHandle > mElements;
00079     std::vector< size_t > mOffsets;
00080     MBMesquite::MsqError mErr;
00081 
00082   public:
00083     MeshInterfaceTest() : mMesh( 0 ) {}
00084 
00085     /* Automatically called by CppUnit before each test function. */
00086     void setUp()
00087     {
00088         // Read a VTK file -- 1 triangle flanked by 1 quad on each side (1 tri + 3 quads)
00089         mMesh = new MBMesquite::MeshImpl;
00090         mMesh->read_vtk( MESH_FILES_DIR "2D/vtk/mixed/untangled/hybrid_3quad_1tri.vtk", mErr );
00091         CPPUNIT_ASSERT( !mErr );
00092 
00093         // Get mesh data
00094         mMesh->get_all_elements( mElements, mErr );
00095         CPPUNIT_ASSERT( !mErr );
00096         mMesh->elements_get_attached_vertices( arrptr( mElements ), mElements.size(), mConnectivity, mOffsets, mErr );
00097         CPPUNIT_ASSERT( !mErr );
00098 
00099         // Construct list of vertices w/out duplicates from
00100         // connectivity list.
00101         std::vector< MBMesquite::Mesh::VertexHandle >::iterator new_end;
00102         mVertices = mConnectivity;
00103         std::sort( mVertices.begin(), mVertices.end() );
00104         new_end = std::unique( mVertices.begin(), mVertices.end() );
00105         mVertices.resize( new_end - mVertices.begin() );
00106     }
00107 
00108     // Automatically called by CppUnit after each test function.
00109     void tearDown()
00110     {
00111 
00112         delete mMesh;
00113         if( mErr ) cout << mErr << endl;
00114         mErr.clear();
00115     }
00116 
00117   public:
00118     void test_get_geometric_dimension()
00119     {
00120         int d = mMesh->get_geometric_dimension( mErr );
00121         CPPUNIT_ASSERT_EQUAL( d, 3 );
00122     }
00123 
00124     void test_vertices()
00125     {
00126         size_t nbVert = mVertices.size();
00127         CPPUNIT_ASSERT_EQUAL( 9, (int)nbVert );
00128 
00129         MBMesquite::MsqVertex correct_coords[9], coords[9];
00130         correct_coords[0].set( 1, 0, 0 );
00131         correct_coords[1].set( 0, 1.732, 0 );
00132         correct_coords[2].set( -1, 0, 0 );
00133         correct_coords[3].set( -1, -2, 0 );
00134         correct_coords[4].set( 1, -2, 0 );
00135         correct_coords[5].set( 2.732, 1, 0 );
00136         correct_coords[6].set( 1.732, 2.732, 0 );
00137         correct_coords[7].set( -1.732, 2.732, 0 );
00138         correct_coords[8].set( -2.732, 1, 0 );
00139 
00140         mMesh->vertices_get_coordinates( arrptr( mVertices ), coords, nbVert, mErr );
00141         CPPUNIT_ASSERT( !mErr );
00142         for( size_t i = 0; i < nbVert; ++i )
00143         {
00144             for( int j = 0; j < 3; ++j )
00145                 CPPUNIT_ASSERT_DOUBLES_EQUAL( coords[i][j], correct_coords[i][j], .01 );
00146         }
00147 
00148         coords[3].set( 2., 3., 4. );
00149         mMesh->vertex_set_coordinates( mVertices[3], coords[3], mErr );
00150         CPPUNIT_ASSERT( !mErr );
00151         MBMesquite::MsqVertex coords_2;
00152         mMesh->vertices_get_coordinates( &mVertices[3], &coords_2, 1, mErr );
00153         CPPUNIT_ASSERT( !mErr );
00154         for( int j = 0; j < 3; ++j )
00155             CPPUNIT_ASSERT_DOUBLES_EQUAL( coords[3][j], coords_2[j], 1e-6 );
00156     }
00157 
00158     //  void test_vertices_are_on_boundary()
00159     //  {
00160     //    bool on_bnd[9];
00161     //    mMesh->vertices_are_on_boundary(mVertices, on_bnd, nbVert, mErr);
00162     //    CPPUNIT_ASSERT(!mErr);
00163     //    bool correct_boundary[9] = {false, false, false, true, true, true, true, true, true};
00164     //    for (size_t i=0; i<nbVert; ++i) {
00165     //      CPPUNIT_ASSERT(on_bnd[i] == correct_boundary[i]);
00166     //    }
00167     //  }
00168 
00169     void test_vertex_is_fixed()
00170     {
00171         size_t nbVert         = mVertices.size();
00172         bool correct_fixed[9] = { false, false, false, true, true, true, true, true, true };
00173         std::vector< bool > fixed;
00174         mMesh->vertices_get_fixed_flag( arrptr( mVertices ), fixed, 9, mErr );
00175         CPPUNIT_ASSERT( !mErr );
00176         CPPUNIT_ASSERT_EQUAL( (size_t)8, fixed.size() );
00177         for( size_t i = 0; i < nbVert; ++i )
00178         {
00179             CPPUNIT_ASSERT_EQUAL( correct_fixed[i], (bool)fixed[i] );
00180         }
00181     }
00182 
00183     void test_vertex_byte()
00184     {
00185         size_t nbVert = mVertices.size();
00186         size_t i;
00187         unsigned char* bytes = new unsigned char[nbVert];
00188         mMesh->vertices_get_byte( arrptr( mVertices ), bytes, nbVert, mErr );
00189         CPPUNIT_ASSERT( !mErr );
00190 
00191         // Asserts all vertex bytes are initialised to 0.
00192         for( i = 0; i < nbVert; ++i )
00193             CPPUNIT_ASSERT( bytes[i] == 0 );
00194 
00195         // Test various vertex byte read / write routines.
00196         bytes[3] |= 4;
00197         mMesh->vertices_set_byte( arrptr( mVertices ), bytes, nbVert, mErr );
00198         CPPUNIT_ASSERT( !mErr );
00199         mMesh->vertex_set_byte( mVertices[5], 8, mErr );
00200         CPPUNIT_ASSERT( !mErr );
00201         unsigned char byte;
00202         mMesh->vertex_get_byte( mVertices[3], &byte, mErr );
00203         CPPUNIT_ASSERT( !mErr );
00204         CPPUNIT_ASSERT( byte == 4 );
00205         mMesh->vertices_get_byte( arrptr( mVertices ), bytes, nbVert, mErr );
00206         CPPUNIT_ASSERT( !mErr );
00207         for( i = 0; i < nbVert; ++i )
00208         {
00209             if( i == 3 )
00210                 CPPUNIT_ASSERT( bytes[i] == 4 );
00211             else if( i == 5 )
00212                 CPPUNIT_ASSERT( bytes[i] == 8 );
00213             else
00214                 CPPUNIT_ASSERT( bytes[i] == 0 );
00215         }
00216 
00217         delete[] bytes;
00218     }
00219 
00220     void test_vertex_get_attached_elements()
00221     {
00222         size_t i;
00223         const size_t nbVert = mVertices.size();
00224 
00225         std::vector< MBMesquite::Mesh::ElementHandle > elements;
00226         std::vector< size_t > offsets;
00227         mMesh->vertices_get_attached_elements( arrptr( mVertices ), mVertices.size(), elements, offsets, mErr );
00228         CPPUNIT_ASSERT( !mErr );
00229         CPPUNIT_ASSERT_EQUAL( offsets.size(), mVertices.size() + 1 );
00230 
00231         // checks we have 6 vertices contained in 1 element only
00232         // and 3 vertices contained in 3 elements.
00233         int n1 = 0;
00234         int n3 = 0;
00235         for( i = 1; i <= mVertices.size(); ++i )
00236         {
00237             const size_t nev = offsets[i] - offsets[i - 1];
00238             if( nev == 1 )
00239                 ++n1;
00240             else if( nev == 3 )
00241                 ++n3;
00242             else  // failure.
00243                 CPPUNIT_ASSERT( false );
00244         }
00245         CPPUNIT_ASSERT( n1 == 6 );
00246         CPPUNIT_ASSERT( n3 == 3 );
00247 
00248         // gets the index of a vertex in a corner
00249         int one_corner_vertex_index = 0;
00250         for( i = 0; i < nbVert; ++i )
00251         {
00252             const size_t nev = offsets[i + 1] - offsets[i];
00253             if( 1 == nev ) break;
00254         }
00255         CPPUNIT_ASSERT( i < nbVert );
00256         one_corner_vertex_index = i;
00257 
00258         // retrieve the attached element.
00259         // This is a poor test.  We allow an element handle of zero,
00260         // and just testing that the function returned something isn't
00261         // that useful. - J.K.
00262         // MBMesquite::Mesh::ElementHandle elem=0;
00263         // mMesh->vertex_get_attached_elements(mVertices[one_corner_vertex_index], &elem, 1, mErr);
00264         // CPPUNIT_ASSERT(!mErr);
00265         // CPPUNIT_ASSERT(elem!=0);
00266     }
00267 
00268     void test_elements()
00269     {
00270         CPPUNIT_ASSERT_EQUAL( 4, (int)mElements.size() );
00271     }
00272 
00273     void test_elements_get_attached_vertices()
00274     {
00275         const size_t nbElem = mElements.size();
00276 
00277         // checks we have 3 elements containing 4 vertices
00278         // and 1 element containing 3 vertices.
00279         int n3 = 0;
00280         int n4 = 0;
00281         size_t i;
00282         for( i = 0; i < nbElem; ++i )
00283         {
00284             size_t nve = mOffsets[i + 1] - mOffsets[i];
00285             if( nve == 3 )
00286                 ++n3;
00287             else if( nve == 4 )
00288                 ++n4;
00289             else  // failure.
00290                 CPPUNIT_ASSERT( false );
00291         }
00292         CPPUNIT_ASSERT( n3 == 1 );  // 1 triangle
00293         CPPUNIT_ASSERT( n4 == 3 );  // 3 quads
00294 
00295         // Make sure CSR data is valid
00296         std::map< MBMesquite::Mesh::VertexHandle, int > vtx_repeated_occurence;
00297         for( i = 0; i < mVertices.size(); ++i )
00298             vtx_repeated_occurence[mVertices[i]] = 0;
00299         for( i = 0; i < mConnectivity.size(); ++i )
00300             ++vtx_repeated_occurence[mConnectivity[i]];
00301         for( i = 0; i < 9; ++i )
00302         {
00303             CPPUNIT_ASSERT( vtx_repeated_occurence[mVertices[i]] <= 3 );
00304         }
00305 
00306         // Makes sure CSR offsets are valid
00307         CPPUNIT_ASSERT( mOffsets[0] == 0 );
00308         CPPUNIT_ASSERT( mOffsets[1] >= 3 && mOffsets[1] <= 12 );
00309         CPPUNIT_ASSERT( mOffsets[2] >= 3 && mOffsets[2] <= 12 );
00310         CPPUNIT_ASSERT( mOffsets[3] >= 3 && mOffsets[3] <= 12 );
00311         CPPUNIT_ASSERT( mOffsets[4] == 15 );
00312     }
00313 
00314     void test_elements_get_topology()
00315     {
00316         const size_t nbElem               = mElements.size();
00317         int nb_quads                      = 0;
00318         int nb_tri                        = 0;
00319         MBMesquite::EntityTopology* topos = new MBMesquite::EntityTopology[nbElem];
00320         mMesh->elements_get_topologies( arrptr( mElements ), topos, nbElem, mErr );
00321         CPPUNIT_ASSERT( !mErr );
00322         for( size_t i = 0; i < nbElem; ++i )
00323         {
00324             switch( topos[i] )
00325             {
00326                 case MBMesquite::TRIANGLE:
00327                     ++nb_tri;
00328                     break;
00329                 case MBMesquite::QUADRILATERAL:
00330                     ++nb_quads;
00331                     break;
00332                 default:
00333                     CPPUNIT_FAIL( "Topology should be quad or Hex only." );
00334             }
00335         }
00336         CPPUNIT_ASSERT_EQUAL( 1, nb_tri );
00337         CPPUNIT_ASSERT_EQUAL( 3, nb_quads );
00338         delete[] topos;
00339     }
00340 
00341     void test_element_get_attached_vertex_indices()
00342     {
00343         // Find the index of the triangle
00344         MBMesquite::EntityTopology topo = Mesquite::MIXED;
00345         int tri_index                   = -1;
00346         while( topo != MBMesquite::TRIANGLE )
00347         {
00348             ++tri_index;
00349             CPPUNIT_ASSERT( (unsigned)tri_index < mElements.size() );
00350             MBMesquite::Mesh::ElementHandle handle = mElements[tri_index];
00351             mMesh->elements_get_topologies( &handle, &topo, 1, mErr );
00352             CPPUNIT_ASSERT( !mErr );
00353         }
00354 
00355         // creates list with correct vertices coordinates for the triangle
00356         std::vector< Mesquite::Vector3D > correct_coords;
00357         correct_coords.push_back( Mesquite::Vector3D( 1., 0., 0. ) );
00358         correct_coords.push_back( Mesquite::Vector3D( 0., 1.732050807, 0. ) );
00359         correct_coords.push_back( Mesquite::Vector3D( -1., 0., 0. ) );
00360 
00361         // Creates same list from the mesh implementation
00362         std::vector< MBMesquite::MsqVertex > tri_coords( 3 );
00363         mMesh->vertices_get_coordinates( &mConnectivity[mOffsets[tri_index]], arrptr( tri_coords ), 3, mErr );
00364         CPPUNIT_ASSERT( !mErr );
00365 
00366         // Makes sure both list contain the same elements (not necessarily in the same order).
00367         std::vector< Mesquite::Vector3D >::iterator correct_iter;
00368         std::vector< MBMesquite::MsqVertex >::iterator tri_iter;
00369         for( tri_iter = tri_coords.begin(); tri_iter != tri_coords.end(); ++tri_iter )
00370         {
00371             for( correct_iter = correct_coords.begin(); correct_iter != correct_coords.end(); ++correct_iter )
00372             {
00373                 if( Mesquite::Vector3D::distance_between( *tri_iter, *correct_iter ) < 10e-4 ) break;
00374             }
00375 
00376             // check if a match was found
00377             CPPUNIT_ASSERT( correct_iter != correct_coords.end() );
00378 
00379             // remove match from list
00380             correct_coords.erase( correct_iter );
00381         }
00382         CPPUNIT_ASSERT( correct_coords.empty() );
00383     }
00384 };
00385 
00386 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MeshInterfaceTest, "MeshInterfaceTest" );
00387 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MeshInterfaceTest, "Unit" );
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines