MOAB: Mesh Oriented datABase  (version 5.4.0)
mbcn_test.cpp
Go to the documentation of this file.
00001 #include "TestUtil.hpp"
00002 #include "moab/CN.hpp"
00003 
00004 using namespace moab;
00005 
00006 void test_dimension_pair();
00007 void test_type_names();
00008 void test_dimension();
00009 void test_vertices_per_entity();
00010 void test_num_sub_entities();
00011 
00012 void test_sub_entity_type_vtx();
00013 void test_sub_entity_type_edge();
00014 void test_sub_entity_type_tri();
00015 void test_sub_entity_type_quad();
00016 void test_sub_entity_type_tet();
00017 void test_sub_entity_type_pyr();
00018 void test_sub_entity_type_pri();
00019 void test_sub_entity_type_knife();
00020 void test_sub_entity_type_hex();
00021 
00022 void test_sub_entity_indices_vtx();
00023 void test_sub_entity_indices_edge();
00024 void test_sub_entity_indices_tri();
00025 void test_sub_entity_indices_quad();
00026 void test_sub_entity_indices_tet();
00027 void test_sub_entity_indices_pyr();
00028 void test_sub_entity_indices_pri();
00029 void test_sub_entity_indices_hex();
00030 
00031 void test_side_number_tri();
00032 void test_side_number_quad();
00033 void test_side_number_tet();
00034 void test_side_number_pyr();
00035 void test_side_number_pri();
00036 void test_side_number_hex();
00037 
00038 void test_opposite_side_tri();
00039 void test_opposite_side_quad();
00040 void test_opposite_side_tet();
00041 void test_opposite_side_hex();
00042 
00043 void test_has_mid_nodes( EntityType type );
00044 void test_has_mid_nodes_edge()
00045 {
00046     test_has_mid_nodes( MBEDGE );
00047 }
00048 void test_has_mid_nodes_tri()
00049 {
00050     test_has_mid_nodes( MBTRI );
00051 }
00052 void test_has_mid_nodes_quad()
00053 {
00054     test_has_mid_nodes( MBQUAD );
00055 }
00056 void test_has_mid_nodes_tet()
00057 {
00058     test_has_mid_nodes( MBTET );
00059 }
00060 void test_has_mid_nodes_pyr()
00061 {
00062     test_has_mid_nodes( MBPYRAMID );
00063 }
00064 void test_has_mid_nodes_pri()
00065 {
00066     test_has_mid_nodes( MBPRISM );
00067 }
00068 void test_has_mid_nodes_knife()
00069 {
00070     test_has_mid_nodes( MBKNIFE );
00071 }
00072 void test_has_mid_nodes_hex()
00073 {
00074     test_has_mid_nodes( MBHEX );
00075 }
00076 
00077 void test_ho_node_parent();
00078 void test_ho_node_index();
00079 
00080 void test_sub_entity_nodes( EntityType parent, int sub_dimension );
00081 void test_sub_entity_nodes( EntityType parent, int num_nodes, int sub_dimension );
00082 void test_sub_entity_nodes_tri_edges()
00083 {
00084     test_sub_entity_nodes( MBTRI, 1 );
00085 }
00086 void test_sub_entity_nodes_quad_edges()
00087 {
00088     test_sub_entity_nodes( MBQUAD, 1 );
00089 }
00090 void test_sub_entity_nodes_tet_edges()
00091 {
00092     test_sub_entity_nodes( MBTET, 1 );
00093 }
00094 void test_sub_entity_nodes_tet_faces()
00095 {
00096     test_sub_entity_nodes( MBTET, 2 );
00097 }
00098 void test_sub_entity_nodes_pyr_edges()
00099 {
00100     test_sub_entity_nodes( MBPYRAMID, 1 );
00101 }
00102 void test_sub_entity_nodes_pyr_faces()
00103 {
00104     test_sub_entity_nodes( MBPYRAMID, 2 );
00105 }
00106 void test_sub_entity_nodes_pri_edges()
00107 {
00108     test_sub_entity_nodes( MBPRISM, 1 );
00109 }
00110 void test_sub_entity_nodes_pri_faces()
00111 {
00112     test_sub_entity_nodes( MBPRISM, 2 );
00113 }
00114 void test_sub_entity_nodes_kni_edges()
00115 {
00116     test_sub_entity_nodes( MBKNIFE, 1 );
00117 }
00118 void test_sub_entity_nodes_kni_faces()
00119 {
00120     test_sub_entity_nodes( MBKNIFE, 2 );
00121 }
00122 void test_sub_entity_nodes_hex_edges()
00123 {
00124     test_sub_entity_nodes( MBHEX, 1 );
00125 }
00126 void test_sub_entity_nodes_hex_faces()
00127 {
00128     test_sub_entity_nodes( MBHEX, 2 );
00129 }
00130 void prism_issue();
00131 void test_wedges();
00132 
00133 int main()
00134 {
00135     int result = 0;
00136     result += RUN_TEST( test_dimension_pair );
00137     result += RUN_TEST( test_type_names );
00138     result += RUN_TEST( test_dimension );
00139     result += RUN_TEST( test_vertices_per_entity );
00140     result += RUN_TEST( test_num_sub_entities );
00141 
00142     result += RUN_TEST( test_sub_entity_type_vtx );
00143     result += RUN_TEST( test_sub_entity_type_edge );
00144     result += RUN_TEST( test_sub_entity_type_tri );
00145     result += RUN_TEST( test_sub_entity_type_quad );
00146     result += RUN_TEST( test_sub_entity_type_tet );
00147     result += RUN_TEST( test_sub_entity_type_pyr );
00148     result += RUN_TEST( test_sub_entity_type_pri );
00149     result += RUN_TEST( test_sub_entity_type_knife );
00150     result += RUN_TEST( test_sub_entity_type_hex );
00151 
00152     result += RUN_TEST( test_sub_entity_indices_vtx );
00153     result += RUN_TEST( test_sub_entity_indices_edge );
00154     result += RUN_TEST( test_sub_entity_indices_tri );
00155     result += RUN_TEST( test_sub_entity_indices_quad );
00156     result += RUN_TEST( test_sub_entity_indices_tet );
00157     result += RUN_TEST( test_sub_entity_indices_pyr );
00158     result += RUN_TEST( test_sub_entity_indices_pri );
00159     result += RUN_TEST( test_sub_entity_indices_hex );
00160 
00161     result += RUN_TEST( test_side_number_tri );
00162     result += RUN_TEST( test_side_number_quad );
00163     result += RUN_TEST( test_side_number_tet );
00164     result += RUN_TEST( test_side_number_pyr );
00165     result += RUN_TEST( test_side_number_pri );
00166     result += RUN_TEST( test_side_number_hex );
00167 
00168     result += RUN_TEST( test_opposite_side_tri );
00169     result += RUN_TEST( test_opposite_side_quad );
00170     result += RUN_TEST( test_opposite_side_tet );
00171     result += RUN_TEST( test_opposite_side_hex );
00172 
00173     result += RUN_TEST( test_has_mid_nodes_edge );
00174     result += RUN_TEST( test_has_mid_nodes_tri );
00175     result += RUN_TEST( test_has_mid_nodes_quad );
00176     result += RUN_TEST( test_has_mid_nodes_tet );
00177     result += RUN_TEST( test_has_mid_nodes_pyr );
00178     result += RUN_TEST( test_has_mid_nodes_pri );
00179     result += RUN_TEST( test_has_mid_nodes_knife );
00180     result += RUN_TEST( test_has_mid_nodes_hex );
00181 
00182     result += RUN_TEST( test_sub_entity_nodes_tri_edges );
00183     result += RUN_TEST( test_sub_entity_nodes_quad_edges );
00184     result += RUN_TEST( test_sub_entity_nodes_tet_edges );
00185     result += RUN_TEST( test_sub_entity_nodes_tet_faces );
00186     result += RUN_TEST( test_sub_entity_nodes_pyr_edges );
00187     result += RUN_TEST( test_sub_entity_nodes_pyr_faces );
00188     result += RUN_TEST( test_sub_entity_nodes_pri_edges );
00189     result += RUN_TEST( test_sub_entity_nodes_pri_faces );
00190     result += RUN_TEST( test_sub_entity_nodes_kni_edges );
00191     result += RUN_TEST( test_sub_entity_nodes_kni_faces );
00192     result += RUN_TEST( test_sub_entity_nodes_hex_edges );
00193     result += RUN_TEST( test_sub_entity_nodes_hex_faces );
00194 
00195     result += RUN_TEST( test_ho_node_parent );
00196     result += RUN_TEST( test_ho_node_index );
00197     result += RUN_TEST( prism_issue );
00198     result += RUN_TEST( test_wedges );
00199     return result;
00200 }
00201 
00202 const EntityType elem_types[] = { MBTRI, MBQUAD, MBTET, MBPYRAMID, MBPRISM, MBHEX, MBMAXTYPE };
00203 // const int num_elem_types = sizeof(elem_types)/sizeof(elem_types[0]) - 1;
00204 
00205 void test_dimension_pair()
00206 {
00207     DimensionPair dp;
00208 
00209     dp = CN::TypeDimensionMap[0];
00210     CHECK_EQUAL( MBVERTEX, dp.first );
00211     CHECK_EQUAL( MBVERTEX, dp.second );
00212 
00213     dp = CN::TypeDimensionMap[1];
00214     CHECK_EQUAL( MBEDGE, dp.first );
00215     CHECK_EQUAL( MBEDGE, dp.second );
00216 
00217     dp = CN::TypeDimensionMap[2];
00218     CHECK_EQUAL( MBTRI, dp.first );
00219     CHECK_EQUAL( MBPOLYGON, dp.second );
00220 
00221     dp = CN::TypeDimensionMap[3];
00222     CHECK_EQUAL( MBTET, dp.first );
00223     CHECK_EQUAL( MBPOLYHEDRON, dp.second );
00224 }
00225 
00226 void test_type_names()
00227 {
00228     for( EntityType t = MBVERTEX; t != MBMAXTYPE; ++t )
00229     {
00230         const char* name = CN::EntityTypeName( t );
00231         CHECK_EQUAL( t, CN::EntityTypeFromName( name ) );
00232     }
00233 }
00234 
00235 void test_dimension()
00236 {
00237     CHECK_EQUAL( 0, CN::Dimension( MBVERTEX ) );
00238     CHECK_EQUAL( 1, CN::Dimension( MBEDGE ) );
00239     CHECK_EQUAL( 2, CN::Dimension( MBTRI ) );
00240     CHECK_EQUAL( 2, CN::Dimension( MBQUAD ) );
00241     CHECK_EQUAL( 2, CN::Dimension( MBPOLYGON ) );
00242     CHECK_EQUAL( 3, CN::Dimension( MBTET ) );
00243     CHECK_EQUAL( 3, CN::Dimension( MBPYRAMID ) );
00244     CHECK_EQUAL( 3, CN::Dimension( MBPRISM ) );
00245     CHECK_EQUAL( 3, CN::Dimension( MBKNIFE ) );
00246     CHECK_EQUAL( 3, CN::Dimension( MBHEX ) );
00247     CHECK_EQUAL( 3, CN::Dimension( MBPOLYHEDRON ) );
00248 }
00249 
00250 void test_vertices_per_entity()
00251 {
00252     CHECK_EQUAL( 1, CN::VerticesPerEntity( MBVERTEX ) );
00253     CHECK_EQUAL( 2, CN::VerticesPerEntity( MBEDGE ) );
00254     CHECK_EQUAL( 3, CN::VerticesPerEntity( MBTRI ) );
00255     CHECK_EQUAL( 4, CN::VerticesPerEntity( MBQUAD ) );
00256     CHECK_EQUAL( 4, CN::VerticesPerEntity( MBTET ) );
00257     CHECK_EQUAL( 5, CN::VerticesPerEntity( MBPYRAMID ) );
00258     CHECK_EQUAL( 6, CN::VerticesPerEntity( MBPRISM ) );
00259     CHECK_EQUAL( 7, CN::VerticesPerEntity( MBKNIFE ) );
00260     CHECK_EQUAL( 8, CN::VerticesPerEntity( MBHEX ) );
00261 }
00262 
00263 void test_num_sub_entities()
00264 {
00265     CHECK_EQUAL( 1, CN::NumSubEntities( MBVERTEX, 0 ) );
00266 
00267     CHECK_EQUAL( 2, CN::NumSubEntities( MBEDGE, 0 ) );
00268     CHECK_EQUAL( 1, CN::NumSubEntities( MBEDGE, 1 ) );
00269 
00270     CHECK_EQUAL( 3, CN::NumSubEntities( MBTRI, 0 ) );
00271     CHECK_EQUAL( 3, CN::NumSubEntities( MBTRI, 1 ) );
00272     CHECK_EQUAL( 1, CN::NumSubEntities( MBTRI, 2 ) );
00273 
00274     CHECK_EQUAL( 4, CN::NumSubEntities( MBQUAD, 0 ) );
00275     CHECK_EQUAL( 4, CN::NumSubEntities( MBQUAD, 1 ) );
00276     CHECK_EQUAL( 1, CN::NumSubEntities( MBQUAD, 2 ) );
00277 
00278     CHECK_EQUAL( 4, CN::NumSubEntities( MBTET, 0 ) );
00279     CHECK_EQUAL( 6, CN::NumSubEntities( MBTET, 1 ) );
00280     CHECK_EQUAL( 4, CN::NumSubEntities( MBTET, 2 ) );
00281 
00282     CHECK_EQUAL( 5, CN::NumSubEntities( MBPYRAMID, 0 ) );
00283     CHECK_EQUAL( 8, CN::NumSubEntities( MBPYRAMID, 1 ) );
00284     CHECK_EQUAL( 5, CN::NumSubEntities( MBPYRAMID, 2 ) );
00285 
00286     CHECK_EQUAL( 6, CN::NumSubEntities( MBPRISM, 0 ) );
00287     CHECK_EQUAL( 9, CN::NumSubEntities( MBPRISM, 1 ) );
00288     CHECK_EQUAL( 5, CN::NumSubEntities( MBPRISM, 2 ) );
00289 
00290     CHECK_EQUAL( 7, CN::NumSubEntities( MBKNIFE, 0 ) );
00291     CHECK_EQUAL( 10, CN::NumSubEntities( MBKNIFE, 1 ) );
00292     CHECK_EQUAL( 5, CN::NumSubEntities( MBKNIFE, 2 ) );
00293 
00294     CHECK_EQUAL( 8, CN::NumSubEntities( MBHEX, 0 ) );
00295     CHECK_EQUAL( 12, CN::NumSubEntities( MBHEX, 1 ) );
00296     CHECK_EQUAL( 6, CN::NumSubEntities( MBHEX, 2 ) );
00297 }
00298 
00299 void do_test_sub_entity_type_2d( EntityType type )
00300 {
00301     for( int j = 0; j < CN::VerticesPerEntity( type ); ++j )
00302     {
00303         CHECK_EQUAL( MBVERTEX, CN::SubEntityType( type, 0, j ) );
00304         CHECK_EQUAL( MBEDGE, CN::SubEntityType( type, 1, j ) );
00305     }
00306     CHECK_EQUAL( type, CN::SubEntityType( type, 2, 0 ) );
00307 }
00308 
00309 void do_test_sub_entity_type_3d( EntityType type, int num_faces, const EntityType* face_types )
00310 {
00311     for( int j = 0; j < CN::VerticesPerEntity( type ); ++j )
00312     {
00313         CHECK_EQUAL( MBVERTEX, CN::SubEntityType( type, 0, j ) );
00314     }
00315 
00316     for( int j = 0; j < CN::NumSubEntities( type, 1 ); ++j )
00317     {
00318         CHECK_EQUAL( MBEDGE, CN::SubEntityType( type, 1, j ) );
00319     }
00320 
00321     for( int j = 0; j < num_faces; ++j )
00322     {
00323         EntityType sub_type = CN::SubEntityType( type, 2, j );
00324         CHECK_EQUAL( face_types[j], sub_type );
00325     }
00326 
00327     CHECK_EQUAL( type, CN::SubEntityType( type, 3, 0 ) );
00328 }
00329 
00330 void test_sub_entity_type_vtx()
00331 {
00332     CHECK_EQUAL( MBVERTEX, CN::SubEntityType( MBVERTEX, 0, 0 ) );
00333 }
00334 
00335 void test_sub_entity_type_edge()
00336 {
00337     CHECK_EQUAL( MBVERTEX, CN::SubEntityType( MBEDGE, 0, 0 ) );
00338     CHECK_EQUAL( MBVERTEX, CN::SubEntityType( MBEDGE, 0, 1 ) );
00339     CHECK_EQUAL( MBEDGE, CN::SubEntityType( MBEDGE, 1, 0 ) );
00340 }
00341 
00342 void test_sub_entity_type_tri()
00343 {
00344     do_test_sub_entity_type_2d( MBTRI );
00345 }
00346 
00347 void test_sub_entity_type_quad()
00348 {
00349     do_test_sub_entity_type_2d( MBQUAD );
00350 }
00351 
00352 void test_sub_entity_type_tet()
00353 {
00354     const EntityType types[] = { MBTRI, MBTRI, MBTRI, MBTRI };
00355     do_test_sub_entity_type_3d( MBTET, sizeof( types ) / sizeof( types[0] ), types );
00356 }
00357 
00358 void test_sub_entity_type_pyr()
00359 {
00360     const EntityType types[] = { MBTRI, MBTRI, MBTRI, MBTRI, MBQUAD };
00361     do_test_sub_entity_type_3d( MBPYRAMID, sizeof( types ) / sizeof( types[0] ), types );
00362 }
00363 
00364 void test_sub_entity_type_pri()
00365 {
00366     const EntityType types[] = { MBQUAD, MBQUAD, MBQUAD, MBTRI, MBTRI };
00367     do_test_sub_entity_type_3d( MBPRISM, sizeof( types ) / sizeof( types[0] ), types );
00368 }
00369 
00370 void test_sub_entity_type_knife()
00371 {
00372     const EntityType types[] = { MBQUAD, MBQUAD, MBQUAD, MBQUAD, MBQUAD };
00373     do_test_sub_entity_type_3d( MBKNIFE, sizeof( types ) / sizeof( types[0] ), types );
00374 }
00375 
00376 void test_sub_entity_type_hex()
00377 {
00378     const EntityType types[] = { MBQUAD, MBQUAD, MBQUAD, MBQUAD, MBQUAD, MBQUAD };
00379     do_test_sub_entity_type_3d( MBHEX, sizeof( types ) / sizeof( types[0] ), types );
00380 }
00381 
00382 void test_0d_sub_entity_indices( EntityType type, int num_vtx )
00383 {
00384     for( int i = 0; i < num_vtx; ++i )
00385     {
00386         // zero input array
00387         int indices[2] = { 0, -100 };
00388         // check correct results
00389         CN::SubEntityVertexIndices( type, 0, i, indices );
00390         CHECK_EQUAL( i, indices[0] );
00391         // check didn't write past end of array
00392         CHECK_EQUAL( -100, indices[1] );
00393     }
00394 }
00395 
00396 void test_1d_sub_entity_indices( EntityType type, int num_edges, const int ( *edge_indices )[2] )
00397 {
00398     for( int i = 0; i < num_edges; ++i )
00399     {
00400         // zero input array
00401         int indices[3] = { 0, 0, -99 };
00402         // check correct results
00403         CN::SubEntityVertexIndices( type, 1, i, indices );
00404         if( edge_indices[i][0] == indices[0] )
00405         {
00406             CHECK_EQUAL( edge_indices[i][1], indices[1] );
00407         }
00408         else
00409         {
00410             CHECK_EQUAL( edge_indices[i][0], indices[1] );
00411             CHECK_EQUAL( edge_indices[i][1], indices[0] );
00412         }
00413         // check didn't write past end of array
00414         CHECK_EQUAL( -99, indices[2] );
00415     }
00416 }
00417 
00418 void test_2d_sub_entity_indices( EntityType type, int num_faces, const int ( *face_indices )[5] )
00419 {
00420     for( int i = 0; i < num_faces; ++i )
00421     {
00422         // zero input array
00423         int indices[5] = { 0, 0, 0, -99, -99 };
00424         // check correct results
00425         CN::SubEntityVertexIndices( type, 2, i, indices );
00426         const int num_vtx = face_indices[i][0];
00427         if( num_vtx != 3 ) CHECK_EQUAL( 4, num_vtx );
00428         const int* exp_index = face_indices[i] + 1;
00429         int off              = std::find( indices, indices + num_vtx, exp_index[0] ) - indices;
00430         CHECK( off < num_vtx );
00431         /* Expect faces to be ordered such that CCW normal is outwards
00432          *
00433       bool reverse = indices[(off+num_vtx-1)%num_vtx] == exp_index[1];
00434       if (reverse) {
00435         CHECK_EQUAL( exp_index[1], indices[(off+num_vtx-1)%num_vtx] );
00436         CHECK_EQUAL( exp_index[2], indices[(off+num_vtx-2)%num_vtx] );
00437         if (num_vtx == 4)
00438           CHECK_EQUAL( exp_index[3], indices[(off+num_vtx-3)%num_vtx] );
00439       }
00440       else {
00441           */
00442         CHECK_EQUAL( exp_index[1], indices[( off + 1 ) % num_vtx] );
00443         CHECK_EQUAL( exp_index[2], indices[( off + 2 ) % num_vtx] );
00444         if( num_vtx == 4 ) CHECK_EQUAL( exp_index[3], indices[( off + 3 ) % num_vtx] );
00445         /*
00446       }
00447         */
00448 
00449         // check didn't write past end of array
00450         if( num_vtx == 3 ) CHECK_EQUAL( -99, indices[3] );
00451         CHECK_EQUAL( -99, indices[4] );
00452     }
00453 }
00454 
00455 void test_elem_as_sub_entity( EntityType type, int dim, int num_vertices )
00456 {
00457     int indices[9] = { -2, -2, -2, -2, -2, -2, -2, -2, -2 };
00458     CN::SubEntityVertexIndices( type, dim, 0, indices );
00459     for( int i = 0; i < num_vertices; ++i )
00460         CHECK_EQUAL( i, indices[i] );
00461     // make sure didn't write past end
00462     CHECK_EQUAL( -2, indices[num_vertices] );
00463 }
00464 
00465 void test_sub_entity_indices_vtx()
00466 {
00467     test_elem_as_sub_entity( MBVERTEX, 0, 1 );
00468 }
00469 
00470 void test_sub_entity_indices_edge()
00471 {
00472     test_0d_sub_entity_indices( MBEDGE, 2 );
00473     test_elem_as_sub_entity( MBEDGE, 1, 2 );
00474 }
00475 
00476 void test_sub_entity_indices_tri()
00477 {
00478     const int edges[3][2] = { { 0, 1 }, { 1, 2 }, { 2, 0 } };
00479     test_0d_sub_entity_indices( MBTRI, 3 );
00480     test_1d_sub_entity_indices( MBTRI, 3, edges );
00481     test_elem_as_sub_entity( MBTRI, 2, 3 );
00482 }
00483 
00484 void test_sub_entity_indices_quad()
00485 {
00486     const int edges[4][2] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 } };
00487     test_0d_sub_entity_indices( MBQUAD, 4 );
00488     test_1d_sub_entity_indices( MBQUAD, 4, edges );
00489     test_elem_as_sub_entity( MBQUAD, 2, 4 );
00490 }
00491 
00492 void test_sub_entity_indices_tet()
00493 {
00494     const EntityType type = MBTET;
00495     const int num_vtx     = 4;
00496     const int edges[][2]  = { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 3 }, { 2, 3 } };
00497     const int faces[][5]  = { { 3, 0, 1, 3, 0 }, { 3, 1, 2, 3, 0 }, { 3, 2, 0, 3, 0 }, { 3, 2, 1, 0, 0 } };
00498     test_0d_sub_entity_indices( type, num_vtx );
00499     test_1d_sub_entity_indices( type, sizeof( edges ) / sizeof( edges[0] ), edges );
00500     test_2d_sub_entity_indices( type, sizeof( faces ) / sizeof( faces[0] ), faces );
00501     test_elem_as_sub_entity( type, 3, num_vtx );
00502 }
00503 
00504 void test_sub_entity_indices_pyr()
00505 {
00506     const EntityType type = MBPYRAMID;
00507     const int num_vtx     = 5;
00508     const int edges[][2]  = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 4 }, { 2, 4 }, { 3, 4 } };
00509     const int faces[][5]  = {
00510         { 3, 0, 1, 4, 0 }, { 3, 1, 2, 4, 0 }, { 3, 2, 3, 4, 0 }, { 3, 3, 0, 4, 0 }, { 4, 3, 2, 1, 0 } };
00511     test_0d_sub_entity_indices( type, num_vtx );
00512     test_1d_sub_entity_indices( type, sizeof( edges ) / sizeof( edges[0] ), edges );
00513     test_2d_sub_entity_indices( type, sizeof( faces ) / sizeof( faces[0] ), faces );
00514     test_elem_as_sub_entity( type, 3, num_vtx );
00515 }
00516 
00517 void test_sub_entity_indices_pri()
00518 {
00519     const EntityType type = MBPRISM;
00520     const int num_vtx     = 6;
00521     const int edges[][2] = { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 4 }, { 4, 5 }, { 5, 3 } };
00522     const int faces[][5] = {
00523         { 4, 0, 1, 4, 3 }, { 4, 1, 2, 5, 4 }, { 4, 2, 0, 3, 5 }, { 3, 2, 1, 0, 0 }, { 3, 3, 4, 5, 0 } };
00524     test_0d_sub_entity_indices( type, num_vtx );
00525     test_1d_sub_entity_indices( type, sizeof( edges ) / sizeof( edges[0] ), edges );
00526     test_2d_sub_entity_indices( type, sizeof( faces ) / sizeof( faces[0] ), faces );
00527     test_elem_as_sub_entity( type, 3, num_vtx );
00528 }
00529 
00530 void test_sub_entity_indices_hex()
00531 {
00532     const EntityType type = MBHEX;
00533     const int num_vtx     = 8;
00534     const int edges[][2]  = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 5 },
00535                              { 2, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 } };
00536     const int faces[][5]  = { { 4, 0, 1, 5, 4 }, { 4, 1, 2, 6, 5 }, { 4, 2, 3, 7, 6 },
00537                              { 4, 3, 0, 4, 7 }, { 4, 3, 2, 1, 0 }, { 4, 4, 5, 6, 7 } };
00538     test_0d_sub_entity_indices( type, num_vtx );
00539     test_1d_sub_entity_indices( type, sizeof( edges ) / sizeof( edges[0] ), edges );
00540     test_2d_sub_entity_indices( type, sizeof( faces ) / sizeof( faces[0] ), faces );
00541     test_elem_as_sub_entity( type, 3, num_vtx );
00542 }
00543 
00544 static void do_test_side_number_1d( EntityType type, int idx )
00545 {
00546     // define a random handle list
00547     const int elem_verts[] = { 7400, 6233, 3027, 0454, 6839, 5391, 7735, 3603 };
00548     // get side indices
00549     int side_idx[4] = { 0, 0 };
00550     CN::SubEntityVertexIndices( type, 1, idx, side_idx );
00551 
00552     // "reversed" and "offset" are the same thing for edges.
00553     int side_conn[2] = { elem_verts[side_idx[0]], elem_verts[side_idx[1]] };
00554     int rev_conn[2]  = { elem_verts[side_idx[1]], elem_verts[side_idx[0]] };
00555     int result_side = -100, result_sense = -100, result_offset = -100;
00556     int err = CN::SideNumber( type, elem_verts, side_conn, 2, 1, result_side, result_sense, result_offset );
00557     CHECK_EQUAL( 0, err );
00558     CHECK_EQUAL( idx, result_side );
00559     CHECK_EQUAL( 1, result_sense );
00560     CHECK_EQUAL( 0, result_offset );
00561     err = CN::SideNumber( type, elem_verts, rev_conn, 2, 1, result_side, result_sense, result_offset );
00562     CHECK_EQUAL( 0, err );
00563     CHECK_EQUAL( idx, result_side );
00564     CHECK( result_offset == 1 || result_sense == -1 );
00565 }
00566 
00567 static void do_test_side_number_2d( EntityType type, int idx )
00568 {
00569     // define a random handle list
00570     const int elem_verts[] = { 7400, 6233, 3027, 0454, 6839, 5391, 7735, 3603 };
00571     // get side indices
00572     const int side_size = CN::VerticesPerEntity( CN::SubEntityType( type, 2, idx ) );
00573     int side_idx[4]     = { 0, 0, 0, 0 };
00574     CN::SubEntityVertexIndices( type, 2, idx, side_idx );
00575 
00576     // for each possible forward or reverse offset
00577     for( int rev = -1; rev < 2; rev += 2 )
00578     {
00579         for( int off = 0; off < side_size; ++off )
00580         {
00581             int side_conn[4];
00582             side_conn[3] = 0;
00583             for( int i = 0; i < side_size; ++i )
00584                 side_conn[( side_size + rev * i ) % side_size] = elem_verts[side_idx[( i + off ) % side_size]];
00585 
00586             int result_side = -100, result_sense = -100, result_offset = -100;
00587             int err =
00588                 CN::SideNumber( type, elem_verts, side_conn, side_size, 2, result_side, result_sense, result_offset );
00589             CHECK_EQUAL( 0, err );
00590             CHECK_EQUAL( idx, result_side );
00591             CHECK_EQUAL( rev, result_sense );
00592             CHECK_EQUAL( off, result_offset );
00593         }
00594     }
00595 }
00596 
00597 void test_side_number_tri()
00598 {
00599     for( int side = 0; side < 3; ++side )
00600         do_test_side_number_1d( MBTRI, side );
00601 }
00602 
00603 void test_side_number_quad()
00604 {
00605     for( int side = 0; side < 4; ++side )
00606         do_test_side_number_1d( MBQUAD, side );
00607 }
00608 
00609 void test_side_number_tet()
00610 {
00611     for( int edge = 0; edge < 6; ++edge )
00612         do_test_side_number_1d( MBTET, edge );
00613     for( int face = 0; face < 4; ++face )
00614         do_test_side_number_2d( MBTET, face );
00615 }
00616 
00617 void test_side_number_pyr()
00618 {
00619     for( int edge = 0; edge < 8; ++edge )
00620         do_test_side_number_1d( MBPYRAMID, edge );
00621     for( int face = 0; face < 5; ++face )
00622         do_test_side_number_2d( MBPYRAMID, face );
00623 }
00624 
00625 void test_side_number_pri()
00626 {
00627     for( int edge = 0; edge < 9; ++edge )
00628         do_test_side_number_1d( MBPRISM, edge );
00629     for( int face = 0; face < 5; ++face )
00630         do_test_side_number_2d( MBPRISM, face );
00631 }
00632 
00633 void test_side_number_hex()
00634 {
00635     for( int edge = 0; edge < 12; ++edge )
00636         do_test_side_number_1d( MBHEX, edge );
00637     for( int face = 0; face < 6; ++face )
00638         do_test_side_number_2d( MBHEX, face );
00639 }
00640 
00641 void test_opposite_side_tri()
00642 {
00643     int idx, dim, err;
00644     err = CN::OppositeSide( MBTRI, 0, 0, idx, dim );
00645     CHECK_EQUAL( 0, err );
00646     CHECK_EQUAL( 1, dim );
00647     CHECK_EQUAL( 1, idx );
00648     err = CN::OppositeSide( MBTRI, 1, 0, idx, dim );
00649     CHECK_EQUAL( 0, err );
00650     CHECK_EQUAL( 1, dim );
00651     CHECK_EQUAL( 2, idx );
00652     err = CN::OppositeSide( MBTRI, 2, 0, idx, dim );
00653     CHECK_EQUAL( 0, err );
00654     CHECK_EQUAL( 1, dim );
00655     CHECK_EQUAL( 0, idx );
00656     err = CN::OppositeSide( MBTRI, 0, 1, idx, dim );
00657     CHECK_EQUAL( 0, err );
00658     CHECK_EQUAL( 0, dim );
00659     CHECK_EQUAL( 2, idx );
00660     err = CN::OppositeSide( MBTRI, 1, 1, idx, dim );
00661     CHECK_EQUAL( 0, err );
00662     CHECK_EQUAL( 0, dim );
00663     CHECK_EQUAL( 0, idx );
00664     err = CN::OppositeSide( MBTRI, 2, 1, idx, dim );
00665     CHECK_EQUAL( 0, err );
00666     CHECK_EQUAL( 0, dim );
00667     CHECK_EQUAL( 1, idx );
00668 }
00669 
00670 void test_opposite_side_quad()
00671 {
00672     int idx, dim, err;
00673     err = CN::OppositeSide( MBQUAD, 0, 0, idx, dim );
00674     CHECK_EQUAL( 0, err );
00675     CHECK_EQUAL( 0, dim );
00676     CHECK_EQUAL( 2, idx );
00677     err = CN::OppositeSide( MBQUAD, 1, 0, idx, dim );
00678     CHECK_EQUAL( 0, err );
00679     CHECK_EQUAL( 0, dim );
00680     CHECK_EQUAL( 3, idx );
00681     err = CN::OppositeSide( MBQUAD, 2, 0, idx, dim );
00682     CHECK_EQUAL( 0, err );
00683     CHECK_EQUAL( 0, dim );
00684     CHECK_EQUAL( 0, idx );
00685     err = CN::OppositeSide( MBQUAD, 3, 0, idx, dim );
00686     CHECK_EQUAL( 0, err );
00687     CHECK_EQUAL( 0, dim );
00688     CHECK_EQUAL( 1, idx );
00689 
00690     err = CN::OppositeSide( MBQUAD, 0, 1, idx, dim );
00691     CHECK_EQUAL( 0, err );
00692     CHECK_EQUAL( 1, dim );
00693     CHECK_EQUAL( 2, idx );
00694     err = CN::OppositeSide( MBQUAD, 1, 1, idx, dim );
00695     CHECK_EQUAL( 0, err );
00696     CHECK_EQUAL( 1, dim );
00697     CHECK_EQUAL( 3, idx );
00698     err = CN::OppositeSide( MBQUAD, 2, 1, idx, dim );
00699     CHECK_EQUAL( 0, err );
00700     CHECK_EQUAL( 1, dim );
00701     CHECK_EQUAL( 0, idx );
00702     err = CN::OppositeSide( MBQUAD, 3, 1, idx, dim );
00703     CHECK_EQUAL( 0, err );
00704     CHECK_EQUAL( 1, dim );
00705     CHECK_EQUAL( 1, idx );
00706 }
00707 
00708 void test_opposite_side_tet()
00709 {
00710     int idx, dim, err;
00711 
00712     err = CN::OppositeSide( MBTET, 0, 0, idx, dim );
00713     CHECK_EQUAL( 0, err );
00714     CHECK_EQUAL( 2, dim );
00715     CHECK_EQUAL( 1, idx );
00716     err = CN::OppositeSide( MBTET, 1, 0, idx, dim );
00717     CHECK_EQUAL( 0, err );
00718     CHECK_EQUAL( 2, dim );
00719     CHECK_EQUAL( 2, idx );
00720     err = CN::OppositeSide( MBTET, 2, 0, idx, dim );
00721     CHECK_EQUAL( 0, err );
00722     CHECK_EQUAL( 2, dim );
00723     CHECK_EQUAL( 0, idx );
00724     err = CN::OppositeSide( MBTET, 3, 0, idx, dim );
00725     CHECK_EQUAL( 0, err );
00726     CHECK_EQUAL( 2, dim );
00727     CHECK_EQUAL( 3, idx );
00728 
00729     err = CN::OppositeSide( MBTET, 0, 2, idx, dim );
00730     CHECK_EQUAL( 0, err );
00731     CHECK_EQUAL( 0, dim );
00732     CHECK_EQUAL( 2, idx );
00733     err = CN::OppositeSide( MBTET, 1, 2, idx, dim );
00734     CHECK_EQUAL( 0, err );
00735     CHECK_EQUAL( 0, dim );
00736     CHECK_EQUAL( 0, idx );
00737     err = CN::OppositeSide( MBTET, 2, 2, idx, dim );
00738     CHECK_EQUAL( 0, err );
00739     CHECK_EQUAL( 0, dim );
00740     CHECK_EQUAL( 1, idx );
00741     err = CN::OppositeSide( MBTET, 3, 2, idx, dim );
00742     CHECK_EQUAL( 0, err );
00743     CHECK_EQUAL( 0, dim );
00744     CHECK_EQUAL( 3, idx );
00745 
00746     err = CN::OppositeSide( MBTET, 0, 1, idx, dim );
00747     CHECK_EQUAL( 0, err );
00748     CHECK_EQUAL( 1, dim );
00749     CHECK_EQUAL( 5, idx );
00750     err = CN::OppositeSide( MBTET, 1, 1, idx, dim );
00751     CHECK_EQUAL( 0, err );
00752     CHECK_EQUAL( 1, dim );
00753     CHECK_EQUAL( 3, idx );
00754     err = CN::OppositeSide( MBTET, 2, 1, idx, dim );
00755     CHECK_EQUAL( 0, err );
00756     CHECK_EQUAL( 1, dim );
00757     CHECK_EQUAL( 4, idx );
00758     err = CN::OppositeSide( MBTET, 3, 1, idx, dim );
00759     CHECK_EQUAL( 0, err );
00760     CHECK_EQUAL( 1, dim );
00761     CHECK_EQUAL( 1, idx );
00762     err = CN::OppositeSide( MBTET, 4, 1, idx, dim );
00763     CHECK_EQUAL( 0, err );
00764     CHECK_EQUAL( 1, dim );
00765     CHECK_EQUAL( 2, idx );
00766     err = CN::OppositeSide( MBTET, 5, 1, idx, dim );
00767     CHECK_EQUAL( 0, err );
00768     CHECK_EQUAL( 1, dim );
00769     CHECK_EQUAL( 0, idx );
00770 }
00771 
00772 void test_opposite_side_hex()
00773 {
00774     int idx, dim, err;
00775 
00776     err = CN::OppositeSide( MBHEX, 0, 0, idx, dim );
00777     CHECK_EQUAL( 0, err );
00778     CHECK_EQUAL( 0, dim );
00779     CHECK_EQUAL( 6, idx );
00780     err = CN::OppositeSide( MBHEX, 1, 0, idx, dim );
00781     CHECK_EQUAL( 0, err );
00782     CHECK_EQUAL( 0, dim );
00783     CHECK_EQUAL( 7, idx );
00784     err = CN::OppositeSide( MBHEX, 2, 0, idx, dim );
00785     CHECK_EQUAL( 0, err );
00786     CHECK_EQUAL( 0, dim );
00787     CHECK_EQUAL( 4, idx );
00788     err = CN::OppositeSide( MBHEX, 3, 0, idx, dim );
00789     CHECK_EQUAL( 0, err );
00790     CHECK_EQUAL( 0, dim );
00791     CHECK_EQUAL( 5, idx );
00792     err = CN::OppositeSide( MBHEX, 4, 0, idx, dim );
00793     CHECK_EQUAL( 0, err );
00794     CHECK_EQUAL( 0, dim );
00795     CHECK_EQUAL( 2, idx );
00796     err = CN::OppositeSide( MBHEX, 5, 0, idx, dim );
00797     CHECK_EQUAL( 0, err );
00798     CHECK_EQUAL( 0, dim );
00799     CHECK_EQUAL( 3, idx );
00800     err = CN::OppositeSide( MBHEX, 6, 0, idx, dim );
00801     CHECK_EQUAL( 0, err );
00802     CHECK_EQUAL( 0, dim );
00803     CHECK_EQUAL( 0, idx );
00804     err = CN::OppositeSide( MBHEX, 7, 0, idx, dim );
00805     CHECK_EQUAL( 0, err );
00806     CHECK_EQUAL( 0, dim );
00807     CHECK_EQUAL( 1, idx );
00808 
00809     err = CN::OppositeSide( MBHEX, 0, 1, idx, dim );
00810     CHECK_EQUAL( 0, err );
00811     CHECK_EQUAL( 1, dim );
00812     CHECK_EQUAL( 10, idx );
00813     err = CN::OppositeSide( MBHEX, 1, 1, idx, dim );
00814     CHECK_EQUAL( 0, err );
00815     CHECK_EQUAL( 1, dim );
00816     CHECK_EQUAL( 11, idx );
00817     err = CN::OppositeSide( MBHEX, 2, 1, idx, dim );
00818     CHECK_EQUAL( 0, err );
00819     CHECK_EQUAL( 1, dim );
00820     CHECK_EQUAL( 8, idx );
00821     err = CN::OppositeSide( MBHEX, 3, 1, idx, dim );
00822     CHECK_EQUAL( 0, err );
00823     CHECK_EQUAL( 1, dim );
00824     CHECK_EQUAL( 9, idx );
00825     err = CN::OppositeSide( MBHEX, 4, 1, idx, dim );
00826     CHECK_EQUAL( 0, err );
00827     CHECK_EQUAL( 1, dim );
00828     CHECK_EQUAL( 6, idx );
00829     err = CN::OppositeSide( MBHEX, 5, 1, idx, dim );
00830     CHECK_EQUAL( 0, err );
00831     CHECK_EQUAL( 1, dim );
00832     CHECK_EQUAL( 7, idx );
00833     err = CN::OppositeSide( MBHEX, 6, 1, idx, dim );
00834     CHECK_EQUAL( 0, err );
00835     CHECK_EQUAL( 1, dim );
00836     CHECK_EQUAL( 4, idx );
00837     err = CN::OppositeSide( MBHEX, 7, 1, idx, dim );
00838     CHECK_EQUAL( 0, err );
00839     CHECK_EQUAL( 1, dim );
00840     CHECK_EQUAL( 5, idx );
00841     err = CN::OppositeSide( MBHEX, 8, 1, idx, dim );
00842     CHECK_EQUAL( 0, err );
00843     CHECK_EQUAL( 1, dim );
00844     CHECK_EQUAL( 2, idx );
00845     err = CN::OppositeSide( MBHEX, 9, 1, idx, dim );
00846     CHECK_EQUAL( 0, err );
00847     CHECK_EQUAL( 1, dim );
00848     CHECK_EQUAL( 3, idx );
00849     err = CN::OppositeSide( MBHEX, 10, 1, idx, dim );
00850     CHECK_EQUAL( 0, err );
00851     CHECK_EQUAL( 1, dim );
00852     CHECK_EQUAL( 0, idx );
00853     err = CN::OppositeSide( MBHEX, 11, 1, idx, dim );
00854     CHECK_EQUAL( 0, err );
00855     CHECK_EQUAL( 1, dim );
00856     CHECK_EQUAL( 1, idx );
00857 
00858     err = CN::OppositeSide( MBHEX, 0, 2, idx, dim );
00859     CHECK_EQUAL( 0, err );
00860     CHECK_EQUAL( 2, dim );
00861     CHECK_EQUAL( 2, idx );
00862     err = CN::OppositeSide( MBHEX, 1, 2, idx, dim );
00863     CHECK_EQUAL( 0, err );
00864     CHECK_EQUAL( 2, dim );
00865     CHECK_EQUAL( 3, idx );
00866     err = CN::OppositeSide( MBHEX, 2, 2, idx, dim );
00867     CHECK_EQUAL( 0, err );
00868     CHECK_EQUAL( 2, dim );
00869     CHECK_EQUAL( 0, idx );
00870     err = CN::OppositeSide( MBHEX, 3, 2, idx, dim );
00871     CHECK_EQUAL( 0, err );
00872     CHECK_EQUAL( 2, dim );
00873     CHECK_EQUAL( 1, idx );
00874     err = CN::OppositeSide( MBHEX, 4, 2, idx, dim );
00875     CHECK_EQUAL( 0, err );
00876     CHECK_EQUAL( 2, dim );
00877     CHECK_EQUAL( 5, idx );
00878     err = CN::OppositeSide( MBHEX, 5, 2, idx, dim );
00879     CHECK_EQUAL( 0, err );
00880     CHECK_EQUAL( 2, dim );
00881     CHECK_EQUAL( 4, idx );
00882 }
00883 
00884 void test_has_mid_nodes( EntityType type )
00885 {
00886     const int combinations[][4] = { { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 1, 1, 0 },
00887                                     { 0, 0, 0, 1 }, { 0, 1, 0, 1 }, { 0, 0, 1, 1 }, { 0, 1, 1, 1 } };
00888 
00889     const int dim = CN::Dimension( type );
00890     // calculate number of valid combinations of ho node flags
00891     int num_comb = 1;
00892     for( int i = 0; i < dim; ++i )
00893         num_comb *= 2;
00894     // for each valid combination
00895     for( int c = 0; c < num_comb; ++c )
00896     {
00897         // calculate corresponding number of vertices in element
00898         const int* ho_nodes = combinations[c];
00899         int num_vtx         = CN::VerticesPerEntity( type );
00900         switch( dim )
00901         {
00902             case 3:
00903             case 2:
00904                 // extra clauses to avoid fall-through error
00905                 if( 3 == dim && ho_nodes[2] ) num_vtx += CN::NumSubEntities( type, 2 );
00906                 if( 2 <= dim && ho_nodes[1] ) num_vtx += CN::NumSubEntities( type, 1 );
00907         }
00908         if( ho_nodes[dim] ) ++num_vtx;
00909 
00910         CHECK_EQUAL( ho_nodes[1], (int)CN::HasMidEdgeNodes( type, num_vtx ) );
00911         CHECK_EQUAL( ho_nodes[2], (int)CN::HasMidFaceNodes( type, num_vtx ) );
00912         CHECK_EQUAL( ho_nodes[3], (int)CN::HasMidRegionNodes( type, num_vtx ) );
00913 
00914         int results[4] = { 0, -1, -1, -1 };
00915         CN::HasMidNodes( type, num_vtx, results );
00916         CHECK_EQUAL( 0, !!results[0] );
00917         CHECK_EQUAL( ho_nodes[1], !!results[1] );
00918         CHECK_EQUAL( ho_nodes[2], !!results[2] );
00919         CHECK_EQUAL( ho_nodes[3], !!results[3] );
00920     }
00921 }
00922 
00923 void test_ho_node_parent()
00924 {
00925     const int combinations[][4] = { { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 1, 1, 0 },
00926                                     { 0, 0, 0, 1 }, { 0, 1, 0, 1 }, { 0, 0, 1, 1 }, { 0, 1, 1, 1 } };
00927 
00928     for( const EntityType* t = elem_types; *t != MBMAXTYPE; ++t )
00929     {
00930         const EntityType type = *t;
00931         const int dim         = CN::Dimension( type );
00932         // calculate number of valid combinations of ho node flags
00933         int num_comb = 1;
00934         for( int i = 0; i < dim; ++i )
00935             num_comb *= 2;
00936         // for each valid combination
00937         for( int c = 0; c < num_comb; ++c )
00938         {
00939             // calculate corresponding number of vertices in element
00940             const int* ho_nodes = combinations[c];
00941             int num_vtx         = CN::VerticesPerEntity( type );
00942             switch( dim )
00943             {
00944                 case 3:
00945                 case 2:
00946                     // extra clauses to avoid fall-through error
00947                     if( 3 == dim && ho_nodes[2] ) num_vtx += CN::NumSubEntities( type, 2 );
00948                     if( 2 <= dim && ho_nodes[1] ) num_vtx += CN::NumSubEntities( type, 1 );
00949             }
00950             if( ho_nodes[dim] ) ++num_vtx;
00951 
00952             // start at first higher-order node
00953             int pos = CN::VerticesPerEntity( type );
00954 
00955             // check mid-edge
00956             if( dim > 1 && ho_nodes[1] )
00957             {
00958                 for( int i = 0; i < CN::NumSubEntities( type, 1 ); ++i )
00959                 {
00960                     int pdim = -1, pidx = -1;
00961                     CN::HONodeParent( type, num_vtx, pos++, pdim, pidx );
00962                     CHECK_EQUAL( 1, pdim );
00963                     CHECK_EQUAL( i, pidx );
00964                 }
00965             }
00966 
00967             // check mid-face
00968             if( dim > 2 && ho_nodes[2] )
00969             {
00970                 for( int i = 0; i < CN::NumSubEntities( type, 2 ); ++i )
00971                 {
00972                     int pdim = -1, pidx = -1;
00973                     CN::HONodeParent( type, num_vtx, pos++, pdim, pidx );
00974                     CHECK_EQUAL( 2, pdim );
00975                     CHECK_EQUAL( i, pidx );
00976                 }
00977             }
00978 
00979             // check mid-volume
00980             if( ho_nodes[dim] )
00981             {
00982                 int pdim = -1, pidx = -1;
00983                 CN::HONodeParent( type, num_vtx, pos++, pdim, pidx );
00984                 CHECK_EQUAL( dim, pdim );
00985                 CHECK_EQUAL( 0, pidx );
00986             }
00987         }  // for ho_node combinatinos
00988     }      // for each type
00989 }
00990 
00991 void test_ho_node_index()
00992 {
00993     const int combinations[][4] = { { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 1, 1, 0 },
00994                                     { 0, 0, 0, 1 }, { 0, 1, 0, 1 }, { 0, 0, 1, 1 }, { 0, 1, 1, 1 } };
00995 
00996     for( const EntityType* t = elem_types; *t != MBMAXTYPE; ++t )
00997     {
00998         const EntityType type = *t;
00999         const int dim         = CN::Dimension( type );
01000         // calculate number of valid combinations of ho node flags
01001         int num_comb = 1;
01002         for( int i = 0; i < dim; ++i )
01003             num_comb *= 2;
01004         // for each valid combination
01005         for( int c = 0; c < num_comb; ++c )
01006         {
01007             // calculate corresponding number of vertices in element
01008             const int* ho_nodes = combinations[c];
01009             int num_vtx         = CN::VerticesPerEntity( type );
01010             switch( dim )
01011             {
01012                 case 3:
01013                 case 2:
01014                     // extra clauses to avoid fall-through error
01015                     if( 3 == dim && ho_nodes[2] ) num_vtx += CN::NumSubEntities( type, 2 );
01016                     if( 2 <= dim && ho_nodes[1] ) num_vtx += CN::NumSubEntities( type, 1 );
01017             }
01018             if( ho_nodes[dim] ) ++num_vtx;
01019 
01020             // start at first higher-order node
01021             int pos = CN::VerticesPerEntity( type );
01022 
01023             // check mid-edge
01024             if( dim > 1 && ho_nodes[1] )
01025             {
01026                 for( int i = 0; i < CN::NumSubEntities( type, 1 ); ++i )
01027                 {
01028                     int idx = CN::HONodeIndex( type, num_vtx, 1, i );
01029                     CHECK_EQUAL( pos++, idx );
01030                 }
01031             }
01032 
01033             // check mid-face
01034             if( dim > 2 && ho_nodes[2] )
01035             {
01036                 for( int i = 0; i < CN::NumSubEntities( type, 2 ); ++i )
01037                 {
01038                     int idx = CN::HONodeIndex( type, num_vtx, 2, i );
01039                     CHECK_EQUAL( pos++, idx );
01040                 }
01041             }
01042 
01043             // check mid-volume
01044             if( ho_nodes[dim] )
01045             {
01046                 int idx = CN::HONodeIndex( type, num_vtx, dim, 0 );
01047                 CHECK_EQUAL( pos++, idx );
01048             }
01049         }  // for ho_node combinatinos
01050     }      // for each type
01051 }
01052 
01053 void test_sub_entity_nodes( EntityType parent, int sub_dimension )
01054 {
01055     const int num_corner = CN::VerticesPerEntity( parent );
01056     const int num_edge   = CN::NumSubEntities( parent, 1 );
01057     const int num_face   = CN::NumSubEntities( parent, 2 );
01058 
01059     auto dim = CN::Dimension( parent );
01060     switch( dim )
01061     {
01062         case 3:
01063         case 2:
01064         case 1:
01065             test_sub_entity_nodes( parent, num_corner + num_face, sub_dimension );
01066             test_sub_entity_nodes( parent, num_corner + num_edge + num_face, sub_dimension );
01067             test_sub_entity_nodes( parent, num_corner + num_face + 1, sub_dimension );
01068             test_sub_entity_nodes( parent, num_corner + num_edge + num_face + 1, sub_dimension );
01069             if( 2 <= dim )
01070             {
01071                 test_sub_entity_nodes( parent, num_corner + num_edge, sub_dimension );
01072                 test_sub_entity_nodes( parent, num_corner + num_edge + 1, sub_dimension );
01073             }
01074             if( 1 <= dim )
01075             {
01076                 test_sub_entity_nodes( parent, num_corner, sub_dimension );
01077                 test_sub_entity_nodes( parent, num_corner + 1, sub_dimension );
01078             }
01079             break;
01080         default:
01081             CHECK( false );
01082     }
01083 }
01084 
01085 void test_sub_entity_nodes( EntityType parent, int num_nodes, int sub_dimension )
01086 {
01087     const int num_sub   = CN::NumSubEntities( parent, sub_dimension );
01088     const int parent_ho = CN::HasMidNodes( parent, num_nodes );
01089     int child_ho        = 0;
01090     for( int d = 1; d <= sub_dimension; ++d )
01091         child_ho |= ( parent_ho & ( 1 << d ) );
01092 
01093     // first test the types
01094     for( int i = 0; i < num_sub; ++i )
01095     {
01096         int num, conn[moab::MAX_SUB_ENTITY_VERTICES];
01097         EntityType type;
01098         CN::SubEntityNodeIndices( parent, num_nodes, sub_dimension, i, type, num, conn );
01099         CHECK_EQUAL( CN::SubEntityType( parent, sub_dimension, i ), type );
01100     }
01101 
01102     // now test that they have the correct number of higher-order node
01103     for( int i = 0; i < num_sub; ++i )
01104     {
01105         int num, conn[moab::MAX_SUB_ENTITY_VERTICES];
01106         EntityType type;
01107         CN::SubEntityNodeIndices( parent, num_nodes, sub_dimension, i, type, num, conn );
01108         const int ho = CN::HasMidNodes( type, num );
01109         CHECK_EQUAL( child_ho, ho );
01110     }
01111 
01112     // now test the actual indices
01113     for( int i = 0; i < num_sub; ++i )
01114     {
01115         int num, conn[moab::MAX_SUB_ENTITY_VERTICES], corners[moab::MAX_SUB_ENTITY_VERTICES];
01116         EntityType type;
01117         CN::SubEntityNodeIndices( parent, num_nodes, sub_dimension, i, type, num, conn );
01118 
01119         // check corner indices against SubEntityVertexIndices
01120         const int num_corner = CN::VerticesPerEntity( type );
01121         CHECK( num >= num_corner );
01122         CN::SubEntityVertexIndices( parent, sub_dimension, i, corners );
01123         for( int j = 0; j < num_corner; ++j )
01124             CHECK_EQUAL( corners[j], conn[j] );
01125 
01126         // check mid-edge indices, if present
01127         int idx = num_corner;
01128         if( child_ho & CN::MID_EDGE_BIT )
01129         {
01130             // for each edge in the sub-entity type
01131             const int num_edge = CN::NumSubEntities( type, 1 );
01132             for( int j = 0; j < num_edge; ++j )
01133             {
01134                 // get edge indices for sub-entity connectivity
01135                 int edge_ends[2];
01136                 CN::SubEntityVertexIndices( type, 1, j, edge_ends );
01137                 // convert to indices into parent type's connectivity
01138                 CHECK( edge_ends[0] < num_corner );
01139                 edge_ends[0] = corners[edge_ends[0]];
01140                 CHECK( edge_ends[1] < num_corner );
01141                 edge_ends[1] = corners[edge_ends[1]];
01142                 // find edge index in parent element
01143                 int side, sense, off;
01144                 int result = CN::SideNumber( parent, edge_ends, 2, 1, side, sense, off );
01145                 CHECK_EQUAL( 0, result );
01146                 // get location in parent entity connectivity for mid-edge node
01147                 int loc = CN::HONodeIndex( parent, num_nodes, 1, side );
01148                 CHECK_EQUAL( loc, conn[idx++] );
01149             }
01150         }
01151 
01152         // check mid-face indices, if present
01153         if( child_ho & CN::MID_FACE_BIT )
01154         {
01155             CHECK_EQUAL( 2, CN::Dimension( type ) );
01156             int loc = CN::HONodeIndex( parent, num_nodes, 2, i );
01157             CHECK_EQUAL( loc, conn[idx++] );
01158         }
01159 
01160         // make sure there were no extra node indices returned
01161         CHECK_EQUAL( idx, num );
01162     }
01163 }
01164 
01165 #include "moab/Core.hpp"
01166 void prism_issue()
01167 {
01168     moab::Core mb;
01169 
01170     std::vector< moab::EntityHandle > conn;
01171     double coords[3];
01172     for( int i = 0; i < 15; ++i )
01173     {
01174         moab::EntityHandle h;
01175         mb.create_vertex( coords, h );
01176         conn.push_back( h );
01177     }
01178 
01179     moab::EntityHandle w;
01180     mb.create_element( moab::MBPRISM, conn.data(), 15, w );
01181 
01182     // this leads to the failure
01183     {
01184         std::vector< moab::EntityHandle > adj;
01185         mb.get_adjacencies( &w, 1, 2, true, adj );
01186     }
01187     std::vector< moab::EntityHandle > edges;
01188     std::vector< moab::EntityHandle > faces;
01189     mb.get_entities_by_dimension( 0, 1, edges );
01190     for( const auto& e : edges )
01191     {
01192         std::vector< moab::EntityHandle > conn;
01193         std::cout << "edge " << e << " connectivity: ";
01194 
01195         mb.get_connectivity( &e, 1, conn );
01196         for( const auto& n : conn )
01197             std::cout << n << " ";
01198         std::cout << "\n";
01199     }
01200     mb.get_entities_by_dimension( 0, 2, faces );
01201     for( const auto& f : faces )
01202     {
01203         std::vector< moab::EntityHandle > conn;
01204         std::cout << "face " << f << " connectivity: ";
01205 
01206         mb.get_connectivity( &f, 1, conn );
01207         for( const auto& n : conn )
01208             std::cout << n << " ";
01209         std::cout << "\n";
01210     }
01211     std::vector< moab::EntityHandle > nodes;
01212     mb.get_entities_by_dimension( 0, 0, nodes );
01213     for( const auto& n : nodes )
01214     {
01215         std::vector< moab::EntityHandle > adj;
01216         std::cout << "node " << n << " connection: ";
01217         adj.clear();
01218         mb.get_adjacencies( &n, 1, 1, true, adj );
01219         std::cout << adj.size() << " edges,";
01220         // there are either 1 or 3 adjacent edges to each vertex (1 for mid edge vertex)
01221         CHECK( 1 == adj.size() || 3 == adj.size() );
01222         adj.clear();
01223         mb.get_adjacencies( &n, 1, 2, true, adj );
01224         std::cout << adj.size() << " faces,";
01225         // there are either 2 or 3 adjacent faces to each vertex ( 2 for mid edge evertex)
01226         CHECK( 2 == adj.size() || 3 == adj.size() );
01227         adj.clear();
01228         mb.get_adjacencies( &n, 1, 3, true, adj );
01229         std::cout << adj.size() << " volumes\n";
01230     }
01231 }
01232 
01233 void test_wedges()
01234 {
01235     moab::Core mb;
01236 
01237     //mb.load_file("./wed15_2.h5m");
01238     std::vector< moab::EntityHandle > conn;
01239     double coords[3];
01240     for( int i = 0; i < 22; ++i )
01241     {
01242         moab::EntityHandle h;
01243         mb.create_vertex( coords, h );
01244     }
01245     moab::EntityHandle conn1[15] = { 10, 20, 14, 1, 8, 5, 21, 19, 15, 16, 22, 18, 9, 7, 6 };
01246     moab::EntityHandle conn2[15] = { 10, 14, 12, 1, 5, 3, 15, 13, 11, 16, 18, 17, 6, 4, 2 };
01247 
01248     moab::EntityHandle w;
01249     mb.create_element( moab::MBPRISM, conn1, 15, w );
01250     mb.create_element( moab::MBPRISM, conn2, 15, w );
01251 
01252     std::vector< moab::EntityHandle > wedges;
01253     mb.get_entities_by_dimension( 0, 3, wedges );
01254 
01255     // > If I comment this block there is no problem
01256     for( const auto& w : wedges )
01257     {
01258         std::vector< moab::EntityHandle > adj;
01259         mb.get_adjacencies( &w, 1, 2, true, adj );
01260         CHECK( 5 == adj.size() );
01261     }
01262     // <
01263 
01264     for( const auto& w : wedges )
01265     {
01266         std::vector< moab::EntityHandle > conn;
01267         mb.get_connectivity( &w, 1, conn );
01268         CHECK( 15 == conn.size() );
01269         for( const auto& n : conn )
01270         {
01271             std::vector< moab::EntityHandle > edges;
01272             mb.get_adjacencies( &n, 1, 1, true, edges );
01273             if( edges.size() == 0 )
01274             {
01275                 std::cout << " node " << n << " not connected to edges \n";
01276                 std::vector< moab::EntityHandle > faces;
01277                 mb.get_adjacencies( &n, 1, 2, false, faces );
01278                 for( const auto& f : faces )
01279                 {
01280                     std::vector< moab::EntityHandle > connf;
01281                     mb.get_connectivity( &f, 1, connf );
01282                     std::cout << "face:" << mb.id_from_handle( f );
01283                     for( const auto& n1 : connf )
01284                         std::cout << " " << n1;
01285                     std::cout << "\n";
01286                 }
01287                 std::vector< moab::EntityHandle > prisms;
01288                 mb.get_adjacencies( &n, 1, 3, false, prisms );
01289                 for( const auto& p : prisms )
01290                 {
01291                     std::vector< moab::EntityHandle > connf;
01292                     mb.get_connectivity( &p, 1, connf );
01293                     std::cout << "prism:" << mb.id_from_handle( p );
01294                     for( const auto& n1 : connf )
01295                         std::cout << " " << n1;
01296                     std::cout << "\n";
01297                 }
01298                 CHECK( edges.size() != 0 );
01299             }
01300         }
01301     }
01302 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines