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 /**\file MeshSetSequence.cpp 00017 *\author Jason Kraftcheck ([email protected]) 00018 *\date 2007-04-30 00019 */ 00020 00021 #include "MeshSetSequence.hpp" 00022 #include "SequenceManager.hpp" 00023 00024 namespace moab 00025 { 00026 00027 MeshSetSequence::MeshSetSequence( EntityHandle start, EntityID count, const unsigned* flags, SequenceData* dat ) 00028 : EntitySequence( start, count, dat ) 00029 { 00030 initialize( flags ); 00031 } 00032 00033 MeshSetSequence::MeshSetSequence( EntityHandle start, EntityID count, unsigned flags, SequenceData* dat ) 00034 : EntitySequence( start, count, dat ) 00035 { 00036 std::vector< unsigned > vect( count, flags ); 00037 initialize( &vect[0] ); 00038 } 00039 00040 MeshSetSequence::MeshSetSequence( EntityHandle start, EntityID count, const unsigned* flags, EntityID data_size ) 00041 : EntitySequence( start, count, new SequenceData( 1, start, start + data_size - 1 ) ) 00042 { 00043 initialize( flags ); 00044 } 00045 00046 MeshSetSequence::MeshSetSequence( EntityHandle start, EntityID count, unsigned flags, EntityID data_size ) 00047 : EntitySequence( start, count, new SequenceData( 1, start, start + data_size - 1 ) ) 00048 { 00049 std::vector< unsigned > vect( count, flags ); 00050 initialize( &vect[0] ); 00051 } 00052 00053 void MeshSetSequence::initialize( const unsigned* flags ) 00054 { 00055 if( !data()->get_sequence_data( 0 ) ) data()->create_sequence_data( 0, SET_SIZE ); 00056 00057 EntityID offset = start_handle() - data()->start_handle(); 00058 for( EntityID i = 0; i < size(); ++i ) 00059 allocate_set( flags[i], i + offset ); 00060 } 00061 00062 MeshSetSequence::~MeshSetSequence() 00063 { 00064 EntityID offset = start_handle() - data()->start_handle(); 00065 EntityID count = size(); 00066 for( EntityID i = 0; i < count; ++i ) 00067 deallocate_set( i + offset ); 00068 } 00069 00070 EntitySequence* MeshSetSequence::split( EntityHandle here ) 00071 { 00072 return new MeshSetSequence( *this, here ); 00073 } 00074 00075 ErrorCode MeshSetSequence::pop_back( EntityID count ) 00076 { 00077 EntityID offset = end_handle() + 1 - count - data()->start_handle(); 00078 ErrorCode rval = EntitySequence::pop_back( count ); 00079 if( MB_SUCCESS == rval ) 00080 for( EntityID i = 0; i < count; ++i ) 00081 deallocate_set( i + offset ); 00082 return rval; 00083 } 00084 00085 ErrorCode MeshSetSequence::pop_front( EntityID count ) 00086 { 00087 EntityID offset = start_handle() - data()->start_handle(); 00088 ErrorCode rval = EntitySequence::pop_front( count ); 00089 if( MB_SUCCESS == rval ) 00090 for( EntityID i = 0; i < count; ++i ) 00091 deallocate_set( i + offset ); 00092 return rval; 00093 } 00094 00095 ErrorCode MeshSetSequence::push_back( EntityID count, const unsigned* flags ) 00096 { 00097 EntityID offset = end_handle() + 1 - data()->start_handle(); 00098 ErrorCode rval = EntitySequence::append_entities( count ); 00099 if( MB_SUCCESS == rval ) 00100 for( EntityID i = 0; i < count; ++i ) 00101 allocate_set( flags[i], i + offset ); 00102 return rval; 00103 } 00104 00105 ErrorCode MeshSetSequence::push_front( EntityID count, const unsigned* flags ) 00106 { 00107 EntityID offset = start_handle() - data()->start_handle() - count; 00108 ErrorCode rval = EntitySequence::prepend_entities( count ); 00109 if( MB_SUCCESS == rval ) 00110 for( EntityID i = 0; i < count; ++i ) 00111 allocate_set( flags[i], i + offset ); 00112 return rval; 00113 } 00114 00115 void MeshSetSequence::get_const_memory_use( unsigned long& per_ent, unsigned long& seq_size ) const 00116 { 00117 per_ent = SET_SIZE; 00118 seq_size = sizeof( *this ); 00119 } 00120 00121 unsigned long MeshSetSequence::get_per_entity_memory_use( EntityHandle first, EntityHandle last ) const 00122 { 00123 if( first < start_handle() ) first = start_handle(); 00124 if( last > end_handle() ) last = end_handle(); 00125 00126 unsigned long sum = 0; 00127 for( EntityHandle h = first; h <= last; ++h ) 00128 sum += get_set( h )->get_memory_use(); 00129 return sum; 00130 } 00131 00132 ErrorCode MeshSetSequence::get_entities( const SequenceManager* seqman, 00133 EntityHandle handle, 00134 Range& entities, 00135 bool recursive ) const 00136 { 00137 if( !recursive ) 00138 { 00139 get_set( handle )->get_entities( entities ); 00140 return MB_SUCCESS; 00141 } 00142 else 00143 { 00144 std::vector< const MeshSet* > list; 00145 ErrorCode rval = recursive_get_sets( handle, seqman, &list ); 00146 for( std::vector< const MeshSet* >::iterator i = list.begin(); i != list.end(); ++i ) 00147 ( *i )->get_non_set_entities( entities ); 00148 return rval; 00149 } 00150 } 00151 00152 ErrorCode MeshSetSequence::get_entities( EntityHandle handle, std::vector< EntityHandle >& entities ) const 00153 { 00154 get_set( handle )->get_entities( entities ); 00155 return MB_SUCCESS; 00156 } 00157 00158 ErrorCode MeshSetSequence::get_dimension( const SequenceManager* seqman, 00159 EntityHandle handle, 00160 int dimension, 00161 std::vector< EntityHandle >& entities, 00162 bool recursive ) const 00163 { 00164 if( !recursive ) 00165 { 00166 get_set( handle )->get_entities_by_dimension( dimension, entities ); 00167 return MB_SUCCESS; 00168 } 00169 else 00170 { 00171 std::vector< const MeshSet* > list; 00172 ErrorCode rval = recursive_get_sets( handle, seqman, &list ); 00173 for( std::vector< const MeshSet* >::iterator i = list.begin(); i != list.end(); ++i ) 00174 ( *i )->get_entities_by_dimension( dimension, entities ); 00175 return rval; 00176 } 00177 } 00178 00179 ErrorCode MeshSetSequence::get_dimension( const SequenceManager* seqman, 00180 EntityHandle handle, 00181 int dimension, 00182 Range& entities, 00183 bool recursive ) const 00184 { 00185 if( !recursive ) 00186 { 00187 get_set( handle )->get_entities_by_dimension( dimension, entities ); 00188 return MB_SUCCESS; 00189 } 00190 else 00191 { 00192 std::vector< const MeshSet* > list; 00193 ErrorCode rval = recursive_get_sets( handle, seqman, &list ); 00194 for( std::vector< const MeshSet* >::iterator i = list.begin(); i != list.end(); ++i ) 00195 ( *i )->get_entities_by_dimension( dimension, entities ); 00196 return rval; 00197 } 00198 } 00199 00200 ErrorCode MeshSetSequence::get_type( const SequenceManager* seqman, 00201 EntityHandle handle, 00202 EntityType tp, 00203 std::vector< EntityHandle >& entities, 00204 bool recursive ) const 00205 { 00206 if( !recursive ) 00207 { 00208 get_set( handle )->get_entities_by_type( tp, entities ); 00209 return MB_SUCCESS; 00210 } 00211 else if( tp == MBENTITYSET ) 00212 { 00213 return recursive_get_sets( handle, seqman, 0, 0, &entities ); 00214 } 00215 else if( tp == MBMAXTYPE ) 00216 { 00217 Range tmp; 00218 ErrorCode rval = get_entities( seqman, handle, tmp, recursive ); 00219 if( MB_SUCCESS == rval ) 00220 { 00221 #ifdef MOAB_NO_VECTOR_TEMPLATE_INSERT 00222 std::copy( tmp.begin(), tmp.end(), std::back_inserter( entities ) ); 00223 #else 00224 entities.insert( entities.end(), tmp.begin(), tmp.end() ); 00225 #endif 00226 } 00227 return rval; 00228 } 00229 else 00230 { 00231 std::vector< const MeshSet* > list; 00232 ErrorCode rval = recursive_get_sets( handle, seqman, &list ); 00233 for( std::vector< const MeshSet* >::iterator i = list.begin(); i != list.end(); ++i ) 00234 ( *i )->get_entities_by_type( tp, entities ); 00235 return rval; 00236 } 00237 } 00238 00239 ErrorCode MeshSetSequence::get_type( const SequenceManager* seqman, 00240 EntityHandle handle, 00241 EntityType tp, 00242 Range& entities, 00243 bool recursive ) const 00244 { 00245 if( !recursive ) 00246 { 00247 get_set( handle )->get_entities_by_type( tp, entities ); 00248 return MB_SUCCESS; 00249 } 00250 else if( tp == MBENTITYSET ) 00251 { 00252 return recursive_get_sets( handle, seqman, 0, &entities ); 00253 } 00254 else if( tp == MBMAXTYPE ) 00255 { 00256 std::vector< const MeshSet* > list; 00257 ErrorCode rval = recursive_get_sets( handle, seqman, &list ); 00258 for( std::vector< const MeshSet* >::iterator i = list.begin(); i != list.end(); ++i ) 00259 ( *i )->get_non_set_entities( entities ); 00260 return rval; 00261 } 00262 else 00263 { 00264 std::vector< const MeshSet* > list; 00265 ErrorCode rval = recursive_get_sets( handle, seqman, &list ); 00266 for( std::vector< const MeshSet* >::iterator i = list.begin(); i != list.end(); ++i ) 00267 ( *i )->get_entities_by_type( tp, entities ); 00268 return rval; 00269 } 00270 } 00271 00272 ErrorCode MeshSetSequence::num_entities( const SequenceManager* seqman, 00273 EntityHandle handle, 00274 int& number, 00275 bool recursive ) const 00276 { 00277 if( !recursive ) 00278 { 00279 number = get_set( handle )->num_entities(); 00280 return MB_SUCCESS; 00281 } 00282 else 00283 { 00284 Range range; 00285 ErrorCode result = get_entities( seqman, handle, range, true ); 00286 number = range.size(); 00287 return result; 00288 } 00289 } 00290 00291 ErrorCode MeshSetSequence::num_dimension( const SequenceManager* seqman, 00292 EntityHandle handle, 00293 int dimension, 00294 int& number, 00295 bool recursive ) const 00296 { 00297 if( !recursive ) 00298 { 00299 number = get_set( handle )->num_entities_by_dimension( dimension ); 00300 return MB_SUCCESS; 00301 } 00302 else 00303 { 00304 Range range; 00305 ErrorCode result = get_dimension( seqman, handle, dimension, range, true ); 00306 number = range.size(); 00307 return result; 00308 } 00309 } 00310 00311 ErrorCode MeshSetSequence::num_type( const SequenceManager* seqman, 00312 EntityHandle handle, 00313 EntityType tp, 00314 int& number, 00315 bool recursive ) const 00316 { 00317 if( !recursive ) 00318 { 00319 number = get_set( handle )->num_entities_by_type( tp ); 00320 return MB_SUCCESS; 00321 } 00322 else 00323 { 00324 Range range; 00325 ErrorCode result = get_type( seqman, handle, tp, range, true ); 00326 number = range.size(); 00327 return result; 00328 } 00329 } 00330 00331 ErrorCode MeshSetSequence::recursive_get_sets( EntityHandle start_set, 00332 const SequenceManager* seq_sets, 00333 std::vector< const MeshSet* >* sets, 00334 Range* set_handles, 00335 std::vector< EntityHandle >* set_vector ) 00336 { 00337 std::set< EntityHandle > visited; 00338 std::vector< EntityHandle > stack; 00339 stack.push_back( start_set ); 00340 bool remove_start_set = true; 00341 while( !stack.empty() ) 00342 { 00343 EntityHandle handle = stack.back(); 00344 stack.pop_back(); 00345 00346 if( !visited.insert( handle ).second ) 00347 { 00348 if( handle == start_set ) remove_start_set = false; 00349 continue; 00350 } 00351 00352 const EntitySequence* seq; 00353 ErrorCode rval = seq_sets->find( handle, seq ); 00354 if( MB_SUCCESS != rval ) return rval; 00355 00356 const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq ); 00357 const MeshSet* ms_ptr = mseq->get_set( handle ); 00358 if( sets ) sets->push_back( ms_ptr ); 00359 00360 Range tmp_range; 00361 ms_ptr->get_entities_by_type( MBENTITYSET, tmp_range ); 00362 std::copy( tmp_range.begin(), tmp_range.end(), std::back_inserter( stack ) ); 00363 } 00364 00365 if( set_handles ) 00366 { 00367 if( remove_start_set ) visited.erase( start_set ); 00368 Range::iterator hint = set_handles->begin(); 00369 std::set< EntityHandle >::iterator it; 00370 for( it = visited.begin(); it != visited.end(); ++it ) 00371 hint = set_handles->insert( hint, *it, *it ); 00372 } 00373 00374 if( set_vector ) 00375 { 00376 if( remove_start_set ) visited.erase( start_set ); 00377 std::copy( visited.begin(), visited.end(), std::back_inserter( *set_vector ) ); 00378 } 00379 00380 return MB_SUCCESS; 00381 } 00382 00383 ErrorCode MeshSetSequence::recursive_get_sets( EntityHandle start_set, 00384 SequenceManager* seq_sets, 00385 std::vector< MeshSet* >& sets ) 00386 { 00387 std::set< EntityHandle > visited; 00388 std::vector< EntityHandle > stack; 00389 stack.push_back( start_set ); 00390 while( !stack.empty() ) 00391 { 00392 EntityHandle handle = stack.back(); 00393 stack.pop_back(); 00394 00395 if( !visited.insert( handle ).second ) continue; 00396 00397 EntitySequence* seq; 00398 ErrorCode rval = seq_sets->find( handle, seq ); 00399 if( MB_SUCCESS != rval ) return rval; 00400 00401 MeshSetSequence* mseq = reinterpret_cast< MeshSetSequence* >( seq ); 00402 MeshSet* ms_ptr = mseq->get_set( handle ); 00403 sets.push_back( ms_ptr ); 00404 00405 Range tmp_range; 00406 ms_ptr->get_entities_by_type( MBENTITYSET, tmp_range ); 00407 std::copy( tmp_range.begin(), tmp_range.end(), std::back_inserter( stack ) ); 00408 } 00409 00410 return MB_SUCCESS; 00411 } 00412 00413 ErrorCode MeshSetSequence::get_parent_child_meshsets( EntityHandle meshset, 00414 const SequenceManager* seq_sets, 00415 std::vector< EntityHandle >& results, 00416 int num_hops, 00417 SearchType link_type ) const 00418 { 00419 ErrorCode result = MB_SUCCESS; 00420 std::vector< EntityHandle >::iterator i; 00421 const EntityHandle *tmp_array = 0, *end; 00422 EntityHandle s, e; 00423 int count = 0; 00424 size_t n; 00425 00426 // Skip any meshsets already in input vector (yes, don't 00427 // get their children either even if num_hops would indicate 00428 // that we should.) There is an exception to that if the 00429 // input meshset is in the list, which is handled by the order 00430 // of checks in the main loop below. 00431 std::set< EntityHandle > visited; 00432 for( i = results.begin(); i != results.end(); ++i ) 00433 visited.insert( *i ); 00434 00435 // Two lists for breadth-first search 00436 std::vector< EntityHandle > lists[2]; 00437 int index = 0; // which list to read from (write to lists[1-index]) 00438 lists[index].push_back( meshset ); // begin with input set 00439 // loop for num_hops (or until no more sets) 00440 for( ; num_hops && !lists[index].empty(); --num_hops ) 00441 { 00442 // for each set at the current num_hops 00443 for( i = lists[index].begin(); i != lists[index].end(); ++i ) 00444 { 00445 // get meshset from handle 00446 const EntitySequence* seq; 00447 ErrorCode rval = seq_sets->find( *i, seq ); 00448 if( MB_SUCCESS != rval ) return rval; 00449 const MeshSet* ms_ptr = reinterpret_cast< const MeshSetSequence* >( seq )->get_set( *i ); 00450 00451 switch( link_type ) 00452 { 00453 case CONTAINED: 00454 tmp_array = ms_ptr->get_contents( n ); 00455 end = tmp_array + n; 00456 if( ms_ptr->vector_based() ) 00457 { 00458 for( ; tmp_array != end; ++tmp_array ) 00459 if( MBENTITYSET == TYPE_FROM_HANDLE( *tmp_array ) && visited.insert( *tmp_array ).second ) 00460 lists[1 - index].push_back( *tmp_array ); 00461 } 00462 else 00463 { 00464 assert( n % 2 == 0 ); 00465 tmp_array = std::lower_bound( tmp_array, tmp_array + n, FIRST_HANDLE( MBENTITYSET ) ); 00466 // only part of first block is of type 00467 if( ( end - tmp_array ) % 2 ) 00468 { 00469 ++tmp_array; 00470 s = FIRST_HANDLE( MBENTITYSET ); 00471 e = *tmp_array; 00472 for( ; s <= e; ++s ) 00473 if( visited.insert( s ).second ) lists[1 - index].push_back( s ); 00474 } 00475 while( tmp_array < end ) 00476 { 00477 s = *tmp_array++; 00478 e = *tmp_array++; 00479 for( ; s <= e; ++s ) 00480 if( visited.insert( s ).second ) lists[1 - index].push_back( s ); 00481 } 00482 } 00483 continue; 00484 case PARENTS: 00485 tmp_array = ms_ptr->get_parents( count ); 00486 break; 00487 case CHILDREN: 00488 tmp_array = ms_ptr->get_children( count ); 00489 break; 00490 } 00491 00492 // copy any parents/children we haven't visited yet into list 00493 for( end = tmp_array + count; tmp_array != end; ++tmp_array ) 00494 if( visited.insert( *tmp_array ).second ) lists[1 - index].push_back( *tmp_array ); 00495 } 00496 00497 // iterate 00498 lists[index].clear(); 00499 index = 1 - index; 00500 // append each level of sets to the output list. 00501 // note: to make a more useful search (e.g. get entities 3 hops away, 00502 // rather than entities up to and including 3 hops) move this outside 00503 // the loop, but then need to handle the get all (num_hops < 0) case 00504 // specially. 00505 std::copy( lists[index].begin(), lists[index].end(), std::back_inserter( results ) ); 00506 } 00507 00508 return result; 00509 } 00510 00511 ErrorCode MeshSetSequence::get_parents( const SequenceManager* seqman, 00512 EntityHandle handle, 00513 std::vector< EntityHandle >& parents, 00514 int num_hops ) const 00515 { 00516 if( num_hops == 1 ) 00517 { 00518 int count; 00519 const EntityHandle* tmp_array = get_set( handle )->get_parents( count ); 00520 if( parents.empty() ) 00521 { 00522 parents.resize( count ); 00523 std::copy( tmp_array, tmp_array + count, parents.begin() ); 00524 return MB_SUCCESS; 00525 } 00526 else if( !count ) 00527 { 00528 return MB_SUCCESS; 00529 } 00530 } 00531 00532 if( num_hops > 0 ) 00533 return get_parent_child_meshsets( handle, seqman, parents, num_hops, PARENTS ); 00534 else 00535 return get_parent_child_meshsets( handle, seqman, parents, -1, PARENTS ); 00536 } 00537 00538 ErrorCode MeshSetSequence::get_children( const SequenceManager* seqman, 00539 EntityHandle handle, 00540 std::vector< EntityHandle >& children, 00541 int num_hops ) const 00542 { 00543 if( num_hops == 1 ) 00544 { 00545 int count; 00546 const EntityHandle* tmp_array = get_set( handle )->get_children( count ); 00547 if( children.empty() ) 00548 { 00549 children.resize( count ); 00550 std::copy( tmp_array, tmp_array + count, children.begin() ); 00551 return MB_SUCCESS; 00552 } 00553 else if( !count ) 00554 { 00555 return MB_SUCCESS; 00556 } 00557 } 00558 00559 if( num_hops > 0 ) 00560 return get_parent_child_meshsets( handle, seqman, children, num_hops, CHILDREN ); 00561 else 00562 return get_parent_child_meshsets( handle, seqman, children, -1, CHILDREN ); 00563 } 00564 00565 ErrorCode MeshSetSequence::get_contained_sets( const SequenceManager* seqman, 00566 EntityHandle handle, 00567 std::vector< EntityHandle >& contained, 00568 int num_hops ) const 00569 { 00570 if( num_hops == 1 && contained.empty() ) 00571 { 00572 return get_set( handle )->get_entities_by_type( MBENTITYSET, contained ); 00573 } 00574 00575 if( num_hops > 0 ) 00576 return get_parent_child_meshsets( handle, seqman, contained, num_hops, CONTAINED ); 00577 else 00578 return get_parent_child_meshsets( handle, seqman, contained, -1, CONTAINED ); 00579 } 00580 00581 ErrorCode MeshSetSequence::num_parents( const SequenceManager* seqman, 00582 EntityHandle handle, 00583 int& number, 00584 int num_hops ) const 00585 { 00586 if( num_hops == 1 ) 00587 { 00588 number = get_set( handle )->num_parents(); 00589 return MB_SUCCESS; 00590 } 00591 00592 std::vector< EntityHandle > parents; 00593 ErrorCode result = get_parents( seqman, handle, parents, num_hops ); 00594 number = parents.size(); 00595 return result; 00596 } 00597 00598 ErrorCode MeshSetSequence::num_children( const SequenceManager* seqman, 00599 EntityHandle handle, 00600 int& number, 00601 int num_hops ) const 00602 { 00603 if( num_hops == 1 ) 00604 { 00605 number = get_set( handle )->num_children(); 00606 return MB_SUCCESS; 00607 } 00608 00609 std::vector< EntityHandle > children; 00610 ErrorCode result = get_children( seqman, handle, children, num_hops ); 00611 number = children.size(); 00612 return result; 00613 } 00614 00615 ErrorCode MeshSetSequence::num_contained_sets( const SequenceManager* seqman, 00616 EntityHandle handle, 00617 int& number, 00618 int num_hops ) const 00619 { 00620 if( num_hops == 1 ) 00621 { 00622 number = get_set( handle )->num_entities_by_type( MBENTITYSET ); 00623 return MB_SUCCESS; 00624 } 00625 00626 std::vector< EntityHandle > contained; 00627 ErrorCode result = get_contained_sets( seqman, handle, contained, num_hops ); 00628 number = contained.size(); 00629 return result; 00630 } 00631 00632 } // namespace moab