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
SparseTag.cpp
Go to the documentation of this file.
1 /** 2  * MOAB, a Mesh-Oriented datABase, is a software component for creating, 3  * storing and accessing finite element mesh data. 4  * 5  * Copyright 2004 Sandia Corporation. Under the terms of Contract 6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 7  * retains certain rights in this software. 8  * 9  * This library is free software; you can redistribute it and/or 10  * modify it under the terms of the GNU Lesser General Public 11  * License as published by the Free Software Foundation; either 12  * version 2.1 of the License, or (at your option) any later version. 13  * 14  */ 15  16 #include <memory.h> 17 #include <algorithm> 18  19 #include "SparseTag.hpp" 20 #include "moab/Range.hpp" 21 #include "TagCompare.hpp" 22 #include "SysUtil.hpp" 23 #include "SequenceManager.hpp" 24 #include "moab/Error.hpp" 25 #include "moab/ErrorHandler.hpp" 26 #include "moab/CN.hpp" 27  28 namespace moab 29 { 30  31 SparseTag::SparseTag( const char* name, int size, DataType type, const void* default_value ) 32  : TagInfo( name, size, type, default_value, size ) 33 { 34 } 35  36 SparseTag::~SparseTag() 37 { 38  release_all_data( 0, 0, true ); 39 } 40  41 TagType SparseTag::get_storage_type() const 42 { 43  return MB_TAG_SPARSE; 44 } 45  46 ErrorCode SparseTag::release_all_data( SequenceManager*, Error*, bool ) 47 { 48  for( MapType::iterator i = mData.begin(); i != mData.end(); ++i ) 49  mAllocator.destroy( i->second ); 50  mData.clear(); 51  return MB_SUCCESS; 52 } 53  54 ErrorCode SparseTag::set_data( Error*, EntityHandle entity_handle, const void* data ) 55 { 56 #ifdef MOAB_HAVE_UNORDERED_MAP 57  MapType::iterator iter = mData.find( entity_handle ); 58 #else 59  MapType::iterator iter = mData.lower_bound( entity_handle ); 60 #endif 61  62  // Data space already exists 63  if( iter != mData.end() && iter->first == entity_handle ) memcpy( iter->second, data, get_size() ); 64  // We need to make some data space 65  else 66  { 67  void* new_data = allocate_data( entity_handle, iter, false ); 68  memcpy( new_data, data, get_size() ); 69  } 70  71  return MB_SUCCESS; 72 } 73  74 ErrorCode SparseTag::get_data_ptr( EntityHandle entity_handle, const void*& ptr, bool allocate ) const 75 { 76  MapType::const_iterator iter = mData.find( entity_handle ); 77  78  if( iter != mData.end() ) 79  ptr = iter->second; 80  else if( get_default_value() && allocate ) 81  ptr = const_cast< SparseTag* >( this )->allocate_data( entity_handle, iter, allocate ); 82  else 83  return MB_FAILURE; 84  85  return MB_SUCCESS; 86 } 87  88 ErrorCode SparseTag::get_data( Error* /* error */, EntityHandle entity_handle, void* data ) const 89 { 90  const void* ptr = 0; 91  ErrorCode rval = get_data_ptr( entity_handle, ptr, false ); 92  if( MB_SUCCESS == rval ) 93  { 94  memcpy( data, ptr, get_size() ); 95  return rval; 96  } 97  else if( get_default_value() ) 98  { 99  memcpy( data, get_default_value(), get_size() ); 100  return MB_SUCCESS; 101  } 102  else 103  return MB_TAG_NOT_FOUND; 104 } 105  106 ErrorCode SparseTag::remove_data( Error* /* error */, EntityHandle entity_handle ) 107 { 108  MapType::iterator i = mData.find( entity_handle ); 109  if( i == mData.end() ) return MB_TAG_NOT_FOUND; 110  111  mAllocator.destroy( i->second ); 112  mData.erase( i ); 113  114  return MB_SUCCESS; 115 } 116  117 ErrorCode SparseTag::get_data( const SequenceManager*, 118  Error* /* error */, 119  const EntityHandle* entities, 120  size_t num_entities, 121  void* data ) const 122 { 123  ErrorCode rval; 124  unsigned char* ptr = reinterpret_cast< unsigned char* >( data ); 125  for( size_t i = 0; i < num_entities; ++i, ptr += get_size() ) 126  { 127  rval = get_data( NULL, entities[i], ptr ); 128  if( MB_SUCCESS != rval ) return rval; 129  } 130  131  return MB_SUCCESS; 132 } 133  134 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const Range& entities, void* data ) const 135 { 136  ErrorCode rval; 137  unsigned char* ptr = reinterpret_cast< unsigned char* >( data ); 138  Range::const_iterator i; 139  for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() ) 140  { 141  rval = get_data( NULL, *i, ptr ); 142  if( MB_SUCCESS != rval ) return rval; 143  } 144  145  return MB_SUCCESS; 146 } 147  148 ErrorCode SparseTag::get_data( const SequenceManager*, 149  Error* /* error */, 150  const EntityHandle* entities, 151  size_t num_entities, 152  const void** pointers, 153  int* data_lengths ) const 154 { 155  if( data_lengths ) 156  { 157  int len = get_size(); 158  SysUtil::setmem( data_lengths, &len, sizeof( int ), num_entities ); 159  } 160  161  ErrorCode rval = MB_SUCCESS, rval_tmp; 162  for( size_t i = 0; i < num_entities; ++i, ++pointers ) 163  { 164  rval_tmp = get_data_ptr( entities[i], *pointers ); 165  if( MB_SUCCESS != rval_tmp && get_default_value() ) 166  { 167  *pointers = get_default_value(); 168  } 169  else if( MB_SUCCESS != rval_tmp ) 170  { 171  return MB_TAG_NOT_FOUND; 172  } 173  } 174  175  return rval; 176 } 177  178 ErrorCode SparseTag::get_data( const SequenceManager*, 179  Error* /* error */, 180  const Range& entities, 181  const void** pointers, 182  int* data_lengths ) const 183 { 184  if( data_lengths ) 185  { 186  int len = get_size(); 187  SysUtil::setmem( data_lengths, &len, sizeof( int ), entities.size() ); 188  } 189  190  ErrorCode rval = MB_SUCCESS, rval_tmp; 191  Range::const_iterator i; 192  for( i = entities.begin(); i != entities.end(); ++i, ++pointers ) 193  { 194  rval_tmp = get_data_ptr( *i, *pointers ); 195  if( MB_SUCCESS != rval_tmp && get_default_value() ) 196  { 197  *pointers = get_default_value(); 198  } 199  else if( MB_SUCCESS != rval_tmp ) 200  { 201  return MB_TAG_NOT_FOUND; 202  } 203  } 204  205  return rval; 206 } 207  208 ErrorCode SparseTag::set_data( SequenceManager* seqman, 209  Error* /* error */, 210  const EntityHandle* entities, 211  size_t num_entities, 212  const void* data ) 213 { 214  ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval ); 215  216  const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data ); 217  for( size_t i = 0; i < num_entities; ++i, ptr += get_size() ) 218  { 219  rval = set_data( NULL, entities[i], ptr );MB_CHK_ERR( rval ); 220  } 221  222  return MB_SUCCESS; 223 } 224  225 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities, const void* data ) 226 { 227  ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval ); 228  229  const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data ); 230  Range::const_iterator i; 231  for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() ) 232  if( MB_SUCCESS != ( rval = set_data( NULL, *i, ptr ) ) ) return rval; 233  234  return MB_SUCCESS; 235 } 236  237 ErrorCode SparseTag::set_data( SequenceManager* seqman, 238  Error* /* error */, 239  const EntityHandle* entities, 240  size_t num_entities, 241  void const* const* pointers, 242  const int* lengths ) 243 { 244  ErrorCode rval = validate_lengths( NULL, lengths, num_entities );MB_CHK_ERR( rval ); 245  246  rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval ); 247  248  for( size_t i = 0; i < num_entities; ++i, ++pointers ) 249  { 250  rval = set_data( NULL, entities[i], *pointers );MB_CHK_ERR( rval ); 251  } 252  253  return MB_SUCCESS; 254 } 255  256 ErrorCode SparseTag::set_data( SequenceManager* seqman, 257  Error* /* error */, 258  const Range& entities, 259  void const* const* pointers, 260  const int* lengths ) 261 { 262  ErrorCode rval = validate_lengths( NULL, lengths, entities.size() );MB_CHK_ERR( rval ); 263  264  rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval ); 265  266  Range::const_iterator i; 267  for( i = entities.begin(); i != entities.end(); ++i, ++pointers ) 268  { 269  rval = set_data( NULL, *i, *pointers );MB_CHK_ERR( rval ); 270  } 271  272  return MB_SUCCESS; 273 } 274  275 ErrorCode SparseTag::clear_data( SequenceManager* seqman, 276  Error* /* error */, 277  const EntityHandle* entities, 278  size_t num_entities, 279  const void* value_ptr, 280  int value_len ) 281 { 282  if( value_len && value_len != get_size() ) 283  { 284  MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name() 285  << " of size " << value_len ); 286  } 287  288  ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval ); 289  290  for( size_t i = 0; i < num_entities; ++i ) 291  { 292  rval = set_data( NULL, entities[i], value_ptr );MB_CHK_ERR( rval ); 293  } 294  295  return MB_SUCCESS; 296 } 297  298 ErrorCode SparseTag::clear_data( SequenceManager* seqman, 299  Error* /* error */, 300  const Range& entities, 301  const void* value_ptr, 302  int value_len ) 303 { 304  if( value_len && value_len != get_size() ) 305  { 306  MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name() 307  << " of size " << value_len ); 308  } 309  310  ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval ); 311  312  Range::const_iterator i; 313  for( i = entities.begin(); i != entities.end(); ++i ) 314  { 315  rval = set_data( NULL, *i, value_ptr );MB_CHK_ERR( rval ); 316  } 317  318  return MB_SUCCESS; 319 } 320  321 ErrorCode SparseTag::remove_data( SequenceManager*, 322  Error* /* error */, 323  const EntityHandle* entities, 324  size_t num_entities ) 325 { 326  ErrorCode rval; 327  for( size_t i = 0; i < num_entities; ++i ) 328  { 329  rval = remove_data( NULL, entities[i] ); 330  if( MB_SUCCESS != rval ) return rval; 331  } 332  333  return MB_SUCCESS; 334 } 335  336 ErrorCode SparseTag::remove_data( SequenceManager*, Error* /* error */, const Range& entities ) 337 { 338  for( Range::const_iterator i = entities.begin(); i != entities.end(); ++i ) 339  if( MB_SUCCESS != remove_data( NULL, *i ) ) return MB_TAG_NOT_FOUND; 340  341  return MB_SUCCESS; 342 } 343  344 ErrorCode SparseTag::tag_iterate( SequenceManager* seqman, 345  Error* /* error */, 346  Range::iterator& iter, 347  const Range::iterator& end, 348  void*& data_ptr, 349  bool allocate ) 350 { 351  // Note: We are asked to returning a block of contiguous storage 352  // for some block of contiguous handles for which the tag 353  // storage is also contiguous. As sparse tag storage is 354  // never contiguous, all we can do is return a pointer to the 355  // data for the first entity. 356  357  // If asked for nothing, successfully return nothing. 358  if( iter == end ) return MB_SUCCESS; 359  360  // Note: get_data_ptr will return the default value if the 361  // handle is not found, so test to make sure that the 362  // handle is valid. 363  ErrorCode rval = seqman->check_valid_entities( NULL, &*iter, 1 );MB_CHK_ERR( rval ); 364  365  // Get pointer to tag storage for entity pointed to by iter 366  const void* ptr = NULL; 367  rval = get_data_ptr( *iter, ptr ); 368  if( MB_SUCCESS == rval ) 369  data_ptr = const_cast< void* >( ptr ); 370  else if( get_default_value() && allocate ) 371  { 372  ptr = allocate_data( *iter, mData.end() ); 373  data_ptr = const_cast< void* >( ptr ); 374  } 375  else 376  { 377  // If allocation was not requested, need to increment the iterator so that 378  // the count can be computed properly 379  if( get_default_value() && !allocate ) ++iter; 380  // return not_found(get_name(), *iter); 381  } 382  383  // Increment iterator and return 384  ++iter; 385  return MB_SUCCESS; 386 } 387  388 template < class Container > 389 static inline void get_tagged( const SparseTag::MapType& mData, EntityType type, Container& output_range ) 390 { 391  SparseTag::MapType::const_iterator iter; 392  typename Container::iterator hint = output_range.begin(); 393  if( MBMAXTYPE == type ) 394  { 395  for( iter = mData.begin(); iter != mData.end(); ++iter ) 396  hint = output_range.insert( hint, iter->first ); 397  } 398  else 399  { 400 #ifdef MOAB_HAVE_UNORDERED_MAP 401  for( iter = mData.begin(); iter != mData.end(); ++iter ) 402  if( TYPE_FROM_HANDLE( iter->first ) == type ) hint = output_range.insert( hint, iter->first ); 403 #else 404  iter = mData.lower_bound( FIRST_HANDLE( type ) ); 405  SparseTag::MapType::const_iterator end = mData.lower_bound( LAST_HANDLE( type ) + 1 ); 406  for( ; iter != end; ++iter ) 407  hint = output_range.insert( hint, iter->first ); 408 #endif 409  } 410 } 411  412 template < class Container > 413 static inline void get_tagged( const SparseTag::MapType& mData, 414  Range::const_iterator begin, 415  Range::const_iterator end, 416  Container& output_range ) 417 { 418  typename Container::iterator hint = output_range.begin(); 419  for( Range::const_iterator i = begin; i != end; ++i ) 420  if( mData.find( *i ) != mData.end() ) hint = output_range.insert( hint, *i ); 421 } 422  423 template < class Container > 424 static inline void get_tagged( const SparseTag::MapType& mData, 425  Container& entities, 426  EntityType type, 427  const Range* intersect ) 428 { 429  if( !intersect ) 430  get_tagged< Container >( mData, type, entities ); 431  else if( MBMAXTYPE == type ) 432  get_tagged< Container >( mData, intersect->begin(), intersect->end(), entities ); 433  else 434  { 435  std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type ); 436  get_tagged< Container >( mData, r.first, r.second, entities ); 437  } 438 } 439  440 //! Gets all entity handles that match a type and tag 441 ErrorCode SparseTag::get_tagged_entities( const SequenceManager*, 442  Range& output_range, 443  EntityType type, 444  const Range* intersect ) const 445 { 446  get_tagged( mData, output_range, type, intersect ); 447  return MB_SUCCESS; 448 } 449  450 //! Gets all entity handles that match a type and tag 451 ErrorCode SparseTag::num_tagged_entities( const SequenceManager*, 452  size_t& output_count, 453  EntityType type, 454  const Range* intersect ) const 455 { 456  InsertCount counter( output_count ); 457  get_tagged( mData, counter, type, intersect ); 458  output_count = counter.end(); 459  return MB_SUCCESS; 460 } 461  462 ErrorCode SparseTag::find_entities_with_value( 463 #ifdef MOAB_HAVE_UNORDERED_MAP 464  const SequenceManager* seqman, 465 #else 466  const SequenceManager*, 467 #endif 468  Error* /* error */, 469  Range& output_entities, 470  const void* value, 471  int value_bytes, 472  EntityType type, 473  const Range* intersect_entities ) const 474 { 475  if( value_bytes && value_bytes != get_size() ) 476  { 477  MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name() 478  << " of size " << value_bytes ); 479  } 480  481  MapType::const_iterator iter, end; 482 #ifdef MOAB_HAVE_UNORDERED_MAP 483  if( intersect_entities ) 484  { 485  std::pair< Range::iterator, Range::iterator > r; 486  if( type == MBMAXTYPE ) 487  { 488  r.first = intersect_entities->begin(); 489  r.second = intersect_entities->end(); 490  } 491  else 492  { 493  r = intersect_entities->equal_range( type ); 494  } 495  496  find_map_values_equal( *this, value, get_size(), r.first, r.second, mData, output_entities ); 497  } 498  else if( type == MBMAXTYPE ) 499  { 500  find_tag_values_equal( *this, value, get_size(), mData.begin(), mData.end(), output_entities ); 501  } 502  else 503  { 504  Range tmp; 505  seqman->get_entities( type, tmp ); 506  find_map_values_equal( *this, value, get_size(), tmp.begin(), tmp.end(), mData, output_entities ); 507  } 508 #else 509  if( intersect_entities ) 510  { 511  for( Range::const_pair_iterator p = intersect_entities->begin(); p != intersect_entities->end(); ++p ) 512  { 513  iter = mData.lower_bound( p->first ); 514  end = mData.upper_bound( p->second ); 515  find_tag_values_equal( *this, value, get_size(), iter, end, output_entities ); 516  } 517  } 518  else 519  { 520  if( type == MBMAXTYPE ) 521  { 522  iter = mData.begin(); 523  end = mData.end(); 524  } 525  else 526  { 527  iter = mData.lower_bound( CREATE_HANDLE( type, MB_START_ID ) ); 528  end = mData.upper_bound( CREATE_HANDLE( type, MB_END_ID ) ); 529  } 530  find_tag_values_equal( *this, value, get_size(), iter, end, output_entities ); 531  } 532 #endif 533  534  return MB_SUCCESS; 535 } 536  537 bool SparseTag::is_tagged( const SequenceManager*, EntityHandle h ) const 538 { 539  return mData.find( h ) != mData.end(); 540 } 541  542 ErrorCode SparseTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const 543  544 { 545  per_entity = get_size() + 4 * sizeof( void* ); 546  total = ( mData.size() * per_entity ) + sizeof( *this ) + TagInfo::get_memory_use(); 547  548  return MB_SUCCESS; 549 } 550  551 } // namespace moab