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