Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /** 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00007 * retains certain rights in this software. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 */ 00015 00016 #include <memory.h> 00017 #include <algorithm> 00018 00019 #include "SparseTag.hpp" 00020 #include "moab/Range.hpp" 00021 #include "TagCompare.hpp" 00022 #include "SysUtil.hpp" 00023 #include "SequenceManager.hpp" 00024 #include "moab/Error.hpp" 00025 #include "moab/ErrorHandler.hpp" 00026 #include "moab/CN.hpp" 00027 00028 namespace moab 00029 { 00030 00031 SparseTag::SparseTag( const char* name, int size, DataType type, const void* default_value ) 00032 : TagInfo( name, size, type, default_value, size ) 00033 { 00034 } 00035 00036 SparseTag::~SparseTag() 00037 { 00038 release_all_data( 0, 0, true ); 00039 } 00040 00041 TagType SparseTag::get_storage_type() const 00042 { 00043 return MB_TAG_SPARSE; 00044 } 00045 00046 ErrorCode SparseTag::release_all_data( SequenceManager*, Error*, bool ) 00047 { 00048 for( MapType::iterator i = mData.begin(); i != mData.end(); ++i ) 00049 mAllocator.destroy( i->second ); 00050 mData.clear(); 00051 return MB_SUCCESS; 00052 } 00053 00054 ErrorCode SparseTag::set_data( Error*, EntityHandle entity_handle, const void* data ) 00055 { 00056 #ifdef MOAB_HAVE_UNORDERED_MAP 00057 MapType::iterator iter = mData.find( entity_handle ); 00058 #else 00059 MapType::iterator iter = mData.lower_bound( entity_handle ); 00060 #endif 00061 00062 // Data space already exists 00063 if( iter != mData.end() && iter->first == entity_handle ) memcpy( iter->second, data, get_size() ); 00064 // We need to make some data space 00065 else 00066 { 00067 void* new_data = allocate_data( entity_handle, iter, false ); 00068 memcpy( new_data, data, get_size() ); 00069 } 00070 00071 return MB_SUCCESS; 00072 } 00073 00074 ErrorCode SparseTag::get_data_ptr( EntityHandle entity_handle, const void*& ptr, bool allocate ) const 00075 { 00076 MapType::const_iterator iter = mData.find( entity_handle ); 00077 00078 if( iter != mData.end() ) 00079 ptr = iter->second; 00080 else if( get_default_value() && allocate ) 00081 ptr = const_cast< SparseTag* >( this )->allocate_data( entity_handle, iter, allocate ); 00082 else 00083 return MB_FAILURE; 00084 00085 return MB_SUCCESS; 00086 } 00087 00088 ErrorCode SparseTag::get_data( Error* /* error */, EntityHandle entity_handle, void* data ) const 00089 { 00090 const void* ptr = 0; 00091 ErrorCode rval = get_data_ptr( entity_handle, ptr, false ); 00092 if( MB_SUCCESS == rval ) 00093 { 00094 memcpy( data, ptr, get_size() ); 00095 return rval; 00096 } 00097 else if( get_default_value() ) 00098 { 00099 memcpy( data, get_default_value(), get_size() ); 00100 return MB_SUCCESS; 00101 } 00102 else 00103 return MB_TAG_NOT_FOUND; 00104 } 00105 00106 ErrorCode SparseTag::remove_data( Error* /* error */, EntityHandle entity_handle ) 00107 { 00108 MapType::iterator i = mData.find( entity_handle ); 00109 if( i == mData.end() ) return MB_TAG_NOT_FOUND; 00110 00111 mAllocator.destroy( i->second ); 00112 mData.erase( i ); 00113 00114 return MB_SUCCESS; 00115 } 00116 00117 ErrorCode SparseTag::get_data( const SequenceManager*, 00118 Error* /* error */, 00119 const EntityHandle* entities, 00120 size_t num_entities, 00121 void* data ) const 00122 { 00123 ErrorCode rval; 00124 unsigned char* ptr = reinterpret_cast< unsigned char* >( data ); 00125 for( size_t i = 0; i < num_entities; ++i, ptr += get_size() ) 00126 { 00127 rval = get_data( NULL, entities[i], ptr ); 00128 if( MB_SUCCESS != rval ) return rval; 00129 } 00130 00131 return MB_SUCCESS; 00132 } 00133 00134 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const Range& entities, void* data ) const 00135 { 00136 ErrorCode rval; 00137 unsigned char* ptr = reinterpret_cast< unsigned char* >( data ); 00138 Range::const_iterator i; 00139 for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() ) 00140 { 00141 rval = get_data( NULL, *i, ptr ); 00142 if( MB_SUCCESS != rval ) return rval; 00143 } 00144 00145 return MB_SUCCESS; 00146 } 00147 00148 ErrorCode SparseTag::get_data( const SequenceManager*, 00149 Error* /* error */, 00150 const EntityHandle* entities, 00151 size_t num_entities, 00152 const void** pointers, 00153 int* data_lengths ) const 00154 { 00155 if( data_lengths ) 00156 { 00157 int len = get_size(); 00158 SysUtil::setmem( data_lengths, &len, sizeof( int ), num_entities ); 00159 } 00160 00161 ErrorCode rval = MB_SUCCESS, rval_tmp; 00162 for( size_t i = 0; i < num_entities; ++i, ++pointers ) 00163 { 00164 rval_tmp = get_data_ptr( entities[i], *pointers ); 00165 if( MB_SUCCESS != rval_tmp && get_default_value() ) 00166 { 00167 *pointers = get_default_value(); 00168 } 00169 else if( MB_SUCCESS != rval_tmp ) 00170 { 00171 return MB_TAG_NOT_FOUND; 00172 } 00173 } 00174 00175 return rval; 00176 } 00177 00178 ErrorCode SparseTag::get_data( const SequenceManager*, 00179 Error* /* error */, 00180 const Range& entities, 00181 const void** pointers, 00182 int* data_lengths ) const 00183 { 00184 if( data_lengths ) 00185 { 00186 int len = get_size(); 00187 SysUtil::setmem( data_lengths, &len, sizeof( int ), entities.size() ); 00188 } 00189 00190 ErrorCode rval = MB_SUCCESS, rval_tmp; 00191 Range::const_iterator i; 00192 for( i = entities.begin(); i != entities.end(); ++i, ++pointers ) 00193 { 00194 rval_tmp = get_data_ptr( *i, *pointers ); 00195 if( MB_SUCCESS != rval_tmp && get_default_value() ) 00196 { 00197 *pointers = get_default_value(); 00198 } 00199 else if( MB_SUCCESS != rval_tmp ) 00200 { 00201 return MB_TAG_NOT_FOUND; 00202 } 00203 } 00204 00205 return rval; 00206 } 00207 00208 ErrorCode SparseTag::set_data( SequenceManager* seqman, 00209 Error* /* error */, 00210 const EntityHandle* entities, 00211 size_t num_entities, 00212 const void* data ) 00213 { 00214 ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval ); 00215 00216 const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data ); 00217 for( size_t i = 0; i < num_entities; ++i, ptr += get_size() ) 00218 { 00219 rval = set_data( NULL, entities[i], ptr );MB_CHK_ERR( rval ); 00220 } 00221 00222 return MB_SUCCESS; 00223 } 00224 00225 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities, const void* data ) 00226 { 00227 ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval ); 00228 00229 const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data ); 00230 Range::const_iterator i; 00231 for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() ) 00232 if( MB_SUCCESS != ( rval = set_data( NULL, *i, ptr ) ) ) return rval; 00233 00234 return MB_SUCCESS; 00235 } 00236 00237 ErrorCode SparseTag::set_data( SequenceManager* seqman, 00238 Error* /* error */, 00239 const EntityHandle* entities, 00240 size_t num_entities, 00241 void const* const* pointers, 00242 const int* lengths ) 00243 { 00244 ErrorCode rval = validate_lengths( NULL, lengths, num_entities );MB_CHK_ERR( rval ); 00245 00246 rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval ); 00247 00248 for( size_t i = 0; i < num_entities; ++i, ++pointers ) 00249 { 00250 rval = set_data( NULL, entities[i], *pointers );MB_CHK_ERR( rval ); 00251 } 00252 00253 return MB_SUCCESS; 00254 } 00255 00256 ErrorCode SparseTag::set_data( SequenceManager* seqman, 00257 Error* /* error */, 00258 const Range& entities, 00259 void const* const* pointers, 00260 const int* lengths ) 00261 { 00262 ErrorCode rval = validate_lengths( NULL, lengths, entities.size() );MB_CHK_ERR( rval ); 00263 00264 rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval ); 00265 00266 Range::const_iterator i; 00267 for( i = entities.begin(); i != entities.end(); ++i, ++pointers ) 00268 { 00269 rval = set_data( NULL, *i, *pointers );MB_CHK_ERR( rval ); 00270 } 00271 00272 return MB_SUCCESS; 00273 } 00274 00275 ErrorCode SparseTag::clear_data( SequenceManager* seqman, 00276 Error* /* error */, 00277 const EntityHandle* entities, 00278 size_t num_entities, 00279 const void* value_ptr, 00280 int value_len ) 00281 { 00282 if( value_len && value_len != get_size() ) 00283 { 00284 MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name() 00285 << " of size " << value_len ); 00286 } 00287 00288 ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval ); 00289 00290 for( size_t i = 0; i < num_entities; ++i ) 00291 { 00292 rval = set_data( NULL, entities[i], value_ptr );MB_CHK_ERR( rval ); 00293 } 00294 00295 return MB_SUCCESS; 00296 } 00297 00298 ErrorCode SparseTag::clear_data( SequenceManager* seqman, 00299 Error* /* error */, 00300 const Range& entities, 00301 const void* value_ptr, 00302 int value_len ) 00303 { 00304 if( value_len && value_len != get_size() ) 00305 { 00306 MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name() 00307 << " of size " << value_len ); 00308 } 00309 00310 ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval ); 00311 00312 Range::const_iterator i; 00313 for( i = entities.begin(); i != entities.end(); ++i ) 00314 { 00315 rval = set_data( NULL, *i, value_ptr );MB_CHK_ERR( rval ); 00316 } 00317 00318 return MB_SUCCESS; 00319 } 00320 00321 ErrorCode SparseTag::remove_data( SequenceManager*, 00322 Error* /* error */, 00323 const EntityHandle* entities, 00324 size_t num_entities ) 00325 { 00326 ErrorCode rval; 00327 for( size_t i = 0; i < num_entities; ++i ) 00328 { 00329 rval = remove_data( NULL, entities[i] ); 00330 if( MB_SUCCESS != rval ) return rval; 00331 } 00332 00333 return MB_SUCCESS; 00334 } 00335 00336 ErrorCode SparseTag::remove_data( SequenceManager*, Error* /* error */, const Range& entities ) 00337 { 00338 for( Range::const_iterator i = entities.begin(); i != entities.end(); ++i ) 00339 if( MB_SUCCESS != remove_data( NULL, *i ) ) return MB_TAG_NOT_FOUND; 00340 00341 return MB_SUCCESS; 00342 } 00343 00344 ErrorCode SparseTag::tag_iterate( SequenceManager* seqman, 00345 Error* /* error */, 00346 Range::iterator& iter, 00347 const Range::iterator& end, 00348 void*& data_ptr, 00349 bool allocate ) 00350 { 00351 // Note: We are asked to returning a block of contiguous storage 00352 // for some block of contiguous handles for which the tag 00353 // storage is also contiguous. As sparse tag storage is 00354 // never contiguous, all we can do is return a pointer to the 00355 // data for the first entity. 00356 00357 // If asked for nothing, successfully return nothing. 00358 if( iter == end ) return MB_SUCCESS; 00359 00360 // Note: get_data_ptr will return the default value if the 00361 // handle is not found, so test to make sure that the 00362 // handle is valid. 00363 ErrorCode rval = seqman->check_valid_entities( NULL, &*iter, 1 );MB_CHK_ERR( rval ); 00364 00365 // Get pointer to tag storage for entity pointed to by iter 00366 const void* ptr = NULL; 00367 rval = get_data_ptr( *iter, ptr ); 00368 if( MB_SUCCESS == rval ) 00369 data_ptr = const_cast< void* >( ptr ); 00370 else if( get_default_value() && allocate ) 00371 { 00372 ptr = allocate_data( *iter, mData.end() ); 00373 data_ptr = const_cast< void* >( ptr ); 00374 } 00375 else 00376 { 00377 // If allocation was not requested, need to increment the iterator so that 00378 // the count can be computed properly 00379 if( get_default_value() && !allocate ) ++iter; 00380 // return not_found(get_name(), *iter); 00381 } 00382 00383 // Increment iterator and return 00384 ++iter; 00385 return MB_SUCCESS; 00386 } 00387 00388 template < class Container > 00389 static inline void get_tagged( const SparseTag::MapType& mData, EntityType type, Container& output_range ) 00390 { 00391 SparseTag::MapType::const_iterator iter; 00392 typename Container::iterator hint = output_range.begin(); 00393 if( MBMAXTYPE == type ) 00394 { 00395 for( iter = mData.begin(); iter != mData.end(); ++iter ) 00396 hint = output_range.insert( hint, iter->first ); 00397 } 00398 else 00399 { 00400 #ifdef MOAB_HAVE_UNORDERED_MAP 00401 for( iter = mData.begin(); iter != mData.end(); ++iter ) 00402 if( TYPE_FROM_HANDLE( iter->first ) == type ) hint = output_range.insert( hint, iter->first ); 00403 #else 00404 iter = mData.lower_bound( FIRST_HANDLE( type ) ); 00405 SparseTag::MapType::const_iterator end = mData.lower_bound( LAST_HANDLE( type ) + 1 ); 00406 for( ; iter != end; ++iter ) 00407 hint = output_range.insert( hint, iter->first ); 00408 #endif 00409 } 00410 } 00411 00412 template < class Container > 00413 static inline void get_tagged( const SparseTag::MapType& mData, 00414 Range::const_iterator begin, 00415 Range::const_iterator end, 00416 Container& output_range ) 00417 { 00418 typename Container::iterator hint = output_range.begin(); 00419 for( Range::const_iterator i = begin; i != end; ++i ) 00420 if( mData.find( *i ) != mData.end() ) hint = output_range.insert( hint, *i ); 00421 } 00422 00423 template < class Container > 00424 static inline void get_tagged( const SparseTag::MapType& mData, 00425 Container& entities, 00426 EntityType type, 00427 const Range* intersect ) 00428 { 00429 if( !intersect ) 00430 get_tagged< Container >( mData, type, entities ); 00431 else if( MBMAXTYPE == type ) 00432 get_tagged< Container >( mData, intersect->begin(), intersect->end(), entities ); 00433 else 00434 { 00435 std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type ); 00436 get_tagged< Container >( mData, r.first, r.second, entities ); 00437 } 00438 } 00439 00440 //! Gets all entity handles that match a type and tag 00441 ErrorCode SparseTag::get_tagged_entities( const SequenceManager*, 00442 Range& output_range, 00443 EntityType type, 00444 const Range* intersect ) const 00445 { 00446 get_tagged( mData, output_range, type, intersect ); 00447 return MB_SUCCESS; 00448 } 00449 00450 //! Gets all entity handles that match a type and tag 00451 ErrorCode SparseTag::num_tagged_entities( const SequenceManager*, 00452 size_t& output_count, 00453 EntityType type, 00454 const Range* intersect ) const 00455 { 00456 InsertCount counter( output_count ); 00457 get_tagged( mData, counter, type, intersect ); 00458 output_count = counter.end(); 00459 return MB_SUCCESS; 00460 } 00461 00462 ErrorCode SparseTag::find_entities_with_value( 00463 #ifdef MOAB_HAVE_UNORDERED_MAP 00464 const SequenceManager* seqman, 00465 #else 00466 const SequenceManager*, 00467 #endif 00468 Error* /* error */, 00469 Range& output_entities, 00470 const void* value, 00471 int value_bytes, 00472 EntityType type, 00473 const Range* intersect_entities ) const 00474 { 00475 if( value_bytes && value_bytes != get_size() ) 00476 { 00477 MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name() 00478 << " of size " << value_bytes ); 00479 } 00480 00481 MapType::const_iterator iter, end; 00482 #ifdef MOAB_HAVE_UNORDERED_MAP 00483 if( intersect_entities ) 00484 { 00485 std::pair< Range::iterator, Range::iterator > r; 00486 if( type == MBMAXTYPE ) 00487 { 00488 r.first = intersect_entities->begin(); 00489 r.second = intersect_entities->end(); 00490 } 00491 else 00492 { 00493 r = intersect_entities->equal_range( type ); 00494 } 00495 00496 find_map_values_equal( *this, value, get_size(), r.first, r.second, mData, output_entities ); 00497 } 00498 else if( type == MBMAXTYPE ) 00499 { 00500 find_tag_values_equal( *this, value, get_size(), mData.begin(), mData.end(), output_entities ); 00501 } 00502 else 00503 { 00504 Range tmp; 00505 seqman->get_entities( type, tmp ); 00506 find_map_values_equal( *this, value, get_size(), tmp.begin(), tmp.end(), mData, output_entities ); 00507 } 00508 #else 00509 if( intersect_entities ) 00510 { 00511 for( Range::const_pair_iterator p = intersect_entities->begin(); p != intersect_entities->end(); ++p ) 00512 { 00513 iter = mData.lower_bound( p->first ); 00514 end = mData.upper_bound( p->second ); 00515 find_tag_values_equal( *this, value, get_size(), iter, end, output_entities ); 00516 } 00517 } 00518 else 00519 { 00520 if( type == MBMAXTYPE ) 00521 { 00522 iter = mData.begin(); 00523 end = mData.end(); 00524 } 00525 else 00526 { 00527 iter = mData.lower_bound( CREATE_HANDLE( type, MB_START_ID ) ); 00528 end = mData.upper_bound( CREATE_HANDLE( type, MB_END_ID ) ); 00529 } 00530 find_tag_values_equal( *this, value, get_size(), iter, end, output_entities ); 00531 } 00532 #endif 00533 00534 return MB_SUCCESS; 00535 } 00536 00537 bool SparseTag::is_tagged( const SequenceManager*, EntityHandle h ) const 00538 { 00539 return mData.find( h ) != mData.end(); 00540 } 00541 00542 ErrorCode SparseTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const 00543 00544 { 00545 per_entity = get_size() + 4 * sizeof( void* ); 00546 total = ( mData.size() * per_entity ) + sizeof( *this ) + TagInfo::get_memory_use(); 00547 00548 return MB_SUCCESS; 00549 } 00550 00551 } // namespace moab