MOAB: Mesh Oriented datABase  (version 5.2.1)
CN.cpp
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain 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  */
00015 
00016 #include "moab/CN.hpp"
00017 #include "MBCNArrays.hpp"
00018 #include "MBCN.h"
00019 #include <assert.h>
00020 #include <string.h>
00021 #include <iterator>
00022 
00023 namespace moab
00024 {
00025 
00026 const char* CN::entityTypeNames[] = { "Vertex", "Edge",  "Tri", "Quad",       "Polygon",   "Tet",    "Pyramid",
00027                                       "Prism",  "Knife", "Hex", "Polyhedron", "EntitySet", "MaxType" };
00028 
00029 short int CN::numberBasis = 0;
00030 
00031 short int CN::permuteVec[MBMAXTYPE][3][MAX_SUB_ENTITIES + 1];
00032 short int CN::revPermuteVec[MBMAXTYPE][3][MAX_SUB_ENTITIES + 1];
00033 
00034 const DimensionPair CN::TypeDimensionMap[] = {
00035     DimensionPair( MBVERTEX, MBVERTEX ),       DimensionPair( MBEDGE, MBEDGE ),
00036     DimensionPair( MBTRI, MBPOLYGON ),         DimensionPair( MBTET, MBPOLYHEDRON ),
00037     DimensionPair( MBENTITYSET, MBENTITYSET ), DimensionPair( MBMAXTYPE, MBMAXTYPE )
00038 };
00039 
00040 short CN::increasingInts[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
00041                                20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 };
00042 
00043 //! set the basis of the numbering system; may or may not do things besides setting the
00044 //! member variable
00045 void CN::SetBasis( const int in_basis )
00046 {
00047     numberBasis = in_basis;
00048 }
00049 
00050 /// Get the dimension pair corresponding to a dimension
00051 DimensionPair CN::getDimPair( int entity_type )
00052 {
00053     return TypeDimensionMap[entity_type];
00054 }
00055 
00056 //! return a type for the given name
00057 EntityType CN::EntityTypeFromName( const char* name )
00058 {
00059     for( EntityType i = MBVERTEX; i < MBMAXTYPE; i++ )
00060     {
00061         if( 0 == strcmp( name, entityTypeNames[i] ) ) return i;
00062     }
00063 
00064     return MBMAXTYPE;
00065 }
00066 
00067 void CN::SubEntityNodeIndices( const EntityType this_topo, const int num_nodes, const int sub_dimension,
00068                                const int sub_index, EntityType& subentity_topo, int& num_sub_entity_nodes,
00069                                int sub_entity_conn[] )
00070 {
00071     // If asked for a node, the special case...
00072     if( sub_dimension == 0 )
00073     {
00074         assert( sub_index < num_nodes );
00075         subentity_topo       = MBVERTEX;
00076         num_sub_entity_nodes = 1;
00077         sub_entity_conn[0]   = sub_index;
00078         return;
00079     }
00080 
00081     const int ho_bits    = HasMidNodes( this_topo, num_nodes );
00082     subentity_topo       = SubEntityType( this_topo, sub_dimension, sub_index );
00083     num_sub_entity_nodes = VerticesPerEntity( subentity_topo );
00084     const short* corners = mConnectivityMap[this_topo][sub_dimension - 1].conn[sub_index];
00085     std::copy( corners, corners + num_sub_entity_nodes, sub_entity_conn );
00086 
00087     int sub_sub_corners[MAX_SUB_ENTITY_VERTICES];
00088     int side, sense, offset;
00089     for( int dim = 1; dim <= sub_dimension; ++dim )
00090     {
00091         if( !( ho_bits & ( 1 << dim ) ) ) continue;
00092 
00093         const short num_mid = NumSubEntities( subentity_topo, dim );
00094         for( int i = 0; i < num_mid; ++i )
00095         {
00096             const EntityType sub_sub_topo = SubEntityType( subentity_topo, dim, i );
00097             const int sub_sub_num_vert    = VerticesPerEntity( sub_sub_topo );
00098             SubEntityVertexIndices( subentity_topo, dim, i, sub_sub_corners );
00099 
00100             for( int j = 0; j < sub_sub_num_vert; ++j )
00101                 sub_sub_corners[j] = corners[sub_sub_corners[j]];
00102             SideNumber( this_topo, sub_sub_corners, sub_sub_num_vert, dim, side, sense, offset );
00103             sub_entity_conn[num_sub_entity_nodes++] = HONodeIndex( this_topo, num_nodes, dim, side );
00104         }
00105     }
00106 }
00107 
00108 //! return the vertices of the specified sub entity
00109 //! \param parent_conn Connectivity of parent entity
00110 //! \param parent_type Entity type of parent entity
00111 //! \param sub_dimension Dimension of sub-entity being queried
00112 //! \param sub_index Index of sub-entity being queried
00113 //! \param sub_entity_conn Connectivity of sub-entity, based on parent_conn and canonical
00114 //!           ordering for parent_type
00115 //! \param num_sub_vertices Number of vertices in sub-entity
00116 void CN::SubEntityConn( const void* parent_conn, const EntityType parent_type, const int sub_dimension,
00117                         const int sub_index, void* sub_entity_conn, int& num_sub_vertices )
00118 {
00119     static int sub_indices[MAX_SUB_ENTITY_VERTICES];
00120 
00121     SubEntityVertexIndices( parent_type, sub_dimension, sub_index, sub_indices );
00122 
00123     num_sub_vertices       = VerticesPerEntity( SubEntityType( parent_type, sub_dimension, sub_index ) );
00124     void** parent_conn_ptr = static_cast< void** >( const_cast< void* >( parent_conn ) );
00125     void** sub_conn_ptr    = static_cast< void** >( sub_entity_conn );
00126     for( int i = 0; i < num_sub_vertices; i++ )
00127         sub_conn_ptr[i] = parent_conn_ptr[sub_indices[i]];
00128 }
00129 
00130 //! given an entity and a target dimension & side number, get that entity
00131 short int CN::AdjacentSubEntities( const EntityType this_type, const int* source_indices, const int num_source_indices,
00132                                    const int source_dim, const int target_dim, std::vector< int >& index_list,
00133                                    const int operation_type )
00134 {
00135     // first get all the vertex indices
00136     std::vector< int > tmp_indices;
00137     const int* it1 = source_indices;
00138 
00139     assert( source_dim <= 3 && target_dim >= 0 && target_dim <= 3 &&
00140             // make sure we're not stepping off the end of the array;
00141             ( ( source_dim > 0 && *it1 < mConnectivityMap[this_type][source_dim - 1].num_sub_elements ) ||
00142               ( source_dim == 0 &&
00143                 *it1 < mConnectivityMap[this_type][Dimension( this_type ) - 1].num_corners_per_sub_element[0] ) ) &&
00144             *it1 >= 0 );
00145 
00146 #define MUC CN::mUpConnMap[this_type][source_dim][target_dim]
00147 
00148     // if we're looking for the vertices of a single side, return them in
00149     // the canonical ordering; otherwise, return them in sorted order
00150     if( num_source_indices == 1 && 0 == target_dim && source_dim != target_dim )
00151     {
00152 
00153         // element of mConnectivityMap should be for this type and for one
00154         // less than source_dim, which should give the connectivity of that sub element
00155         const ConnMap& cm = mConnectivityMap[this_type][source_dim - 1];
00156         std::copy( cm.conn[source_indices[0]],
00157                    cm.conn[source_indices[0]] + cm.num_corners_per_sub_element[source_indices[0]],
00158                    std::back_inserter( index_list ) );
00159         return 0;
00160     }
00161 
00162     // now go through source indices, folding adjacencies into target list
00163     for( it1 = source_indices; it1 != source_indices + num_source_indices; it1++ )
00164     {
00165         // *it1 is the side index
00166         // at start of iteration, index_list has the target list
00167 
00168         // if a union, or first iteration and index list was empty, copy the list
00169         if( operation_type == CN::UNION || ( it1 == source_indices && index_list.empty() ) )
00170         {
00171             std::copy( MUC.targets_per_source_element[*it1],
00172                        MUC.targets_per_source_element[*it1] + MUC.num_targets_per_source_element[*it1],
00173                        std::back_inserter( index_list ) );
00174         }
00175         else
00176         {
00177             // else we're intersecting, and have a non-empty list; intersect with this target list
00178             tmp_indices.clear();
00179             for( int i = MUC.num_targets_per_source_element[*it1] - 1; i >= 0; i-- )
00180                 if( std::find( index_list.begin(), index_list.end(), MUC.targets_per_source_element[*it1][i] ) !=
00181                     index_list.end() )
00182                     tmp_indices.push_back( MUC.targets_per_source_element[*it1][i] );
00183             //      std::set_intersection(MUC.targets_per_source_element[*it1],
00184             //                            MUC.targets_per_source_element[*it1]+
00185             //                            MUC.num_targets_per_source_element[*it1],
00186             //                            index_list.begin(), index_list.end(),
00187             //                            std::back_inserter(tmp_indices));
00188             index_list.swap( tmp_indices );
00189 
00190             // if we're at this point and the list is empty, the intersection will be NULL;
00191             // return if so
00192             if( index_list.empty() ) return 0;
00193         }
00194     }
00195 
00196     if( operation_type == CN::UNION && num_source_indices != 1 )
00197     {
00198         // need to sort then unique the list
00199         std::sort( index_list.begin(), index_list.end() );
00200         index_list.erase( std::unique( index_list.begin(), index_list.end() ), index_list.end() );
00201     }
00202 
00203     return 0;
00204 }
00205 
00206 template < typename T >
00207 static short int side_number( const T* parent_conn, const EntityType parent_type, const T* child_conn,
00208                               const int child_num_verts, const int child_dim, int& side_no, int& sense, int& offset )
00209 {
00210     int parent_num_verts = CN::VerticesPerEntity( parent_type );
00211     int side_indices[8];
00212     assert( sizeof( side_indices ) / sizeof( side_indices[0] ) >= (size_t)child_num_verts );
00213 
00214     for( int i = 0; i < child_num_verts; i++ )
00215     {
00216         side_indices[i] = std::find( parent_conn, parent_conn + parent_num_verts, child_conn[i] ) - parent_conn;
00217         if( side_indices[i] == parent_num_verts ) return -1;
00218     }
00219 
00220     return CN::SideNumber( parent_type, &side_indices[0], child_num_verts, child_dim, side_no, sense, offset );
00221 }
00222 
00223 short int CN::SideNumber( const EntityType parent_type, const int* parent_conn, const int* child_conn,
00224                           const int child_num_verts, const int child_dim, int& side_no, int& sense, int& offset )
00225 {
00226     return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset );
00227 }
00228 
00229 short int CN::SideNumber( const EntityType parent_type, const unsigned int* parent_conn, const unsigned int* child_conn,
00230                           const int child_num_verts, const int child_dim, int& side_no, int& sense, int& offset )
00231 {
00232     return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset );
00233 }
00234 short int CN::SideNumber( const EntityType parent_type, const long* parent_conn, const long* child_conn,
00235                           const int child_num_verts, const int child_dim, int& side_no, int& sense, int& offset )
00236 {
00237     return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset );
00238 }
00239 short int CN::SideNumber( const EntityType parent_type, const unsigned long* parent_conn,
00240                           const unsigned long* child_conn, const int child_num_verts, const int child_dim, int& side_no,
00241                           int& sense, int& offset )
00242 {
00243     return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset );
00244 }
00245 
00246 short int CN::SideNumber( const EntityType parent_type, const unsigned long long* parent_conn,
00247                           const unsigned long long* child_conn, const int child_num_verts, const int child_dim,
00248                           int& side_no, int& sense, int& offset )
00249 
00250 {
00251     return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset );
00252 }
00253 
00254 short int CN::SideNumber( const EntityType parent_type, void* const* parent_conn, void* const* child_conn,
00255                           const int child_num_verts, const int child_dim, int& side_no, int& sense, int& offset )
00256 {
00257     return side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, side_no, sense, offset );
00258 }
00259 
00260 short int CN::SideNumber( const EntityType parent_type, const int* child_conn_indices, const int child_num_verts,
00261                           const int child_dim, int& side_no, int& sense, int& offset )
00262 {
00263     int parent_dim       = Dimension( parent_type );
00264     int parent_num_verts = VerticesPerEntity( parent_type );
00265 
00266     // degenerate case (vertex), output == input
00267     if( child_dim == 0 )
00268     {
00269         if( child_num_verts != 1 ) return -1;
00270         side_no = *child_conn_indices;
00271         sense = offset = 0;
00272     }
00273 
00274     // given a parent and child element, find the corresponding side number
00275 
00276     // dim_diff should be -1, 0 or 1 (same dimension, one less dimension, two less, resp.)
00277     if( child_dim > parent_dim || child_dim < 0 ) return -1;
00278 
00279     // different types of same dimension won't be the same
00280     if( parent_dim == child_dim && parent_num_verts != child_num_verts )
00281     {
00282         side_no = -1;
00283         sense   = 0;
00284         return 0;
00285     }
00286 
00287     // loop over the sub-elements, comparing to child connectivity
00288     int sub_conn_indices[10];
00289     for( int i = 0; i < NumSubEntities( parent_type, child_dim ); i++ )
00290     {
00291         int sub_size = VerticesPerEntity( SubEntityType( parent_type, child_dim, i ) );
00292         if( sub_size != child_num_verts ) continue;
00293 
00294         SubEntityVertexIndices( parent_type, child_dim, i, sub_conn_indices );
00295         bool they_match = ConnectivityMatch( child_conn_indices, sub_conn_indices, sub_size, sense, offset );
00296         if( they_match )
00297         {
00298             side_no = i;
00299             return 0;
00300         }
00301     }
00302 
00303     // if we've gotten here, we don't match
00304     side_no = -1;
00305 
00306     // return value is no success
00307     return 1;
00308 }
00309 
00310 //! return the dimension and index of the opposite side, given parent entity type and child
00311 //! dimension and index.  This function is only defined for certain types of parent/child types:
00312 //! (Parent, Child dim->Opposite dim):
00313 //!  (Tri, 1->0), (Tri, 0->1), (Quad, 1->1), (Quad, 0->0),
00314 //!  (Tet, 2->0), (Tet, 1->1), (Tet, 0->2),
00315 //!  (Hex, 2->2), (Hex, 1->1)(diagonally across element), (Hex, 0->0) (diagonally across element)
00316 //! All other parent types and child dimensions return an error.
00317 //!
00318 //! \param parent_type The type of parent element
00319 //! \param child_type The type of child element
00320 //! \param child_index The index of the child element
00321 //! \param opposite_index The index of the opposite element
00322 //! \return status Returns 0 if successful, -1 if not
00323 short int CN::OppositeSide( const EntityType parent_type, const int child_index, const int child_dim,
00324                             int& opposite_index, int& opposite_dim )
00325 {
00326     switch( parent_type )
00327     {
00328         case MBEDGE:
00329             if( 0 != child_dim )
00330                 return -1;
00331             else
00332                 opposite_index = 1 - child_index;
00333             opposite_dim = 0;
00334             break;
00335 
00336         case MBTRI:
00337             switch( child_dim )
00338             {
00339                 case 0:
00340                     opposite_dim   = 1;
00341                     opposite_index = ( child_index + 1 ) % 3;
00342                     break;
00343                 case 1:
00344                     opposite_dim   = 0;
00345                     opposite_index = ( child_index + 2 ) % 3;
00346                     break;
00347                 default:
00348                     return -1;
00349             }
00350             break;
00351 
00352         case MBQUAD:
00353             switch( child_dim )
00354             {
00355                 case 0:
00356                 case 1:
00357                     opposite_dim   = child_dim;
00358                     opposite_index = ( child_index + 2 ) % 4;
00359                     break;
00360                 default:
00361                     return -1;
00362             }
00363             break;
00364 
00365         case MBTET:
00366             switch( child_dim )
00367             {
00368                 case 0:
00369                     opposite_dim   = 2;
00370                     opposite_index = ( child_index + 1 ) % 3 + 2 * ( child_index / 3 );
00371                     break;
00372                 case 1:
00373                     opposite_dim   = 1;
00374                     opposite_index = child_index < 3 ? 3 + ( child_index + 2 ) % 3 : ( child_index + 1 ) % 3;
00375                     break;
00376                 case 2:
00377                     opposite_dim   = 0;
00378                     opposite_index = ( child_index + 2 ) % 3 + child_index / 3;
00379                     break;
00380                 default:
00381                     return -1;
00382             }
00383             break;
00384         case MBHEX:
00385             opposite_dim = child_dim;
00386             switch( child_dim )
00387             {
00388                 case 0:
00389                     opposite_index = child_index < 4 ? 4 + ( child_index + 2 ) % 4 : ( child_index - 2 ) % 4;
00390                     break;
00391                 case 1:
00392                     opposite_index = 4 * ( 2 - child_index / 4 ) + ( child_index + 2 ) % 4;
00393                     break;
00394                 case 2:
00395                     opposite_index = child_index < 4 ? ( child_index + 2 ) % 4 : 9 - child_index;
00396                     break;
00397                 default:
00398                     return -1;
00399             }
00400             break;
00401 
00402         default:
00403             return -1;
00404     }
00405 
00406     return 0;
00407 }
00408 
00409 template < typename T >
00410 inline bool connectivity_match( const T* conn1_i, const T* conn2_i, const int num_vertices, int& direct, int& offset )
00411 {
00412 
00413     bool they_match;
00414 
00415     // special test for 2 handles, since we don't want to wrap the list in this
00416     // case
00417     if( num_vertices == 2 )
00418     {
00419         they_match = false;
00420         if( conn1_i[0] == conn2_i[0] && conn1_i[1] == conn2_i[1] )
00421         {
00422             direct     = 1;
00423             they_match = true;
00424             offset     = 0;
00425         }
00426         else if( conn1_i[0] == conn2_i[1] && conn1_i[1] == conn2_i[0] )
00427         {
00428             they_match = true;
00429             direct     = -1;
00430             offset     = 1;
00431         }
00432     }
00433 
00434     else
00435     {
00436         const T* iter;
00437         iter = std::find( &conn2_i[0], &conn2_i[num_vertices], conn1_i[0] );
00438         if( iter == &conn2_i[num_vertices] ) return false;
00439 
00440         they_match = true;
00441 
00442         offset = iter - conn2_i;
00443         int i;
00444 
00445         // first compare forward
00446         for( i = 1; i < num_vertices; ++i )
00447         {
00448             if( conn1_i[i] != conn2_i[( offset + i ) % num_vertices] )
00449             {
00450                 they_match = false;
00451                 break;
00452             }
00453         }
00454 
00455         if( they_match == true )
00456         {
00457             direct = 1;
00458             return they_match;
00459         }
00460 
00461         they_match = true;
00462 
00463         // then compare reverse
00464         for( i = 1; i < num_vertices; i++ )
00465         {
00466             if( conn1_i[i] != conn2_i[( offset + num_vertices - i ) % num_vertices] )
00467             {
00468                 they_match = false;
00469                 break;
00470             }
00471         }
00472         if( they_match ) { direct = -1; }
00473     }
00474 
00475     return they_match;
00476 }
00477 
00478 bool CN::ConnectivityMatch( const int* conn1_i, const int* conn2_i, const int num_vertices, int& direct, int& offset )
00479 {
00480     return connectivity_match< int >( conn1_i, conn2_i, num_vertices, direct, offset );
00481 }
00482 
00483 bool CN::ConnectivityMatch( const unsigned int* conn1_i, const unsigned int* conn2_i, const int num_vertices,
00484                             int& direct, int& offset )
00485 {
00486     return connectivity_match< unsigned int >( conn1_i, conn2_i, num_vertices, direct, offset );
00487 }
00488 
00489 bool CN::ConnectivityMatch( const long* conn1_i, const long* conn2_i, const int num_vertices, int& direct, int& offset )
00490 {
00491     return connectivity_match< long >( conn1_i, conn2_i, num_vertices, direct, offset );
00492 }
00493 
00494 bool CN::ConnectivityMatch( const unsigned long* conn1_i, const unsigned long* conn2_i, const int num_vertices,
00495                             int& direct, int& offset )
00496 {
00497     return connectivity_match< unsigned long >( conn1_i, conn2_i, num_vertices, direct, offset );
00498 }
00499 
00500 bool CN::ConnectivityMatch( const unsigned long long* conn1_i, const unsigned long long* conn2_i,
00501                             const int num_vertices, int& direct, int& offset )
00502 {
00503     return connectivity_match< unsigned long long >( conn1_i, conn2_i, num_vertices, direct, offset );
00504 }
00505 
00506 bool CN::ConnectivityMatch( void* const* conn1_i, void* const* conn2_i, const int num_vertices, int& direct,
00507                             int& offset )
00508 {
00509     return connectivity_match< void* >( conn1_i, conn2_i, num_vertices, direct, offset );
00510 }
00511 
00512 //! for an entity of this type and a specified subfacet (dimension and index), return
00513 //! the index of the higher order node for that entity in this entity's connectivity array
00514 short int CN::HONodeIndex( const EntityType this_type, const int num_verts, const int subfacet_dim,
00515                            const int subfacet_index )
00516 {
00517     int i;
00518     int has_mids[4];
00519     HasMidNodes( this_type, num_verts, has_mids );
00520 
00521     // if we have no mid nodes on the subfacet_dim, we have no index
00522     if( subfacet_index != -1 && !has_mids[subfacet_dim] ) return -1;
00523 
00524     // put start index at last index (one less than the number of vertices
00525     // plus the index basis)
00526     int index = VerticesPerEntity( this_type ) - 1 + numberBasis;
00527 
00528     // for each subfacet dimension less than the target subfacet dim which has mid nodes,
00529     // add the number of subfacets of that dimension to the index
00530     for( i = 1; i < subfacet_dim; i++ )
00531         if( has_mids[i] ) index += NumSubEntities( this_type, i );
00532 
00533     // now add the index of this subfacet, or one if we're asking about the entity as a whole
00534     if( subfacet_index == -1 && has_mids[subfacet_dim] )
00535         // want the index of the last ho node on this subfacet
00536         index += NumSubEntities( this_type, subfacet_dim );
00537 
00538     else if( subfacet_index != -1 && has_mids[subfacet_dim] )
00539         index += subfacet_index + 1 - numberBasis;
00540 
00541     // that's it
00542     return index;
00543 }
00544 
00545 //! given data about an element and a vertex in that element, return the dimension
00546 //! and index of the sub-entity that the vertex resolves.  If it does not resolve a
00547 //! sub-entity, either because it's a corner node or it's not in the element, -1 is
00548 //! returned in both return values
00549 void CN::HONodeParent( EntityType elem_type, int num_verts, int ho_index, int& parent_dim, int& parent_index )
00550 {
00551     // begin with error values
00552     parent_dim = parent_index = -1;
00553 
00554     // given the number of verts and the element type, get the hasmidnodes solution
00555     int has_mids[4];
00556     HasMidNodes( elem_type, num_verts, has_mids );
00557 
00558     int index     = VerticesPerEntity( elem_type ) - 1;
00559     const int dim = Dimension( elem_type );
00560 
00561     // keep a running sum of the ho node indices for this type of element, and stop
00562     // when you get to the dimension which has the ho node
00563     for( int i = 1; i < dim; i++ )
00564     {
00565         if( has_mids[i] )
00566         {
00567             if( ho_index <= index + NumSubEntities( elem_type, i ) )
00568             {
00569                 // the ho_index resolves an entity of dimension i, so set the return values
00570                 // and break out of the loop
00571                 parent_dim   = i;
00572                 parent_index = ho_index - index - 1;
00573                 return;
00574             }
00575             else
00576             {
00577                 index += NumSubEntities( elem_type, i );
00578             }
00579         }
00580     }
00581 
00582     // mid region node case
00583     if( has_mids[dim] && ho_index == index + 1 )
00584     {
00585         parent_dim   = dim;
00586         parent_index = 0;
00587     }
00588 }
00589 
00590 const char* CN::EntityTypeName( const EntityType this_type )
00591 {
00592     return entityTypeNames[this_type];
00593 }
00594 
00595 }  // namespace moab
00596 
00597 using moab::CN;
00598 using moab::EntityType;
00599 
00600 //! get the basis of the numbering system
00601 void MBCN_GetBasis( int* rval )
00602 {
00603     *rval = CN::GetBasis();
00604 }
00605 
00606 //! set the basis of the numbering system
00607 void MBCN_SetBasis( const int in_basis )
00608 {
00609     CN::SetBasis( in_basis );
00610 }
00611 
00612 //! return the string type name for this type
00613 void MBCN_EntityTypeName( const int this_type, char* rval, int rval_len )
00614 {
00615     const char* rval_tmp = CN::EntityTypeName( (EntityType)this_type );
00616     int rval_len_tmp     = strlen( rval_tmp );
00617     rval_len_tmp         = ( rval_len_tmp < rval_len ? rval_len_tmp : rval_len );
00618     strncpy( rval, rval_tmp, rval_len_tmp );
00619 }
00620 
00621 //! given a name, find the corresponding entity type
00622 void MBCN_EntityTypeFromName( const char* name, int* rval )
00623 {
00624     *rval = CN::EntityTypeFromName( name );
00625 }
00626 
00627 //! return the topological entity dimension
00628 void MBCN_Dimension( const int t, int* rval )
00629 {
00630     *rval = CN::Dimension( (EntityType)t );
00631 }
00632 
00633 //! return the number of (corner) vertices contained in the specified type.
00634 void MBCN_VerticesPerEntity( const int t, int* rval )
00635 {
00636     *rval = CN::VerticesPerEntity( (EntityType)t );
00637 }
00638 
00639 //! return the number of sub-entities bounding the entity.
00640 void MBCN_NumSubEntities( const int t, const int d, int* rval )
00641 {
00642     *rval = CN::NumSubEntities( (EntityType)t, d );
00643 }
00644 
00645 //! return the type of a particular sub-entity.
00646 //! \param this_type Type of entity for which sub-entity type is being queried
00647 //! \param sub_dimension Topological dimension of sub-entity whose type is being queried
00648 //! \param index Index of sub-entity whose type is being queried
00649 //! \return type Entity type of sub-entity with specified dimension and index
00650 void MBCN_SubEntityType( const int this_type, const int sub_dimension, const int index, int* rval )
00651 
00652 {
00653 
00654     *rval = CN::SubEntityType( (EntityType)this_type, sub_dimension, index );
00655 }
00656 
00657 //! return the vertex indices of the specified sub-entity.
00658 //! \param this_type Type of entity for which sub-entity connectivity is being queried
00659 //! \param sub_dimension Dimension of sub-entity
00660 //! \param sub_index Index of sub-entity
00661 //! \param sub_entity_conn Connectivity of sub-entity (returned to calling function)
00662 void MBCN_SubEntityVertexIndices( const int this_type, const int sub_dimension, const int sub_index,
00663                                   int sub_entity_conn[] )
00664 {
00665     CN::SubEntityVertexIndices( (EntityType)this_type, sub_dimension, sub_index, sub_entity_conn );
00666 }
00667 
00668 //! return the vertices of the specified sub entity
00669 //! \param parent_conn Connectivity of parent entity
00670 //! \param parent_type Entity type of parent entity
00671 //! \param sub_dimension Dimension of sub-entity being queried
00672 //! \param sub_index Index of sub-entity being queried
00673 //! \param sub_entity_conn Connectivity of sub-entity, based on parent_conn and canonical
00674 //!           ordering for parent_type
00675 //! \param num_sub_vertices Number of vertices in sub-entity
00676 //  void MBCN_SubEntityConn(const void *parent_conn, const int parent_type,
00677 //                            const int sub_dimension,
00678 //                            const int sub_index,
00679 //                            void *sub_entity_conn, int &num_sub_vertices) {return
00680 //                            CN::SubEntityConn();}
00681 
00682 //! For a specified set of sides of given dimension, return the intersection
00683 //! or union of all sides of specified target dimension adjacent to those sides.
00684 //! \param this_type Type of entity for which sub-entity connectivity is being queried
00685 //! \param source_indices Indices of sides being queried
00686 //! \param num_source_indices Number of entries in <em>source_indices</em>
00687 //! \param source_dim Dimension of source entity
00688 //! \param target_dim Dimension of target entity
00689 //! \param index_list Indices of target entities (returned)
00690 //! \param num_indices Number of indices of target entities (returned)
00691 //! \param operation_type Specify either CN::INTERSECT (0) or CN::UNION (1) to get intersection
00692 //!        or union of target entity lists over source entities
00693 //! \param rval Error code indicating success or failure (returned)
00694 void MBCN_AdjacentSubEntities( const int this_type, const int* source_indices, const int num_source_indices,
00695                                const int source_dim, const int target_dim, int* index_list, int* num_indices,
00696                                const int operation_type, int* rval )
00697 {
00698     std::vector< int > tmp_index_list;
00699     *rval = CN::AdjacentSubEntities( (EntityType)this_type, source_indices, num_source_indices, source_dim, target_dim,
00700                                      tmp_index_list, operation_type );
00701     std::copy( tmp_index_list.begin(), tmp_index_list.end(), index_list );
00702     *num_indices = tmp_index_list.size();
00703 }
00704 
00705 //! return the side index represented in the input sub-entity connectivity
00706 //! \param parent_type Entity type of parent entity
00707 //! \param child_conn_indices Child connectivity to query, specified as indices
00708 //!                           into the connectivity list of the parent.
00709 //! \param child_num_verts Number of values in <em>child_conn_indices</em>
00710 //! \param child_dim Dimension of child entity being queried
00711 //! \param side_no Side number of child entity (returned)
00712 //! \param sense Sense of child entity with respect to order in <em>child_conn</em> (returned)
00713 //! \param offset Offset of <em>child_conn</em> with respect to canonical ordering data (returned)
00714 //! \return status Returns zero if successful, -1 if not
00715 void MBCN_SideNumber( const int parent_type, const int* child_conn_indices, const int child_num_verts,
00716                       const int child_dim, int* side_no, int* sense, int* offset )
00717 {
00718     CN::SideNumber( (EntityType)parent_type, child_conn_indices, child_num_verts, child_dim, *side_no, *sense,
00719                     *offset );
00720 }
00721 
00722 void MBCN_SideNumberInt( const int* parent_conn, const EntityType parent_type, const int* child_conn,
00723                          const int child_num_verts, const int child_dim, int* side_no, int* sense, int* offset )
00724 {
00725     moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset );
00726 }
00727 
00728 void MBCN_SideNumberUint( const unsigned int* parent_conn, const EntityType parent_type, const unsigned int* child_conn,
00729                           const int child_num_verts, const int child_dim, int* side_no, int* sense, int* offset )
00730 {
00731     moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset );
00732 }
00733 
00734 void MBCN_SideNumberLong( const long* parent_conn, const EntityType parent_type, const long* child_conn,
00735                           const int child_num_verts, const int child_dim, int* side_no, int* sense, int* offset )
00736 {
00737     moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset );
00738 }
00739 
00740 void MBCN_SideNumberUlong( const unsigned long* parent_conn, const EntityType parent_type,
00741                            const unsigned long* child_conn, const int child_num_verts, const int child_dim,
00742                            int* side_no, int* sense, int* offset )
00743 {
00744     moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset );
00745 }
00746 
00747 void MBCN_SideNumberVoid( void* const* parent_conn, const EntityType parent_type, void* const* child_conn,
00748                           const int child_num_verts, const int child_dim, int* side_no, int* sense, int* offset )
00749 {
00750     moab::side_number( parent_conn, parent_type, child_conn, child_num_verts, child_dim, *side_no, *sense, *offset );
00751 }
00752 
00753 //! return the dimension and index of the opposite side, given parent entity type and child
00754 //! dimension and index.  This function is only defined for certain types of parent/child types:
00755 //! (Parent, Child dim->Opposite dim):
00756 //!  (Tri, 1->0), (Tri, 0->1), (Quad, 1->1), (Quad, 0->0),
00757 //!  (Tet, 2->0), (Tet, 1->1), (Tet, 0->2),
00758 //!  (Hex, 2->2), (Hex, 1->1)(diagonally across element), (Hex, 0->0) (diagonally across element)
00759 //! All other parent types and child dimensions return an error.
00760 //!
00761 //! \param parent_type The type of parent element
00762 //! \param child_type The type of child element
00763 //! \param child_index The index of the child element
00764 //! \param opposite_index The index of the opposite element
00765 //! \return status Returns 0 if successful, -1 if not
00766 void MBCN_OppositeSide( const int parent_type, const int child_index, const int child_dim, int* opposite_index,
00767                         int* opposite_dim, int* rval )
00768 {
00769     *rval = CN::OppositeSide( (EntityType)parent_type, child_index, child_dim, *opposite_index, *opposite_dim );
00770 }
00771 
00772 //! given two connectivity arrays, determine whether or not they represent the same entity.
00773 //! \param conn1 Connectivity array of first entity
00774 //! \param conn2 Connectivity array of second entity
00775 //! \param num_vertices Number of entries in <em>conn1</em> and <em>conn2</em>
00776 //! \param direct If positive, entities have the same sense (returned)
00777 //! \param offset Offset of <em>conn2</em>'s first vertex in <em>conn1</em>
00778 //! \return rval Returns true if <em>conn1</em> and <em>conn2</em> match
00779 void MBCN_ConnectivityMatchInt( const int* conn1, const int* conn2, const int num_vertices, int* direct, int* offset,
00780                                 int* rval )
00781 {
00782     *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset );
00783 }
00784 
00785 void MBCN_ConnectivityMatchUint( const unsigned int* conn1, const unsigned int* conn2, const int num_vertices,
00786                                  int* direct, int* offset, int* rval )
00787 {
00788     *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset );
00789 }
00790 
00791 void MBCN_ConnectivityMatchLong( const long* conn1, const long* conn2, const int num_vertices, int* direct, int* offset,
00792                                  int* rval )
00793 {
00794     *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset );
00795 }
00796 
00797 void MBCN_ConnectivityMatchUlong( const unsigned long* conn1, const unsigned long* conn2, const int num_vertices,
00798                                   int* direct, int* offset, int* rval )
00799 {
00800     *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset );
00801 }
00802 
00803 void MBCN_ConnectivityMatchVoid( void* const* conn1, void* const* conn2, const int num_vertices, int* direct,
00804                                  int* offset, int* rval )
00805 {
00806     *rval = CN::ConnectivityMatch( conn1, conn2, num_vertices, *direct, *offset );
00807 }
00808 
00809 //! true if entities of a given type and number of nodes indicates mid edge nodes are present.
00810 //! \param this_type Type of entity for which sub-entity connectivity is being queried
00811 //! \param num_verts Number of nodes defining entity
00812 //! \return int Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates
00813 //!  mid-edge nodes are likely
00814 void MBCN_HasMidEdgeNodes( const int this_type, const int num_verts, int* rval )
00815 {
00816     *rval = CN::HasMidEdgeNodes( (EntityType)this_type, num_verts );
00817 }
00818 
00819 //! true if entities of a given type and number of nodes indicates mid face nodes are present.
00820 //! \param this_type Type of entity for which sub-entity connectivity is being queried
00821 //! \param num_verts Number of nodes defining entity
00822 //! \return int Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates
00823 //!  mid-face nodes are likely
00824 void MBCN_HasMidFaceNodes( const int this_type, const int num_verts, int* rval )
00825 {
00826     *rval = CN::HasMidFaceNodes( (EntityType)this_type, num_verts );
00827 }
00828 
00829 //! true if entities of a given type and number of nodes indicates mid region nodes are present.
00830 //! \param this_type Type of entity for which sub-entity connectivity is being queried
00831 //! \param num_verts Number of nodes defining entity
00832 //! \return int Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates
00833 //!  mid-region nodes are likely
00834 void MBCN_HasMidRegionNodes( const int this_type, const int num_verts, int* rval )
00835 {
00836     *rval = CN::HasMidRegionNodes( (EntityType)this_type, num_verts );
00837 }
00838 
00839 //! true if entities of a given type and number of nodes indicates mid edge/face/region nodes
00840 //! are present.
00841 //! \param this_type Type of entity for which sub-entity connectivity is being queried
00842 //! \param num_verts Number of nodes defining entity
00843 //! \param mid_nodes If <em>mid_nodes[i], i=1..3</em> is true, indicates that mid-edge
00844 //!    (i=1), mid-face (i=2), and/or mid-region (i=3) nodes are likely
00845 void MBCN_HasMidNodes( const int this_type, const int num_verts, int mid_nodes[4] )
00846 {
00847     return CN::HasMidNodes( (EntityType)this_type, num_verts, mid_nodes );
00848 }
00849 
00850 //! given data about an element and a vertex in that element, return the dimension
00851 //! and index of the sub-entity that the vertex resolves.  If it does not resolve a
00852 //! sub-entity, either because it's a corner node or it's not in the element, -1 is
00853 //! returned in both return values.
00854 //! \param elem_type Type of entity being queried
00855 //! \param num_nodes The number of nodes in the element connectivity
00856 //! \param ho_node_index The position of the HO node in the connectivity list (zero based)
00857 //! \param parent_dim Dimension of sub-entity high-order node resolves (returned)
00858 //! \param parent_index Index of sub-entity high-order node resolves (returned)
00859 void MBCN_HONodeParent( int elem_type, int num_nodes, int ho_node_index, int* parent_dim, int* parent_index )
00860 {
00861     return CN::HONodeParent( (EntityType)elem_type, num_nodes, ho_node_index, *parent_dim, *parent_index );
00862 }
00863 
00864 //! for an entity of this type with num_verts vertices, and a specified subfacet
00865 //! (dimension and index), return the index of the higher order node for that entity
00866 //! in this entity's connectivity array
00867 //! \param this_type Type of entity being queried
00868 //! \param num_verts Number of vertices for the entity being queried
00869 //! \param subfacet_dim Dimension of sub-entity being queried
00870 //! \param subfacet_index Index of sub-entity being queried
00871 //! \return index Index of sub-entity's higher-order node
00872 void MBCN_HONodeIndex( const int this_type, const int num_verts, const int subfacet_dim, const int subfacet_index,
00873                        int* rval )
00874 
00875 {
00876 
00877     *rval = CN::HONodeIndex( (EntityType)this_type, num_verts, subfacet_dim, subfacet_index );
00878 }
00879 
00880 namespace moab
00881 {
00882 
00883 template < typename T >
00884 inline int permute_this( EntityType t, const int dim, T* conn, const int indices_per_ent, const int num_entries )
00885 {
00886     T tmp_conn[MAX_SUB_ENTITIES];
00887     assert( indices_per_ent <= CN::permuteVec[t][dim][MAX_SUB_ENTITIES] );
00888     if( indices_per_ent > CN::permuteVec[t][dim][MAX_SUB_ENTITIES] ) return 1;
00889     short int* tvec = CN::permuteVec[t][dim];
00890     T* pvec         = conn;
00891     for( int j = 0; j < num_entries; j++ )
00892     {
00893         for( int i = 0; i < indices_per_ent; i++ )
00894             tmp_conn[tvec[i]] = pvec[i];
00895         memcpy( pvec, tmp_conn, indices_per_ent * sizeof( T ) );
00896         pvec += indices_per_ent;
00897     }
00898 
00899     return 0;
00900 }
00901 
00902 template < typename T >
00903 inline int rev_permute_this( EntityType t, const int dim, T* conn, const int indices_per_ent, const int num_entries )
00904 {
00905     T tmp_conn[MAX_SUB_ENTITIES];
00906     assert( indices_per_ent <= CN::revPermuteVec[t][dim][MAX_SUB_ENTITIES] );
00907     if( indices_per_ent > CN::revPermuteVec[t][dim][MAX_SUB_ENTITIES] ) return 1;
00908     short int* tvec = CN::revPermuteVec[t][dim];
00909     T* pvec         = conn;
00910     for( int j = 0; j < num_entries; j++ )
00911     {
00912         for( int i = 0; i < indices_per_ent; i++ )
00913             tmp_conn[i] = pvec[tvec[i]];
00914         memcpy( pvec, tmp_conn, indices_per_ent * sizeof( T ) );
00915         pvec += indices_per_ent;
00916     }
00917 
00918     return 0;
00919 }
00920 
00921 short int CN::Dimension( const EntityType t )
00922 {
00923     return mConnectivityMap[t][0].topo_dimension;
00924 }
00925 
00926 short int CN::VerticesPerEntity( const EntityType t )
00927 {
00928     return ( MBVERTEX == t
00929                  ? (short int)1
00930                  : mConnectivityMap[t][mConnectivityMap[t][0].topo_dimension - 1].num_corners_per_sub_element[0] );
00931 }
00932 
00933 short int CN::NumSubEntities( const EntityType t, const int d )
00934 {
00935     return ( t != MBVERTEX && d > 0 ? mConnectivityMap[t][d - 1].num_sub_elements
00936                                     : ( d ? (short int)-1 : VerticesPerEntity( t ) ) );
00937 }
00938 
00939 //! return the type of a particular sub-entity.
00940 EntityType CN::SubEntityType( const EntityType this_type, const int sub_dimension, const int index )
00941 {
00942     return ( !sub_dimension ? MBVERTEX
00943                             : ( Dimension( this_type ) == sub_dimension && 0 == index
00944                                     ? this_type
00945                                     : mConnectivityMap[this_type][sub_dimension - 1].target_type[index] ) );
00946 }
00947 
00948 const short* CN::SubEntityVertexIndices( const EntityType this_type, const int sub_dimension, const int index,
00949                                          EntityType& sub_type, int& n )
00950 {
00951     if( sub_dimension == 0 )
00952     {
00953         n        = 1;
00954         sub_type = MBVERTEX;
00955         return increasingInts + index;
00956     }
00957     else
00958     {
00959         const CN::ConnMap& map = mConnectivityMap[this_type][sub_dimension - 1];
00960         sub_type               = map.target_type[index];
00961         n                      = map.num_corners_per_sub_element[index];
00962         return map.conn[index];
00963     }
00964 }
00965 
00966 //! Permute this vector
00967 inline int CN::permuteThis( const EntityType t, const int dim, int* pvec, const int num_indices, const int num_entries )
00968 {
00969     return permute_this( t, dim, pvec, num_indices, num_entries );
00970 }
00971 inline int CN::permuteThis( const EntityType t, const int dim, unsigned int* pvec, const int num_indices,
00972                             const int num_entries )
00973 {
00974     return permute_this( t, dim, pvec, num_indices, num_entries );
00975 }
00976 inline int CN::permuteThis( const EntityType t, const int dim, long* pvec, const int num_indices,
00977                             const int num_entries )
00978 {
00979     return permute_this( t, dim, pvec, num_indices, num_entries );
00980 }
00981 inline int CN::permuteThis( const EntityType t, const int dim, void** pvec, const int num_indices,
00982                             const int num_entries )
00983 {
00984     return permute_this( t, dim, pvec, num_indices, num_entries );
00985 }
00986 
00987 //! Reverse permute this vector
00988 inline int CN::revPermuteThis( const EntityType t, const int dim, int* pvec, const int num_indices,
00989                                const int num_entries )
00990 {
00991     return rev_permute_this( t, dim, pvec, num_indices, num_entries );
00992 }
00993 inline int CN::revPermuteThis( const EntityType t, const int dim, unsigned int* pvec, const int num_indices,
00994                                const int num_entries )
00995 {
00996     return rev_permute_this( t, dim, pvec, num_indices, num_entries );
00997 }
00998 inline int CN::revPermuteThis( const EntityType t, const int dim, long* pvec, const int num_indices,
00999                                const int num_entries )
01000 {
01001     return rev_permute_this( t, dim, pvec, num_indices, num_entries );
01002 }
01003 inline int CN::revPermuteThis( const EntityType t, const int dim, void** pvec, const int num_indices,
01004                                const int num_entries )
01005 {
01006     return rev_permute_this( t, dim, pvec, num_indices, num_entries );
01007 }
01008 
01009 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines