Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ReorderTool.cpp
Go to the documentation of this file.
1 /** \file ReorderTool.cpp 2  * \author Jason Kraftcheck 3  * \date 2011-05-23 4  */ 5  6 #include "moab/ReorderTool.hpp" 7 #include "moab/Core.hpp" 8 #include "moab/Range.hpp" 9  10 #include "SequenceManager.hpp" 11 #include "TypeSequenceManager.hpp" 12 #include "EntitySequence.hpp" 13  14 #include <algorithm> 15 #include <numeric> 16 #include <set> 17 #include <iostream> 18  19 namespace moab 20 { 21  22 // no-op function as a convenient spot to set a breakpoint 23 static inline ErrorCode error( ErrorCode val ) 24 { 25  return val; 26 } 27  28 #define CHKERR \ 29  if( MB_SUCCESS != rval ) return error( rval ) 30  31 #define UNRECOVERABLE( ERRCODE ) \ 32  do \ 33  { \ 34  if( MB_SUCCESS != ( ERRCODE ) ) \ 35  { \ 36  error( ( ERRCODE ) ); \ 37  std::cerr << "Unreconverable error during mesh reorder." << std::endl \ 38  << "Error Code " << ( ERRCODE ) << " at " << __FILE__ << ":" << __LINE__ << std::endl; \ 39  std::cerr.flush(); \ 40  abort(); \ 41  } \ 42  } while( false ) 43  44 static ErrorCode check_tag_type( Interface* moab, Tag tag, DataType exp_type, int exp_size ) 45 { 46  ErrorCode rval; 47  DataType act_type; 48  int act_size; 49  50  rval = moab->tag_get_data_type( tag, act_type );CHKERR; 51  52  rval = moab->tag_get_bytes( tag, act_size );CHKERR; 53  54  if( act_type != exp_type || act_size != exp_size ) return MB_TYPE_OUT_OF_RANGE; 55  56  return MB_SUCCESS; 57 } 58  59 ErrorCode ReorderTool::handle_order_from_int_tag( Tag tag, int skip_value, Tag& new_handles ) 60 { 61  ErrorCode rval; 62  63  // check that input tag handles are what we expect 64  rval = check_tag_type( mMB, tag, MB_TYPE_INTEGER, sizeof( int ) );CHKERR; 65  EntityHandle zero = 0; 66  rval = mMB->tag_get_handle( 0, 1, MB_TYPE_HANDLE, new_handles, MB_TAG_DENSE | MB_TAG_CREAT | MB_TAG_EXCL, &zero );CHKERR; 67  68  // Can only reorder within same type/connectivity (or vertex/num_coords) 69  // groupings. Call helper function for each such grouping. 70  for( EntityType t = MBVERTEX; t < MBENTITYSET; ++t ) 71  { 72  // Get list of all connectivity lengths (or vertex dimensions) 73  // that exist for type t. 74  TypeSequenceManager& seqs = mMB->sequence_manager()->entity_map( t ); 75  TypeSequenceManager::iterator i; 76  std::set< int > values; 77  for( i = seqs.begin(); i != seqs.end(); ++i ) 78  { 79  EntitySequence* seq = *i; 80  // 0 values per entity implies structured data, which 81  // we cannot reorder. Skip those. 82  if( t == MBVERTEX || 0 < seq->values_per_entity() ) values.insert( seq->values_per_entity() ); 83  } 84  85  // Call helper function for each (type,size) tuple. 86  std::set< int >::iterator j; 87  for( j = values.begin(); j != values.end(); ++j ) 88  { 89  rval = handle_order_from_int_tag( t, *j, tag, skip_value, new_handles ); 90  if( MB_SUCCESS != rval ) 91  { 92  mMB->tag_delete( new_handles ); 93  return error( rval ); 94  } 95  } 96  } 97  98  return MB_SUCCESS; 99 } 100  101 void ReorderTool::get_entities( EntityType t, int vals_per_ent, Range& entities ) 102 { 103  Range::iterator hint = entities.begin(); 104  ; 105  TypeSequenceManager& seqs = mMB->sequence_manager()->entity_map( t ); 106  TypeSequenceManager::iterator s; 107  for( s = seqs.begin(); s != seqs.end(); ++s ) 108  { 109  EntitySequence* seq = *s; 110  if( seq->values_per_entity() == vals_per_ent ) 111  hint = entities.insert( hint, seq->start_handle(), seq->end_handle() ); 112  } 113 } 114  115 ErrorCode ReorderTool::handle_order_from_int_tag( EntityType t, 116  int vals_per_ent, 117  Tag tag, 118  int skip_value, 119  Tag new_handles ) 120 { 121  ErrorCode rval; 122  123  // check that input tag handles are what we expect 124  rval = check_tag_type( mMB, tag, MB_TYPE_INTEGER, sizeof( int ) );CHKERR; 125  rval = check_tag_type( mMB, new_handles, MB_TYPE_HANDLE, sizeof( EntityHandle ) );CHKERR; 126  127  // get entities to re-order 128  Range entities; 129  get_entities( t, vals_per_ent, entities ); 130  131  // get entity order values 132  std::vector< int > sortvals( entities.size() ); 133  rval = mMB->tag_get_data( tag, entities, &sortvals[0] );CHKERR; 134  135  // remove any entities for which value is skip_value 136  size_t r = 0, w = 0; 137  for( Range::iterator i = entities.begin(); i != entities.end(); ++r ) 138  { 139  if( sortvals[r] == skip_value ) 140  i = entities.erase( i ); 141  else 142  { 143  sortvals[w++] = sortvals[r]; 144  ++i; 145  } 146  } 147  sortvals.resize( w ); 148  149  // sort 150  std::sort( sortvals.begin(), sortvals.end() ); 151  // Convert to unique list and offsets for each value 152  // When done, sortvals will contain unique, sortvals and 153  // offsets will contain, for each unique value in sortvals, 154  // the number of values that occured in the non-unique list 155  // before the first instance of that value. 156  std::vector< size_t > offsets; 157  offsets.push_back( 0 ); 158  offsets.push_back( 1 ); 159  for( w = 0, r = 1; r < sortvals.size(); ++r ) 160  { 161  if( sortvals[r] == sortvals[w] ) 162  { 163  ++offsets.back(); 164  } 165  else 166  { 167  ++w; 168  sortvals[w] = sortvals[r]; 169  offsets.push_back( offsets.back() + 1 ); 170  } 171  } 172  ++w; 173  assert( w + 1 == offsets.size() ); 174  sortvals.resize( w ); 175  176  // Tag each entity with its new handle 177  for( Range::iterator i = entities.begin(); i != entities.end(); ++i ) 178  { 179  int val; 180  rval = mMB->tag_get_data( tag, &*i, 1, &val );CHKERR; 181  w = std::lower_bound( sortvals.begin(), sortvals.end(), val ) - sortvals.begin(); 182  assert( w < sortvals.size() ); 183  size_t offset = offsets[w]; 184  ++offsets[w]; 185  // should maybe copy range into array to avoid possibly n^2 behavior here 186  EntityHandle h = *( entities.begin() + offset ); 187  rval = mMB->tag_set_data( new_handles, &*i, 1, &h );CHKERR; 188  } 189  190  return MB_SUCCESS; 191 } 192  193 ErrorCode ReorderTool::handle_order_from_sets_and_adj( const Range& sets, Tag& handle_tag ) 194 { 195  ErrorCode rval; 196  197  if( !sets.all_of_type( MBENTITYSET ) ) return MB_TYPE_OUT_OF_RANGE; 198  199  Tag order_tag; 200  const int negone = -1; 201  rval = mMB->tag_get_handle( 0, 1, MB_TYPE_INTEGER, order_tag, MB_TAG_DENSE | MB_TAG_CREAT | MB_TAG_EXCL, &negone ); 202  if( MB_SUCCESS != rval ) 203  { 204  mMB->tag_delete( handle_tag ); 205  handle_tag = 0; 206  return error( rval ); 207  } 208  209  std::vector< std::vector< EntityHandle >* > data; 210  rval = int_order_from_sets_and_adj( sets, order_tag, negone, data ); 211  for( size_t i = 0; i < data.size(); ++i ) 212  delete data[i]; 213  if( MB_SUCCESS != rval ) 214  { 215  mMB->tag_delete( order_tag ); 216  return error( rval ); 217  } 218  219  rval = handle_order_from_int_tag( order_tag, negone, handle_tag ); 220  if( MB_SUCCESS != rval ) 221  { 222  mMB->tag_delete( order_tag ); 223  return error( rval ); 224  } 225  226  rval = mMB->tag_delete( order_tag ); 227  if( MB_SUCCESS != rval ) return error( rval ); 228  229  return MB_SUCCESS; 230 } 231  232 // Compare function to use for a map keyed on pointers to sorted vectors 233 struct CompSortedVect 234 { 235  bool operator()( const std::vector< EntityHandle >* v1, const std::vector< EntityHandle >* v2 ) const 236  { 237  std::vector< EntityHandle >::const_iterator i1, i2; 238  for( i1 = v1->begin(), i2 = v2->begin(); i1 != v1->end(); ++i1, ++i2 ) 239  { 240  if( i2 == v2->end() || *i1 > *i2 ) 241  return false; 242  else if( *i1 < *i2 ) 243  return true; 244  } 245  return i2 != v2->end(); 246  } 247 }; 248  249 ErrorCode ReorderTool::int_order_from_sets_and_adj( const Range& sets, 250  Tag order_tag, 251  int skip_val, 252  std::vector< std::vector< EntityHandle >* >& revMap ) 253 { 254  ErrorCode rval; 255  256  if( !sets.all_of_type( MBENTITYSET ) ) return MB_TYPE_OUT_OF_RANGE; 257  258  rval = check_tag_type( mMB, order_tag, MB_TYPE_INTEGER, sizeof( int ) );CHKERR; 259  260  // Compare function to use for a map keyed on pointers to sorted vectors 261  CompSortedVect lessthan; 262  // Map from sorted list of handles to index 263  std::map< std::vector< EntityHandle >*, int, CompSortedVect > forMap; 264  std::map< std::vector< EntityHandle >*, int, CompSortedVect >::iterator fiter, fiter2; 265  std::vector< EntityHandle > sharing; // tmp storage for entity 266  267  // for each set 268  for( Range::iterator s = sets.begin(); s != sets.end(); ++s ) 269  { 270  271  // gather up all entities and adjacencies 272  Range tmp, ents, adj[4]; // indexed by dimension 273  for( int dim = 0; dim < 4; ++dim ) 274  { 275  rval = mMB->get_entities_by_dimension( *s, dim, tmp );CHKERR; 276  for( int ldim = 0; ldim < dim; ++ldim ) 277  { 278  rval = mMB->get_adjacencies( tmp, ldim, false, adj[ldim], Interface::UNION );CHKERR; 279  } 280  for( int udim = dim + 1; udim <= 3; ++udim ) 281  { 282  rval = mMB->get_adjacencies( tmp, udim, false, adj[udim], Interface::UNION );CHKERR; 283  } 284  ents.merge( tmp ); 285  tmp.clear(); 286  } 287  for( int dim = 0; dim < 4; ++dim ) 288  { 289  ents.merge( adj[dim] ); 290  adj[dim].clear(); 291  } 292  293  // process each entity 294  for( Range::iterator e = ents.begin(); e != ents.end(); ++e ) 295  { 296  int val; 297  rval = mMB->tag_get_data( order_tag, &*e, 1, &val );CHKERR; 298  299  // If this entity is already in one or more of the sets (either 300  // directly or through adjacency) then get the existing list of 301  // sets and append this set handle (we are iterating over sets 302  // in sorted order, so appending should aways maintain a sorted 303  // list.) 304  sharing.clear(); 305  if( val != skip_val ) 306  { 307  sharing = *revMap[val]; 308  assert( std::lower_bound( sharing.begin(), sharing.end(), *s ) == sharing.end() ); 309  } 310  sharing.push_back( *s ); 311  312  // Check if new sharing list already exists in forward map 313  fiter = forMap.lower_bound( &sharing ); 314  if( fiter == forMap.end() || lessthan( fiter->first, &sharing ) ) 315  { 316  // Add new sharing list to forward and reverse maps. 317  std::vector< EntityHandle >* newvec = new std::vector< EntityHandle >; 318  newvec->swap( sharing ); 319  if( (int)revMap.size() == skip_val ) revMap.push_back( 0 ); 320  fiter2 = 321  forMap.insert( fiter, std::pair< std::vector< EntityHandle >*, int >( newvec, revMap.size() ) ); 322  assert( fiter2 != fiter ); 323  fiter = fiter2; 324  revMap.push_back( newvec ); 325  } 326  327  // Update index on entity 328  val = fiter->second; 329  rval = mMB->tag_set_data( order_tag, &*e, 1, &val );CHKERR; 330  } 331  } 332  333  return MB_SUCCESS; 334 } 335  336 ErrorCode ReorderTool::get_reordered_handles( Tag tag, 337  const Range& old_handles, 338  std::vector< EntityHandle >& new_handles ) 339 { 340  new_handles.resize( old_handles.size() ); 341  ErrorCode rval = mMB->tag_get_data( tag, old_handles, ( new_handles.empty() ) ? NULL : &new_handles[0] );CHKERR; 342  343  Range::const_iterator it1 = old_handles.begin(); 344  std::vector< EntityHandle >::iterator it2 = new_handles.begin(); 345  for( ; it1 != old_handles.end(); ++it1, ++it2 ) 346  if( 0 == *it2 ) *it2 = *it1; 347  348  return MB_SUCCESS; 349 } 350  351 ErrorCode ReorderTool::get_reordered_handles( Tag tag, 352  const std::vector< EntityHandle >& old_handles, 353  std::vector< EntityHandle >& new_handles ) 354 { 355  new_handles.resize( old_handles.size() ); 356  return get_reordered_handles( tag, &old_handles[0], &new_handles[0], old_handles.size() ); 357 } 358  359 ErrorCode ReorderTool::get_reordered_handles( Tag tag, 360  const EntityHandle* old_handles, 361  EntityHandle* new_handles, 362  size_t num_handles ) 363 { 364  ErrorCode rval = mMB->tag_get_data( tag, old_handles, num_handles, new_handles );CHKERR; 365  366  for( size_t i = 0; i < num_handles; ++i ) 367  if( 0 == new_handles[i] ) new_handles[i] = old_handles[i]; 368  369  return MB_SUCCESS; 370 } 371  372 ErrorCode ReorderTool::get_new_handles( Tag tag, Range& old_handles, std::vector< EntityHandle >& newhandles ) 373 { 374  // get new handles for tagged entities 375  newhandles.resize( old_handles.size() ); 376  ErrorCode rval = mMB->tag_get_data( tag, old_handles, ( newhandles.empty() ) ? NULL : &newhandles[0] );CHKERR; 377  378  // remove entities that were not reordered 379  Range::iterator i = old_handles.begin(); 380  size_t w = 0; 381  for( size_t r = 0; r < newhandles.size(); ++r ) 382  { 383  if( 0 != newhandles[r] ) 384  { 385  newhandles[w] = newhandles[r]; 386  ++w; 387  ++i; 388  } 389  else 390  { 391  i = old_handles.erase( i ); 392  } 393  } 394  newhandles.resize( w ); 395  assert( newhandles.size() == old_handles.size() ); 396  return MB_SUCCESS; 397 } 398  399 ErrorCode ReorderTool::reorder_entities( Tag new_handles ) 400 { 401  ErrorCode rval; 402  403  rval = check_tag_type( mMB, new_handles, MB_TYPE_HANDLE, sizeof( EntityHandle ) );CHKERR; 404  EntityHandle defval; 405  rval = mMB->tag_get_default_value( new_handles, &defval );CHKERR; 406  if( 0 != defval ) return error( MB_INDEX_OUT_OF_RANGE ); 407  408  // Can only reorder within same type/connectivity (or vertex/num_coords) 409  // groupings. 410  for( EntityType t = MBVERTEX; t < MBENTITYSET; ++t ) 411  { 412  // Get list of all connectivity lengths (or vertex dimensions) 413  // that exist for type t. 414  TypeSequenceManager& seqs = mMB->sequence_manager()->entity_map( t ); 415  TypeSequenceManager::iterator i; 416  std::set< int > values; 417  for( i = seqs.begin(); i != seqs.end(); ++i ) 418  { 419  EntitySequence* seq = *i; 420  // 0 values per entity implies structured data, which 421  // we cannot reorder. Skip those. 422  if( t == MBVERTEX || 0 < seq->values_per_entity() ) values.insert( seq->values_per_entity() ); 423  } 424  425  // reorder primary data for each (type,size) tuple. 426  std::set< int >::iterator j; 427  for( j = values.begin(); j != values.end(); ++j ) 428  { 429  Range entities; 430  get_entities( t, *j, entities ); 431  std::vector< EntityHandle > handles; 432  rval = get_reordered_handles( new_handles, entities, handles ); 433  UNRECOVERABLE( rval ); 434  435  if( t == MBVERTEX ) 436  { 437  std::vector< double > coords( entities.size() * 3 ); 438  rval = mMB->get_coords( entities, &coords[0] ); 439  UNRECOVERABLE( rval ); 440  rval = mMB->set_coords( &handles[0], handles.size(), &coords[0] ); 441  UNRECOVERABLE( rval ); 442  } 443  else 444  { 445  std::vector< EntityHandle > conn; 446  conn.reserve( entities.size() * *j ); 447  std::vector< EntityHandle > old_handles; 448  old_handles.resize( entities.size() ); 449  std::copy( entities.begin(), entities.end(), old_handles.begin() ); 450  rval = mMB->get_connectivity( &old_handles[0], old_handles.size(), conn, false ); 451  UNRECOVERABLE( rval ); 452  old_handles.clear(); 453  old_handles = conn; 454  rval = get_reordered_handles( new_handles, old_handles, conn ); 455  UNRECOVERABLE( rval ); 456  for( unsigned int h = 0; h < handles.size(); ++h ) 457  { 458  rval = mMB->set_connectivity( handles[h], &conn[h * *j], *j ); 459  UNRECOVERABLE( rval ); 460  } 461  } 462  } 463  } 464  465  // now update tag data 466  std::vector< Tag > tag_handles; 467  mMB->tag_get_tags( tag_handles ); 468  for( size_t i = 0; i < tag_handles.size(); ++i ) 469  { 470  Tag tag = tag_handles[i]; 471  if( tag == new_handles ) // don't mess up mapping from old to new handles 472  continue; 473  474  for( EntityType t = MBVERTEX; t <= MBENTITYSET; ++t ) 475  { 476  rval = reorder_tag_data( t, new_handles, tag ); 477  UNRECOVERABLE( rval ); 478  } 479  } 480  481  rval = update_set_contents( new_handles ); 482  UNRECOVERABLE( rval ); 483  484  return MB_SUCCESS; 485 } 486  487 ErrorCode ReorderTool::reorder_tag_data( EntityType etype, Tag new_handles, Tag tag ) 488 { 489  ErrorCode rval; 490  491  int tagsize; 492  DataType tagtype; 493  rval = mMB->tag_get_data_type( tag, tagtype ); 494  if( MB_SUCCESS != rval ) return error( rval ); 495  if( MB_TYPE_BIT == tagtype ) 496  tagsize = 1; 497  else 498  { 499  rval = mMB->tag_get_bytes( tag, tagsize ); 500  if( MB_VARIABLE_DATA_LENGTH == rval ) 501  tagsize = -1; 502  else if( MB_SUCCESS != rval ) 503  return error( rval ); 504  } 505  506  // we don't re-order set handles, so we don't care about sets 507  // unless the tag contains handles that need to be updated 508  if( MBENTITYSET == etype && MB_TYPE_HANDLE != tagtype ) return MB_SUCCESS; 509  510  // get tagged entities 511  Range old_tagged; 512  rval = mMB->get_entities_by_type_and_tag( 0, etype, &tag, 0, 1, old_tagged ); 513  if( MB_SUCCESS != rval && old_tagged.empty() ) return error( rval ); 514  515  // remove entities that were not reordered, unless the tag 516  // is handle type in which case we need to update the data 517  // for all entities, regardless of reordering. 518  std::vector< EntityHandle > newhandles; 519  if( MB_TYPE_HANDLE == tagtype ) 520  rval = get_reordered_handles( new_handles, old_tagged, newhandles ); 521  else 522  rval = get_new_handles( new_handles, old_tagged, newhandles );CHKERR; 523  524  if( old_tagged.empty() ) return MB_SUCCESS; 525  526  // get copy of all tag data 527  std::vector< unsigned char > buffer; 528  std::vector< const void* > pointers; 529  std::vector< int > sizes; 530  // if variable-length tag 531  if( -1 == tagsize ) 532  { 533  pointers.resize( old_tagged.size() ); 534  sizes.resize( pointers.size() ); 535  rval = mMB->tag_get_by_ptr( tag, old_tagged, &pointers[0], &sizes[0] );CHKERR; 536  int total = std::accumulate( sizes.begin(), sizes.end(), 0 ); 537  DataType dtype; 538  mMB->tag_get_data_type( tag, dtype ); 539  int type_size; 540  switch( dtype ) 541  { 542  case MB_TYPE_INTEGER: 543  type_size = sizeof( int ); 544  break; 545  case MB_TYPE_DOUBLE: 546  type_size = sizeof( double ); 547  break; 548  case MB_TYPE_HANDLE: 549  type_size = sizeof( EntityHandle ); 550  break; 551  case MB_TYPE_BIT: 552  type_size = 1; 553  break; 554  case MB_TYPE_OPAQUE: 555  type_size = 1; 556  break; 557  default: 558  return MB_TYPE_OUT_OF_RANGE; 559  } 560  buffer.resize( total * type_size ); 561  size_t off = 0; 562  for( size_t j = 0; j < pointers.size(); ++j ) 563  { 564  memcpy( &buffer[off], pointers[j], type_size * sizes[j] ); 565  pointers[j] = &buffer[off]; 566  off += sizes[j] * type_size; 567  } 568  } 569  // if fixed-length tag 570  else 571  { 572  buffer.resize( old_tagged.size() * tagsize ); 573  rval = mMB->tag_get_data( tag, old_tagged, &buffer[0] );CHKERR; 574  } 575  576  // if handle tag, update tag values for reordered handles 577  if( MB_TYPE_HANDLE == tagtype ) 578  { 579  assert( !( buffer.size() % sizeof( EntityHandle ) ) ); 580  std::vector< unsigned char > buffer2( buffer.size() ); 581  rval = get_reordered_handles( new_handles, reinterpret_cast< const EntityHandle* >( &buffer[0] ), 582  reinterpret_cast< EntityHandle* >( &buffer2[0] ), 583  buffer.size() / sizeof( EntityHandle ) );CHKERR; 584  // if var-length tag then do not do swap because pointers[] contains pointers 585  // into old buffer 586  if( -1 == tagsize ) 587  memcpy( &buffer[0], &buffer2[0], buffer.size() ); 588  else 589  buffer.swap( buffer2 ); 590  } 591  592  // store re-ordered tag data 593  if( -1 == tagsize ) 594  { 595  rval = mMB->tag_set_by_ptr( tag, &newhandles[0], newhandles.size(), &pointers[0], &sizes[0] ); 596  pointers.clear(); 597  sizes.clear(); 598  buffer.clear(); 599  } 600  else 601  { 602  rval = mMB->tag_set_data( tag, &newhandles[0], newhandles.size(), &buffer[0] ); 603  buffer.clear(); 604  } 605  CHKERR; 606  607  // all permutations should be cyclical, but not all permuted 608  // entities necessarily had tag values, so we might need to delete 609  // tags for some entities 610  std::sort( newhandles.begin(), newhandles.end() ); 611  std::vector< EntityHandle >::iterator k = newhandles.begin(); 612  Range::iterator i = old_tagged.begin(); 613  while( i != old_tagged.end() ) 614  { 615  while( k != newhandles.end() && *k < *i ) 616  ++k; 617  if( k == newhandles.end() ) break; 618  619  if( *i == *k ) // what old_tagged -= newhandles 620  i = old_tagged.erase( i ); 621  else 622  ++i; 623  } 624  625  if( !old_tagged.empty() ) 626  { 627  rval = mMB->tag_delete_data( tag, old_tagged );CHKERR; 628  } 629  630  return MB_SUCCESS; 631 } 632  633 ErrorCode ReorderTool::update_set_contents( Tag nh_tag ) 634 { 635  Range sets; 636  ErrorCode rval = mMB->get_entities_by_type( 0, MBENTITYSET, sets );CHKERR; 637  638  std::vector< EntityHandle > old_handles, new_handles; 639  for( Range::iterator i = sets.begin(); i != sets.end(); ++i ) 640  { 641  // If set is un-ordered... 642  unsigned opts = 0; 643  mMB->get_meshset_options( *i, opts ); 644  if( !( opts & MESHSET_ORDERED ) ) 645  { 646  Range contents; 647  rval = mMB->get_entities_by_handle( *i, contents );CHKERR; 648  649  rval = get_new_handles( nh_tag, contents, new_handles );CHKERR; 650  651  Range replace; 652  std::sort( new_handles.begin(), new_handles.end() ); 653  Range::iterator hint = replace.begin(); 654  for( size_t j = 0; j < new_handles.size(); ++j ) 655  hint = replace.insert( hint, new_handles[j] ); 656  Range common = intersect( contents, replace ); 657  contents -= common; 658  replace -= common; 659  assert( contents.size() == replace.size() ); 660  if( !contents.empty() ) 661  { 662  rval = mMB->remove_entities( *i, contents );CHKERR; 663  rval = mMB->add_entities( *i, replace ); 664  } 665  } 666  667  // If set is ordered... 668  else 669  { 670  // get set contents 671  old_handles.clear(); 672  rval = mMB->get_entities_by_handle( *i, old_handles );CHKERR; 673  674  // get new handles from old contained handles 675  rval = get_reordered_handles( nh_tag, old_handles, new_handles );CHKERR; 676  677  rval = mMB->clear_meshset( &*i, 1 );CHKERR; 678  679  rval = mMB->add_entities( *i, &new_handles[0], new_handles.size() );CHKERR; 680  } 681  } // for each set 682  683  return MB_SUCCESS; 684 } 685  686 } // namespace moab