![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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
00020 #include
00021 #include
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 source_indices
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 child_conn_indices
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 child_conn (returned)
00797 //! \param offset Offset of child_conn 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 conn1 and conn2
00898 //! \param direct If positive, entities have the same sense (returned)
00899 //! \param offset Offset of conn2's first vertex in conn1
00900 //! \return rval Returns true if conn1 and conn2 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 this_type combined with num_nodes 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 this_type combined with num_nodes 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 this_type combined with num_nodes 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 mid_nodes[i], i=1..3 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