Mesh Oriented datABase  (version 5.6.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  if( MB_SUCCESS == get_data_ptr( entity_handle, ptr, false ) )
92  {
93  memcpy( data, ptr, get_size() );
94  return MB_SUCCESS;
95  }
96  else if( get_default_value() )
97  {
98  memcpy( data, get_default_value(), get_size() );
99  return MB_SUCCESS;
100  }
101  else
102  return MB_TAG_NOT_FOUND;
103 }
104 
105 ErrorCode SparseTag::remove_data( Error* /* error */, EntityHandle entity_handle )
106 {
107  MapType::iterator i = mData.find( entity_handle );
108  if( i == mData.end() ) return MB_TAG_NOT_FOUND;
109 
110  mAllocator.destroy( i->second );
111  mData.erase( i );
112 
113  return MB_SUCCESS;
114 }
115 
117  Error* /* error */,
118  const EntityHandle* entities,
119  size_t num_entities,
120  void* data ) const
121 {
122  unsigned char* ptr = reinterpret_cast< unsigned char* >( data );
123  for( size_t i = 0; i < num_entities; ++i, ptr += get_size() )
124  {
125  MB_CHK_ERR( get_data( NULL, entities[i], ptr ) );
126  }
127 
128  return MB_SUCCESS;
129 }
130 
131 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const Range& entities, void* data ) const
132 {
133  unsigned char* ptr = reinterpret_cast< unsigned char* >( data );
135  for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() )
136  {
137  MB_CHK_ERR( get_data( NULL, *i, ptr ) );
138  }
139 
140  return MB_SUCCESS;
141 }
142 
144  Error* /* error */,
145  const EntityHandle* entities,
146  size_t num_entities,
147  const void** pointers,
148  int* data_lengths ) const
149 {
150  if( data_lengths )
151  {
152  int len = get_size();
153  SysUtil::setmem( data_lengths, &len, sizeof( int ), num_entities );
154  }
155 
156  for( size_t i = 0; i < num_entities; ++i, ++pointers )
157  {
158  if( MB_SUCCESS != get_data_ptr( entities[i], *pointers ) )
159  {
160  if( get_default_value() )
161  *pointers = get_default_value();
162  else
163  return MB_TAG_NOT_FOUND;
164  }
165  }
166 
167  return MB_SUCCESS;
168 }
169 
171  Error* /* error */,
172  const Range& entities,
173  const void** pointers,
174  int* data_lengths ) const
175 {
176  if( data_lengths )
177  {
178  int len = get_size();
179  SysUtil::setmem( data_lengths, &len, sizeof( int ), entities.size() );
180  }
181 
183  for( i = entities.begin(); i != entities.end(); ++i, ++pointers )
184  {
185  if( MB_SUCCESS != get_data_ptr( *i, *pointers ) )
186  {
187  if( get_default_value() )
188  *pointers = get_default_value();
189  else
190  return MB_TAG_NOT_FOUND;
191  }
192  }
193 
194  return MB_SUCCESS;
195 }
196 
198  Error* /* error */,
199  const EntityHandle* entities,
200  size_t num_entities,
201  const void* data )
202 {
203  MB_CHK_ERR( seqman->check_valid_entities( NULL, entities, num_entities, true ) );
204 
205  const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
206  for( size_t i = 0; i < num_entities; ++i, ptr += get_size() )
207  MB_CHK_ERR( set_data( NULL, entities[i], ptr ) );
208 
209  return MB_SUCCESS;
210 }
211 
212 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities, const void* data )
213 {
214  MB_CHK_ERR( seqman->check_valid_entities( NULL, entities ) );
215 
216  const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
218  for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() )
219  MB_CHK_ERR( set_data( NULL, *i, ptr ) );
220 
221  return MB_SUCCESS;
222 }
223 
225  Error* /* error */,
226  const EntityHandle* entities,
227  size_t num_entities,
228  void const* const* pointers,
229  const int* lengths )
230 {
231  MB_CHK_ERR( validate_lengths( NULL, lengths, num_entities ) );
232 
233  MB_CHK_ERR( seqman->check_valid_entities( NULL, entities, num_entities, true ) );
234 
235  for( size_t i = 0; i < num_entities; ++i, ++pointers )
236  MB_CHK_ERR( set_data( NULL, entities[i], *pointers ) );
237 
238  return MB_SUCCESS;
239 }
240 
242  Error* /* error */,
243  const Range& entities,
244  void const* const* pointers,
245  const int* lengths )
246 {
247  MB_CHK_ERR( validate_lengths( NULL, lengths, entities.size() ) );
248 
249  MB_CHK_ERR( seqman->check_valid_entities( NULL, entities ) );
250 
252  for( i = entities.begin(); i != entities.end(); ++i, ++pointers )
253  MB_CHK_ERR( set_data( NULL, *i, *pointers ) );
254 
255  return MB_SUCCESS;
256 }
257 
259  Error* /* error */,
260  const EntityHandle* entities,
261  size_t num_entities,
262  const void* value_ptr,
263  int value_len )
264 {
265  if( value_len && value_len != get_size() )
266  {
267  MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
268  << " of size " << value_len );
269  }
270 
271  MB_CHK_ERR( seqman->check_valid_entities( NULL, entities, num_entities, true ) );
272 
273  for( size_t i = 0; i < num_entities; ++i )
274  MB_CHK_ERR( set_data( NULL, entities[i], value_ptr ) );
275 
276  return MB_SUCCESS;
277 }
278 
280  Error* /* error */,
281  const Range& entities,
282  const void* value_ptr,
283  int value_len )
284 {
285  if( value_len && value_len != get_size() )
286  {
287  MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
288  << " of size " << value_len );
289  }
290 
291  MB_CHK_ERR( seqman->check_valid_entities( NULL, entities ) );
292 
294  for( i = entities.begin(); i != entities.end(); ++i )
295  {
296  MB_CHK_ERR( set_data( NULL, *i, value_ptr ) );
297  }
298 
299  return MB_SUCCESS;
300 }
301 
303  Error* /* error */,
304  const EntityHandle* entities,
305  size_t num_entities )
306 {
307  for( size_t i = 0; i < num_entities; ++i )
308  MB_CHK_ERR( remove_data( NULL, entities[i] ) );
309 
310  return MB_SUCCESS;
311 }
312 
313 ErrorCode SparseTag::remove_data( SequenceManager*, Error* /* error */, const Range& entities )
314 {
315  for( Range::const_iterator i = entities.begin(); i != entities.end(); ++i )
316  if( MB_SUCCESS != remove_data( NULL, *i ) ) return MB_TAG_NOT_FOUND;
317 
318  return MB_SUCCESS;
319 }
320 
322  Error* /* error */,
323  Range::iterator& iter,
324  const Range::iterator& end,
325  void*& data_ptr,
326  bool allocate )
327 {
328  // Note: We are asked to returning a block of contiguous storage
329  // for some block of contiguous handles for which the tag
330  // storage is also contiguous. As sparse tag storage is
331  // never contiguous, all we can do is return a pointer to the
332  // data for the first entity.
333 
334  // If asked for nothing, successfully return nothing.
335  if( iter == end ) return MB_SUCCESS;
336 
337  // Note: get_data_ptr will return the default value if the
338  // handle is not found, so test to make sure that the
339  // handle is valid.
340  MB_CHK_ERR( seqman->check_valid_entities( NULL, &*iter, 1 ) );
341 
342  // Get pointer to tag storage for entity pointed to by iter
343  const void* ptr = NULL;
344  if( MB_SUCCESS == get_data_ptr( *iter, ptr ) )
345  data_ptr = const_cast< void* >( ptr );
346  else if( get_default_value() && allocate )
347  {
348  ptr = allocate_data( *iter, mData.end() );
349  data_ptr = const_cast< void* >( ptr );
350  }
351  else
352  {
353  // If allocation was not requested, need to increment the iterator so that
354  // the count can be computed properly
355  if( get_default_value() && !allocate ) ++iter;
356  // return not_found(get_name(), *iter);
357  }
358 
359  // Increment iterator and return
360  ++iter;
361  return MB_SUCCESS;
362 }
363 
364 template < class Container >
365 static inline void get_tagged( const SparseTag::MapType& mData, EntityType type, Container& output_range )
366 {
367  SparseTag::MapType::const_iterator iter;
368  typename Container::iterator hint = output_range.begin();
369  if( MBMAXTYPE == type )
370  {
371  for( iter = mData.begin(); iter != mData.end(); ++iter )
372  hint = output_range.insert( hint, iter->first );
373  }
374  else
375  {
376 #ifdef MOAB_HAVE_UNORDERED_MAP
377  for( iter = mData.begin(); iter != mData.end(); ++iter )
378  if( TYPE_FROM_HANDLE( iter->first ) == type ) hint = output_range.insert( hint, iter->first );
379 #else
380  iter = mData.lower_bound( FIRST_HANDLE( type ) );
381  SparseTag::MapType::const_iterator end = mData.lower_bound( LAST_HANDLE( type ) + 1 );
382  for( ; iter != end; ++iter )
383  hint = output_range.insert( hint, iter->first );
384 #endif
385  }
386 }
387 
388 template < class Container >
389 static inline void get_tagged( const SparseTag::MapType& mData,
390  Range::const_iterator begin,
392  Container& output_range )
393 {
394  typename Container::iterator hint = output_range.begin();
395  for( Range::const_iterator i = begin; i != end; ++i )
396  if( mData.find( *i ) != mData.end() ) hint = output_range.insert( hint, *i );
397 }
398 
399 template < class Container >
400 static inline void get_tagged( const SparseTag::MapType& mData,
401  Container& entities,
402  EntityType type,
403  const Range* intersect )
404 {
405  if( !intersect )
406  get_tagged< Container >( mData, type, entities );
407  else if( MBMAXTYPE == type )
408  get_tagged< Container >( mData, intersect->begin(), intersect->end(), entities );
409  else
410  {
411  std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
412  get_tagged< Container >( mData, r.first, r.second, entities );
413  }
414 }
415 
416 //! Gets all entity handles that match a type and tag
418  Range& output_range,
419  EntityType type,
420  const Range* intersect ) const
421 {
422  get_tagged( mData, output_range, type, intersect );
423  return MB_SUCCESS;
424 }
425 
426 //! Gets all entity handles that match a type and tag
428  size_t& output_count,
429  EntityType type,
430  const Range* intersect ) const
431 {
432  InsertCount counter( output_count );
433  get_tagged( mData, counter, type, intersect );
434  output_count = counter.end();
435  return MB_SUCCESS;
436 }
437 
440  const SequenceManager* seqman,
441 #else
442  const SequenceManager*,
443 #endif
444  Error* /* error */,
445  Range& output_entities,
446  const void* value,
447  int value_bytes,
448  EntityType type,
449  const Range* intersect_entities ) const
450 {
451  if( value_bytes && value_bytes != get_size() )
452  {
453  MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
454  << " of size " << value_bytes );
455  }
456 
457  MapType::const_iterator iter, end;
458 #ifdef MOAB_HAVE_UNORDERED_MAP
459  if( intersect_entities )
460  {
461  std::pair< Range::iterator, Range::iterator > r;
462  if( type == MBMAXTYPE )
463  {
464  r.first = intersect_entities->begin();
465  r.second = intersect_entities->end();
466  }
467  else
468  {
469  r = intersect_entities->equal_range( type );
470  }
471 
472  find_map_values_equal( *this, value, get_size(), r.first, r.second, mData, output_entities );
473  }
474  else if( type == MBMAXTYPE )
475  {
476  find_tag_values_equal( *this, value, get_size(), mData.begin(), mData.end(), output_entities );
477  }
478  else
479  {
480  Range tmp;
481  seqman->get_entities( type, tmp );
482  find_map_values_equal( *this, value, get_size(), tmp.begin(), tmp.end(), mData, output_entities );
483  }
484 #else
485  if( intersect_entities )
486  {
487  for( Range::const_pair_iterator p = intersect_entities->begin(); p != intersect_entities->end(); ++p )
488  {
489  iter = mData.lower_bound( p->first );
490  end = mData.upper_bound( p->second );
491  find_tag_values_equal( *this, value, get_size(), iter, end, output_entities );
492  }
493  }
494  else
495  {
496  if( type == MBMAXTYPE )
497  {
498  iter = mData.begin();
499  end = mData.end();
500  }
501  else
502  {
503  iter = mData.lower_bound( CREATE_HANDLE( type, MB_START_ID ) );
504  end = mData.upper_bound( CREATE_HANDLE( type, MB_END_ID ) );
505  }
506  find_tag_values_equal( *this, value, get_size(), iter, end, output_entities );
507  }
508 #endif
509 
510  return MB_SUCCESS;
511 }
512 
514 {
515  return mData.find( h ) != mData.end();
516 }
517 
518 ErrorCode SparseTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const
519 
520 {
521  per_entity = get_size() + 4 * sizeof( void* );
522  total = ( mData.size() * per_entity ) + sizeof( *this ) + TagInfo::get_memory_use();
523 
524  return MB_SUCCESS;
525 }
526 
527 } // namespace moab