Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
DenseTag.cpp
Go to the documentation of this file.
1 /** \file DenseTag.cpp
2  * \author Jason Kraftcheck
3  * \date 2010-12-14
4  */
5 
6 #include "DenseTag.hpp"
7 #include "moab/Range.hpp"
8 #include "TagCompare.hpp"
9 #include "SysUtil.hpp"
10 #include "SequenceManager.hpp"
11 #include "SequenceData.hpp"
12 #include "moab/Error.hpp"
13 #include "moab/ErrorHandler.hpp"
14 #include "moab/CN.hpp"
15 #include <utility>
16 
17 namespace moab
18 {
19 
20 inline static ErrorCode not_found( const std::string& /*name*/, EntityHandle /*h*/ )
21 {
22  // MB_TAG_NOT_FOUND could be a non-error condition, do not call MB_SET_ERR on it
23 #if 0
24  if (h)
25  fprintf(stderr, "[Warning]: No dense tag %s value for %s %ld\n",
26  name.c_str(),
28  (unsigned long)ID_FROM_HANDLE(h));
29  else
30  fprintf(stderr, "[Warning]: No dense tag %s value for root set\n", name.c_str());
31 #endif
32 
33  return MB_TAG_NOT_FOUND;
34 }
35 
36 inline static ErrorCode ent_not_found( const std::string& /*name*/, EntityHandle /*h*/ )
37 {
38  // MB_ENTITY_NOT_FOUND could be a non-error condition, do not call MB_SET_ERR on it
39 #if 0
40  fprintf(
41  stderr,
42  "[Warning]: Invalid entity handle setting tag %s: %s %ld\n",
43  name.c_str(),
45  (unsigned long)ID_FROM_HANDLE(h)
46  );
47 #endif
48 
49  return MB_ENTITY_NOT_FOUND;
50 }
51 
52 DenseTag::DenseTag( int index, const char* name, int size, DataType type, const void* default_value )
53  : TagInfo( name, size, type, default_value, size ), mySequenceArray( index ), meshValue( 0 )
54 {
55 }
56 
58 {
59  return MB_TAG_DENSE;
60 }
61 
63  Error* /* error */,
64  const char* name,
65  int bytes,
66  DataType type,
67  const void* default_value )
68 {
69  if( bytes < 1 ) return 0;
70 
71  int index;
72  if( MB_SUCCESS != seqman->reserve_tag_array( NULL, bytes, index ) ) return 0;
73 
74  return new DenseTag( index, name, bytes, type, default_value );
75 }
76 
78 {
79  assert( mySequenceArray < 0 );
80  delete[] meshValue;
81 }
82 
83 ErrorCode DenseTag::release_all_data( SequenceManager* seqman, Error* /* error */, bool delete_pending )
84 {
85  ErrorCode result = seqman->release_tag_array( NULL, mySequenceArray, delete_pending );
86  if( MB_SUCCESS == result && delete_pending ) mySequenceArray = -1;
87  return result;
88 }
89 
91  Error* /* error */,
92  EntityHandle h,
93  const unsigned char* const& ptr,
94  size_t& count ) const
95 {
96  // cast away the const-ness; do we really want to do this?
97  // probably we are not calling this anywhere;
98  // clang compiler found this
99  return get_array_private( seqman, NULL, h, const_cast< const unsigned char*& >( ptr ), count );
100 }
101 
103  Error* /* error */,
104  EntityHandle h,
105  const unsigned char*& ptr,
106  size_t& count ) const
107 {
108  const EntitySequence* seq = 0;
109  ErrorCode rval = seqman->find( h, seq );
110  if( MB_SUCCESS != rval )
111  {
112  if( !h )
113  { // Root set
114  ptr = meshValue;
115  count = 1;
116  return MB_SUCCESS;
117  }
118  else
119  { // Not root set
120  ptr = 0;
121  count = 0;
122  return ent_not_found( get_name(), h );
123  }
124  }
125 
126  const void* mem = seq->data()->get_tag_data( mySequenceArray );
127  ptr = reinterpret_cast< const unsigned char* >( mem );
128  count = seq->data()->end_handle() - h + 1;
129  if( ptr ) ptr += get_size() * ( h - seq->data()->start_handle() );
130 
131  return MB_SUCCESS;
132 }
133 
134 ErrorCode DenseTag::get_array( const EntitySequence* seq, const unsigned char* const& ptr ) const
135 {
136  // cast away the constness; otherwise it would be infinite recursion
137  // probably we are not calling this anywhere
138  return get_array_private( seq, const_cast< const unsigned char*& >( ptr ) );
139 }
140 
141 ErrorCode DenseTag::get_array_private( const EntitySequence* seq, const unsigned char*& ptr ) const
142 {
143  ptr = reinterpret_cast< const unsigned char* >( seq->data()->get_tag_data( mySequenceArray ) );
144  if( ptr ) ptr += get_size() * ( seq->start_handle() - seq->data()->start_handle() );
145 
146  return MB_SUCCESS;
147 }
148 
150  Error* /* error */,
151  EntityHandle h,
152  unsigned char*& ptr,
153  size_t& count,
154  bool allocate )
155 {
156  EntitySequence* seq = 0;
157  ErrorCode rval = seqman->find( h, seq );
158  if( MB_SUCCESS != rval )
159  {
160  if( !h )
161  { // Root set
162  if( !meshValue && allocate ) meshValue = new unsigned char[get_size()];
163  ptr = meshValue;
164  count = 1;
165  return MB_SUCCESS;
166  }
167  else
168  { // Not root set
169  ptr = 0;
170  count = 0;
171  return ent_not_found( get_name(), h );
172  }
173  }
174 
175  void* mem = seq->data()->get_tag_data( mySequenceArray );
176  if( !mem && allocate )
177  {
179  if( !mem )
180  {
181  MB_SET_ERR( MB_MEMORY_ALLOCATION_FAILED, "Memory allocation for dense tag data failed" );
182  }
183 
184  if( !get_default_value() ) memset( mem, 0, get_size() * seq->data()->size() );
185  }
186 
187  ptr = reinterpret_cast< unsigned char* >( mem );
188  count = seq->data()->end_handle() - h + 1;
189  if( ptr ) ptr += get_size() * ( h - seq->data()->start_handle() );
190  return MB_SUCCESS;
191 }
192 
194  Error* /* error */,
195  const EntityHandle* entities,
196  size_t num_entities,
197  void* adata ) const
198 {
199  size_t junk = 0;
200  unsigned char* ptr = reinterpret_cast< unsigned char* >( adata );
201  const EntityHandle* const end = entities + num_entities;
202  for( const EntityHandle* i = entities; i != end; ++i, ptr += get_size() )
203  {
204  const unsigned char* data = 0;
205  ErrorCode rval = get_array( seqman, NULL, *i, data, junk );MB_CHK_ERR( rval );
206 
207  if( data )
208  memcpy( ptr, data, get_size() );
209  else if( get_default_value() )
210  memcpy( ptr, get_default_value(), get_size() );
211  else
212  return not_found( get_name(), *i );
213  }
214 
215  return MB_SUCCESS;
216 }
217 
219  Error* /* error */,
220  const Range& entities,
221  void* values ) const
222 {
223  ErrorCode rval;
224  size_t avail = 0;
225  const unsigned char* array = NULL; // Initialize to get rid of warning
226  unsigned char* data = reinterpret_cast< unsigned char* >( values );
227 
228  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
229  {
230  EntityHandle start = p->first;
231  while( start <= p->second )
232  {
233  rval = get_array( seqman, NULL, start, array, avail );MB_CHK_ERR( rval );
234 
235  const size_t count = std::min< size_t >( p->second - start + 1, avail );
236  if( array )
237  memcpy( data, array, get_size() * count );
238  else if( get_default_value() )
239  SysUtil::setmem( data, get_default_value(), get_size(), count );
240  else
241  return not_found( get_name(), start );
242 
243  data += get_size() * count;
244  start += count;
245  }
246  }
247 
248  return MB_SUCCESS;
249 }
250 
252  Error* /* error */,
253  const EntityHandle* entities,
254  size_t num_entities,
255  const void** pointers,
256  int* data_lengths ) const
257 {
258  ErrorCode result;
259  const EntityHandle* const end = entities + num_entities;
260  size_t junk = 0;
261  const unsigned char* ptr = NULL; // Initialize to get rid of warning
262 
263  if( data_lengths )
264  {
265  const int len = get_size();
266  SysUtil::setmem( data_lengths, &len, sizeof( int ), num_entities );
267  }
268 
269  for( const EntityHandle* i = entities; i != end; ++i, ++pointers )
270  {
271  result = get_array( seqman, NULL, *i, ptr, junk );MB_CHK_ERR( result );
272 
273  if( ptr )
274  *pointers = ptr;
275  else if( get_default_value() )
276  *pointers = get_default_value();
277  else
278  return not_found( get_name(), *i );
279  }
280 
281  return MB_SUCCESS;
282 }
283 
285  Error* /* error */,
286  const Range& entities,
287  const void** pointers,
288  int* data_lengths ) const
289 {
290  ErrorCode rval;
291  size_t avail = 0;
292  const unsigned char* array = NULL;
293 
294  if( data_lengths )
295  {
296  int len = get_size();
297  SysUtil::setmem( data_lengths, &len, sizeof( int ), entities.size() );
298  }
299 
300  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
301  {
302  EntityHandle start = p->first;
303  while( start <= p->second )
304  {
305  rval = get_array( seqman, NULL, start, array, avail );MB_CHK_ERR( rval );
306 
307  const size_t count = std::min< size_t >( p->second - start + 1, avail );
308  if( array )
309  {
310  for( EntityHandle end = start + count; start != end; ++start )
311  {
312  *pointers = array;
313  array += get_size();
314  ++pointers;
315  }
316  }
317  else if( const void* val = get_default_value() )
318  {
319  SysUtil::setmem( pointers, &val, sizeof( void* ), count );
320  pointers += count;
321  start += count;
322  }
323  else
324  {
325  return not_found( get_name(), start );
326  }
327  }
328  }
329 
330  return MB_SUCCESS;
331 }
332 
334  Error* /* error */,
335  const EntityHandle* entities,
336  size_t num_entities,
337  const void* data )
338 {
339  ErrorCode rval;
340  const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
341  const EntityHandle* const end = entities + num_entities;
342  unsigned char* array = NULL;
343  size_t junk = 0;
344 
345  for( const EntityHandle* i = entities; i != end; ++i, ptr += get_size() )
346  {
347  rval = get_array_private( seqman, NULL, *i, array, junk, true );MB_CHK_ERR( rval );
348 
349  memcpy( array, ptr, get_size() );
350  }
351 
352  return MB_SUCCESS;
353 }
354 
355 ErrorCode DenseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities, const void* values )
356 {
357  ErrorCode rval;
358  const char* data = reinterpret_cast< const char* >( values );
359  unsigned char* array = NULL;
360  size_t avail = 0;
361 
362  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
363  {
364  EntityHandle start = p->first;
365  while( start <= p->second )
366  {
367  rval = get_array_private( seqman, NULL, start, array, avail, true );MB_CHK_ERR( rval );
368 
369  const size_t count = std::min< size_t >( p->second - start + 1, avail );
370  memcpy( array, data, get_size() * count );
371  data += get_size() * count;
372  start += count;
373  }
374  }
375 
376  return MB_SUCCESS;
377 }
378 
380  Error* /* error */,
381  const EntityHandle* entities,
382  size_t num_entities,
383  void const* const* pointers,
384  const int* data_lengths )
385 {
386  ErrorCode rval = validate_lengths( NULL, data_lengths, num_entities );MB_CHK_ERR( rval );
387 
388  const EntityHandle* const end = entities + num_entities;
389  unsigned char* array = NULL;
390  size_t junk = 0;
391 
392  for( const EntityHandle* i = entities; i != end; ++i, ++pointers )
393  {
394  rval = get_array_private( seqman, NULL, *i, array, junk, true );MB_CHK_ERR( rval );
395 
396  memcpy( array, *pointers, get_size() );
397  }
398 
399  return MB_SUCCESS;
400 }
401 
403  Error* /* error */,
404  const Range& entities,
405  void const* const* pointers,
406  const int* /* data_lengths */ )
407 {
408  ErrorCode rval;
409  unsigned char* array = NULL;
410  size_t avail = 0;
411 
412  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
413  {
414  EntityHandle start = p->first;
415  while( start <= p->second )
416  {
417  rval = get_array_private( seqman, NULL, start, array, avail, true );MB_CHK_ERR( rval );
418 
419  const EntityHandle end = std::min< EntityHandle >( p->second + 1, start + avail );
420  while( start != end )
421  {
422  memcpy( array, *pointers, get_size() );
423  ++start;
424  ++pointers;
425  array += get_size();
426  }
427  }
428  }
429 
430  return MB_SUCCESS;
431 }
432 
434  SequenceManager* seqman,
435  Error* /* error */,
436  const EntityHandle* entities,
437  size_t num_entities,
438  const void* value_ptr )
439 {
440  ErrorCode rval;
441  const EntityHandle* const end = entities + num_entities;
442  unsigned char* array = NULL;
443  size_t junk = 0;
444 
445  for( const EntityHandle* i = entities; i != end; ++i )
446  {
447  rval = get_array_private( seqman, NULL, *i, array, junk, allocate );MB_CHK_ERR( rval );
448 
449  if( array ) // Array should never be null if allocate == true
450  memcpy( array, value_ptr, get_size() );
451  }
452 
453  return MB_SUCCESS;
454 }
455 
457  SequenceManager* seqman,
458  Error* /* error */,
459  const Range& entities,
460  const void* value_ptr )
461 {
462  ErrorCode rval;
463  unsigned char* array = NULL;
464  size_t avail = 0;
465 
466  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
467  {
468  EntityHandle start = p->first;
469  while( start <= p->second )
470  {
471  rval = get_array_private( seqman, NULL, start, array, avail, allocate );MB_CHK_ERR( rval );
472 
473  const size_t count = std::min< size_t >( p->second - start + 1, avail );
474  if( array ) // Array should never be null if allocate == true
475  SysUtil::setmem( array, value_ptr, get_size(), count );
476  start += count;
477  }
478  }
479 
480  return MB_SUCCESS;
481 }
482 
484  Error* /* error */,
485  const EntityHandle* entities,
486  size_t num_entities,
487  const void* value_ptr,
488  int value_len )
489 {
490  if( value_len && value_len != get_size() ) return MB_INVALID_SIZE;
491 
492  return clear_data( true, seqman, NULL, entities, num_entities, value_ptr );
493 }
494 
496  Error* /* error */,
497  const Range& entities,
498  const void* value_ptr,
499  int value_len )
500 {
501  if( value_len && value_len != get_size() ) return MB_INVALID_SIZE;
502 
503  return clear_data( true, seqman, NULL, entities, value_ptr );
504 }
505 
507  Error* /* error */,
508  const EntityHandle* entities,
509  size_t num_entities )
510 {
511  std::vector< unsigned char > zeros;
512  const void* value = get_default_value();
513  if( !value )
514  {
515  zeros.resize( get_size(), 0 );
516  value = &zeros[0];
517  }
518 
519  return clear_data( false, seqman, NULL, entities, num_entities, value );
520 }
521 
523 {
524  std::vector< unsigned char > zeros;
525  const void* value = get_default_value();
526  if( !value )
527  {
528  zeros.resize( get_size(), 0 );
529  value = &zeros[0];
530  }
531 
532  return clear_data( false, seqman, NULL, entities, value );
533 }
534 
536  Error* /* error */,
537  Range::iterator& iter,
538  const Range::iterator& end,
539  void*& data_ptr,
540  bool allocate )
541 {
542  // If asked for nothing, successfully return nothing.
543  if( iter == end ) return MB_SUCCESS;
544 
545  unsigned char* array = NULL;
546  size_t avail = 0;
547  ErrorCode rval = get_array_private( seqman, NULL, *iter, array, avail, allocate );MB_CHK_ERR( rval );
548  data_ptr = array;
549 
550  size_t count = std::min< size_t >( avail, *( iter.end_of_block() ) - *iter + 1 );
551  if( 0 != *end && *end <= *( iter.end_of_block() ) )
552  iter = end;
553  else
554  iter += count;
555 
556  return MB_SUCCESS;
557 }
558 
560  Range& entities_in,
561  EntityType type,
562  const Range* intersect_list ) const
563 {
564  Range tmp;
565  Range* entities = intersect_list ? &tmp : &entities_in;
566  Range::iterator hint = entities->begin();
567  std::pair< EntityType, EntityType > range = type_range( type );
569  for( EntityType t = range.first; t != range.second; ++t )
570  {
571  const TypeSequenceManager& map = seqman->entity_map( t );
572  for( i = map.begin(); i != map.end(); ++i )
573  if( ( *i )->data()->get_tag_data( mySequenceArray ) )
574  hint = entities->insert( hint, ( *i )->start_handle(), ( *i )->end_handle() );
575  }
576 
577  if( intersect_list ) entities_in = intersect( *entities, *intersect_list );
578 
579  return MB_SUCCESS;
580 }
581 
583  size_t& output_count,
584  EntityType type,
585  const Range* intersect ) const
586 {
587  Range tmp;
588  ErrorCode rval = get_tagged_entities( seqman, tmp, type, intersect );
589  output_count += tmp.size();
590 
591  return rval;
592 }
593 
595  Error* /* error */,
596  Range& output_entities,
597  const void* value,
598  int value_bytes,
599  EntityType type,
600  const Range* intersect_entities ) const
601 {
602  if( value_bytes && value_bytes != get_size() )
603  {
605  "Cannot compare data of size " << value_bytes << " with tag of size " << get_size() );
606  }
607 
608  if( !intersect_entities )
609  {
610  std::pair< EntityType, EntityType > range = type_range( type );
612  for( EntityType t = range.first; t != range.second; ++t )
613  {
614  const TypeSequenceManager& map = seqman->entity_map( t );
615  for( i = map.begin(); i != map.end(); ++i )
616  {
617  const void* data = ( *i )->data()->get_tag_data( mySequenceArray );
618  if( data )
619  {
620  ByteArrayIterator start( ( *i )->data()->start_handle(), data, *this );
621  ByteArrayIterator end( ( *i )->end_handle() + 1, 0, 0 );
622  start += ( *i )->start_handle() - ( *i )->data()->start_handle();
623  find_tag_values_equal( *this, value, get_size(), start, end, output_entities );
624  }
625  }
626  }
627  }
628  else
629  {
630  const unsigned char* array = NULL; // Initialize to get rid of warning
631  size_t count;
632  ErrorCode rval;
633 
634  Range::const_pair_iterator p = intersect_entities->begin();
635  if( type != MBMAXTYPE )
636  {
637  p = intersect_entities->lower_bound( type );
638  assert( TYPE_FROM_HANDLE( p->first ) == type );
639  }
640  for( ;
641  p != intersect_entities->const_pair_end() && ( MBMAXTYPE == type || TYPE_FROM_HANDLE( p->first ) == type );
642  ++p )
643  {
644  EntityHandle start = p->first;
645  while( start <= p->second )
646  {
647  rval = get_array( seqman, NULL, start, array, count );MB_CHK_ERR( rval );
648 
649  if( p->second - start < count - 1 ) count = p->second - start + 1;
650 
651  if( array )
652  {
653  ByteArrayIterator istart( start, array, *this );
654  ByteArrayIterator iend( start + count, 0, 0 );
655  find_tag_values_equal( *this, value, get_size(), istart, iend, output_entities );
656  }
657  start += count;
658  }
659  }
660  }
661 
662  return MB_SUCCESS;
663 }
664 
665 bool DenseTag::is_tagged( const SequenceManager* seqman, EntityHandle h ) const
666 {
667  const unsigned char* ptr = NULL; // Initialize to get rid of warning
668  size_t count;
669  return ( MB_SUCCESS == get_array( seqman, 0, h, ptr, count ) ) && ( NULL != ptr );
670 }
671 
673  unsigned long& total,
674  unsigned long& per_entity ) const
675 {
676  per_entity = get_size();
677  total = TagInfo::get_memory_use() + sizeof( *this );
678  for( EntityType t = MBVERTEX; t <= MBENTITYSET; ++t )
679  {
680  const TypeSequenceManager& map = seqman->entity_map( t );
681  const SequenceData* prev_data = 0;
682  for( TypeSequenceManager::const_iterator i = map.begin(); i != map.end(); ++i )
683  {
684  if( ( *i )->data() != prev_data && ( *i )->data()->get_tag_data( mySequenceArray ) )
685  {
686  prev_data = ( *i )->data();
687  total += get_size() * ( *i )->data()->size();
688  }
689  }
690  }
691 
692  return MB_SUCCESS;
693 }
694 
695 } // namespace moab