Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
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 
37 {
38  release_all_data( 0, 0, true );
39 }
40 
42 {
43  return MB_TAG_SPARSE;
44 }
45 
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 
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 );
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 
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 
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;
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 
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 );
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 
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 
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 
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 
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 
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 
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 
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 
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 
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,
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
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
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 
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 
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