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