MOAB: Mesh Oriented datABase  (version 5.5.0)
reorder_test.cpp
Go to the documentation of this file.
1 #include "moab/Core.hpp"
2 #include "moab/ReorderTool.hpp"
3 #include "TestUtil.hpp"
4 
5 using namespace moab;
6 
7 // some tag names
8 const char GLOBAL_ID_NAME[] = "GLOBAL_ID"; /* global ID assigned to each vtx and quad */
9 const char SET_IDS_NAME[] = "SET_IDS"; /* global IDs of entities in each set */
10 const char SET_HANDLES_NAME[] = "SET_HANDLES"; /* handles of entities in each set */
11 const char CONN_IDS_NAME[] = "CONN_IDS"; /* global IDs of vertices in each quad */
12 const char CONN_NAME[] = "CONN_HANDLES"; /* handles of vertices in each quad */
13 const char VAR_INTS_NAME[] = "VAR_LEN_INTS"; /* variable length tag on nodes */
14 const char BIT_NAME[] = "TEST_BIT_TAG";
15 const int ENTS_PER_SET = 6;
16 const int BITS_PER_TAG = 2;
17 
18 Core* mbcore = 0;
21 
22 const size_t INTERVALS = 6;
23 
24 /* values for variable-length tag data */
25 void tag_vals_from_gid( int global_id, std::vector< int >& values )
26 {
27  int i = global_id / ( INTERVALS + 1 );
28  int j = global_id % ( INTERVALS + 1 );
29  int n = global_id % 5 + 1;
30  int vals[] = { i, j, n, i + j, j - 2 * i };
31  values.resize( n );
32  std::copy( vals, vals + n, values.begin() );
33 }
34 
35 unsigned char bits_from_gid( int global_id )
36 {
37  return global_id % ( 1 << BITS_PER_TAG );
38 }
39 
40 unsigned char order_from_gid( int global_id )
41 {
42  return global_id % 3;
43 }
44 
45 void coords_from_gid( int global_id, double coords[3] )
46 {
47  int i = global_id / ( INTERVALS + 1 );
48  int j = global_id % ( INTERVALS + 1 );
49  coords[0] = i;
50  coords[1] = j;
51  coords[2] = 0.1 * ( i + j );
52 }
53 
54 void build_mesh();
56 void call_reorder();
57 void check_order();
58 void check_node_coords();
59 void check_quad_conn();
60 void check_set_meshset();
61 void check_list_meshset();
62 void check_big_meshset();
63 void check_handle_tag();
64 void check_varlen_tag();
65 void check_bit_tag();
66 
67 int main()
68 {
69  // Define global MOAB instance for use by all tests
70  Core mcore;
71  mbcore = &mcore;
72  mb = &mcore;
73 
74  // if this fails, don't bother with anything else
75  if( RUN_TEST( build_mesh ) ) return 1;
76 
77  // this test needs be be run before reordering the mesh
78  int errors = 0;
80 
81  // if reorder returned failure, don't bother doing anything else
82  int tmp = RUN_TEST( call_reorder );
83  if( tmp ) return tmp + errors;
84 
85  // test the core stuff
86  errors += RUN_TEST( check_order );
87  errors += RUN_TEST( check_node_coords );
88  errors += RUN_TEST( check_quad_conn );
89  errors += RUN_TEST( check_set_meshset );
90  errors += RUN_TEST( check_list_meshset );
91  errors += RUN_TEST( check_big_meshset );
92  errors += RUN_TEST( check_handle_tag );
93  errors += RUN_TEST( check_varlen_tag );
94  errors += RUN_TEST( check_bit_tag );
95  return errors;
96 }
97 
98 void build_mesh()
99 {
100  const unsigned dense = MB_TAG_CREAT | MB_TAG_DENSE;
101  const unsigned sparse = MB_TAG_CREAT | MB_TAG_SPARSE;
102 
103  ErrorCode rval;
104 
105  // get/create various tags
106  Tag gid;
107  rval = mb->tag_get_handle( GLOBAL_ID_NAME, 1, MB_TYPE_INTEGER, gid, dense );CHECK_ERR( rval );
108 
109  Tag conn_ids;
110  rval = mb->tag_get_handle( CONN_IDS_NAME, 4, MB_TYPE_INTEGER, conn_ids, dense );CHECK_ERR( rval );
111 
112  Tag conn_handles;
113  rval = mb->tag_get_handle( CONN_NAME, 4, MB_TYPE_HANDLE, conn_handles, dense );CHECK_ERR( rval );
114 
115  Tag set_ids;
116  rval = mb->tag_get_handle( SET_IDS_NAME, ENTS_PER_SET, MB_TYPE_INTEGER, set_ids, sparse );CHECK_ERR( rval );
117 
118  Tag set_handles;
119  rval = mb->tag_get_handle( SET_HANDLES_NAME, ENTS_PER_SET, MB_TYPE_HANDLE, set_handles, sparse );CHECK_ERR( rval );
120 
121  Tag var_data;
122  rval = mb->tag_get_handle( VAR_INTS_NAME, 0, MB_TYPE_INTEGER, var_data, dense | MB_TAG_VARLEN );CHECK_ERR( rval );
123 
124  Tag bit_data;
125  rval = mb->tag_get_handle( BIT_NAME, BITS_PER_TAG, MB_TYPE_BIT, bit_data, MB_TAG_CREAT );CHECK_ERR( rval );
126 
127  rval = mb->tag_get_handle( "ORDER", 1, MB_TYPE_INTEGER, order_tag, dense );CHECK_ERR( rval );
128 
129  // create and tag vertices
130  std::vector< int > values;
131  EntityHandle nodes[( INTERVALS + 1 ) * ( INTERVALS + 1 )];
132  for( size_t i = 0; i <= INTERVALS; ++i )
133  {
134  for( size_t j = 0; j <= INTERVALS; ++j )
135  {
136  size_t idx = i * ( INTERVALS + 1 ) + j;
137  double coords[3];
138  coords_from_gid( idx, coords );
139  rval = mb->create_vertex( coords, nodes[idx] );CHECK_ERR( rval );
140 
141  int tagval = idx;
142  rval = mb->tag_set_data( gid, nodes + idx, 1, &tagval );CHECK_ERR( rval );
143 
144  tag_vals_from_gid( idx, values );
145  const void* ptr = &values[0];
146  const int size = values.size();
147  rval = mb->tag_set_by_ptr( var_data, nodes + idx, 1, &ptr, &size );CHECK_ERR( rval );
148 
149  unsigned char bits = bits_from_gid( idx );
150  rval = mb->tag_set_data( bit_data, nodes + idx, 1, &bits );CHECK_ERR( rval );
151 
152  int group = order_from_gid( idx );
153  rval = mb->tag_set_data( order_tag, nodes + idx, 1, &group );CHECK_ERR( rval );
154  }
155  }
156 
157  // create and tag elements
159  for( size_t i = 0; i < INTERVALS; ++i )
160  {
161  for( size_t j = 0; j < INTERVALS; ++j )
162  {
163  size_t idx = i * INTERVALS + j;
164  size_t n0 = i * ( INTERVALS + 1 ) + j;
165  size_t n1 = ( i + 1 ) * ( INTERVALS + 1 ) + j;
166  size_t n2 = ( i + 1 ) * ( INTERVALS + 1 ) + j + 1;
167  size_t n3 = i * ( INTERVALS + 1 ) + j + 1;
168  EntityHandle conn[4] = { nodes[n0], nodes[n1], nodes[n2], nodes[n3] };
169  EntityHandle h;
170  rval = mb->create_element( MBQUAD, conn, 4, h );CHECK_ERR( rval );
171 
172  int tagval = idx;
173  rval = mb->tag_set_data( gid, &h, 1, &tagval );CHECK_ERR( rval );
174 
175  int ids[4] = { static_cast< int >( n0 ), static_cast< int >( n1 ), static_cast< int >( n2 ),
176  static_cast< int >( n3 ) };
177  rval = mb->tag_set_data( conn_ids, &h, 1, ids );CHECK_ERR( rval );
178 
179  rval = mb->tag_set_data( conn_handles, &h, 1, conn );CHECK_ERR( rval );
180 
181  int group = order_from_gid( idx );
182  rval = mb->tag_set_data( order_tag, &h, 1, &group );CHECK_ERR( rval );
183 
184  quads[idx] = h;
185  }
186  }
187 
188  // create a few sets
189  for( int i = 0; i < 2; ++i )
190  {
191  EntityHandle* from = 0;
192  size_t count;
193  unsigned flag;
194  if( i )
195  {
196  from = nodes;
197  count = ( INTERVALS + 1 ) * ( INTERVALS + 1 );
198  flag = MESHSET_SET;
199  }
200  else
201  {
202  from = quads;
203  count = INTERVALS * INTERVALS;
204  flag = MESHSET_ORDERED;
205  }
206 
207  EntityHandle h;
208  rval = mb->create_meshset( flag | MESHSET_TRACK_OWNER, h );CHECK_ERR( rval );
209 
211  int gids[ENTS_PER_SET];
212  for( int j = 0; j < ENTS_PER_SET; ++j )
213  {
214  int idx = j + 2;
215  idx = ( idx * idx ) % count;
216  ents[j] = from[idx];
217  gids[j] = idx;
218  }
219 
220  rval = mb->add_entities( h, ents, ENTS_PER_SET );CHECK_ERR( rval );
221 
222  rval = mb->tag_set_data( set_ids, &h, 1, gids );CHECK_ERR( rval );
223 
224  rval = mb->tag_set_data( set_handles, &h, 1, ents );CHECK_ERR( rval );
225  }
226 
227  // create a set containing all vertices
228  EntityHandle allverts;
229  rval = mb->create_meshset( MESHSET_SET, allverts );CHECK_ERR( rval );
230  rval = mb->add_entities( allverts, nodes, ( INTERVALS + 1 ) * ( INTERVALS + 1 ) );CHECK_ERR( rval );
231 }
232 
234 {
235  // do reorder
236  ReorderTool tool( mbcore );
237  Tag mapping;
238  ErrorCode rval = tool.handle_order_from_int_tag( order_tag, -1, mapping );CHECK_ERR( rval );
239  rval = tool.reorder_entities( mapping );CHECK_ERR( rval );
240 }
241 
242 void check_order( EntityType type )
243 {
244  ErrorCode rval;
245 
246  Tag gid;
247  rval = mb->tag_get_handle( GLOBAL_ID_NAME, 1, MB_TYPE_INTEGER, gid );CHECK_ERR( rval );
248 
249  Range ents;
250  rval = mb->get_entities_by_type( 0, type, ents );CHECK_ERR( rval );
251 
252  std::vector< int > ids( ents.size() );
253  rval = mb->tag_get_data( gid, ents, &ids[0] );CHECK_ERR( rval );
254 
255  for( size_t i = 1; i < ids.size(); ++i )
256  {
257  CHECK( order_from_gid( ids[i - 1] ) <= order_from_gid( ids[i] ) );
258  }
259 }
260 
262 {
263  ErrorCode rval;
264 
265  std::vector< EntityHandle > quads;
266  rval = mb->get_entities_by_dimension( 0, 2, quads );CHECK_ERR( rval );
267  CHECK( !quads.empty() );
268 
269  // group quads by the ordering assigned in build_mesh()
270  std::map< int, Range > groups;
271  std::vector< int > group_ids( quads.size() );
272  rval = mb->tag_get_data( order_tag, &quads[0], quads.size(), &group_ids[0] );CHECK_ERR( rval );
273  for( size_t i = 0; i < quads.size(); ++i )
274  groups[group_ids[i]].insert( quads[i] );
275 
276  // create sets from groups
277  Range sets;
278  for( std::map< int, Range >::iterator i = groups.begin(); i != groups.end(); ++i )
279  {
280  EntityHandle h;
281  rval = mb->create_meshset( MESHSET_SET, h );CHECK_ERR( rval );
282  rval = mb->add_entities( h, i->second );CHECK_ERR( rval );
283  sets.insert( h );
284  }
285 
286  // Get ordering assigned by set containment
287  Tag neworder = 0;
288  ReorderTool tool( mbcore );
289  rval = tool.handle_order_from_sets_and_adj( sets, neworder );CHECK_ERR( rval );
290 
291  // check that new quad handles are clustered as expected
292  std::vector< std::pair< EntityHandle, EntityHandle > > ranges;
293  for( std::map< int, Range >::iterator i = groups.begin(); i != groups.end(); ++i )
294  {
295  std::vector< EntityHandle > newh( i->second.size() );
296  rval = mb->tag_get_data( neworder, i->second, &newh[0] );CHECK_ERR( rval );
297  std::sort( newh.begin(), newh.end() );
298  CHECK( newh[0] > 0 ); // zero implies some quad got left out of the reordering
299  std::pair< EntityHandle, EntityHandle > p( newh[0], newh[newh.size() - 1] );
300  ranges.push_back( p );
301  }
302  std::sort( ranges.begin(), ranges.end() );
303  for( size_t i = 1; i < ranges.size(); ++i )
304  {
305  CHECK( ranges[i - 1].second < ranges[i].first );
306  }
307 
308  // group vertices as we expect handles to be grouped
309  std::map< std::vector< int >, Range > vtxgroups;
310  Range verts;
311  rval = mb->get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
312  for( Range::iterator i = verts.begin(); i != verts.end(); ++i )
313  {
314  Range adj;
315  rval = mb->get_adjacencies( &*i, 1, 2, false, adj );CHECK_ERR( rval );
316  std::vector< int > ids( adj.size() );
317  rval = mb->tag_get_data( order_tag, adj, &ids[0] );CHECK_ERR( rval );
318  std::sort( ids.begin(), ids.end() );
319  ids.erase( std::unique( ids.begin(), ids.end() ), ids.end() );
320  vtxgroups[ids].insert( *i );
321  }
322 
323  // check that new vertex handles are clustered as expected
324  ranges.clear();
325  std::map< std::vector< int >, Range >::iterator j;
326  for( j = vtxgroups.begin(); j != vtxgroups.end(); ++j )
327  {
328  std::vector< EntityHandle > newh( j->second.size() );
329  rval = mb->tag_get_data( neworder, j->second, &newh[0] );CHECK_ERR( rval );
330  std::sort( newh.begin(), newh.end() );
331  CHECK( newh[0] > 0 ); // zero implies some quad got left out of the reordering
332  std::pair< EntityHandle, EntityHandle > p( newh[0], newh[newh.size() - 1] );
333  ranges.push_back( p );
334  }
335  std::sort( ranges.begin(), ranges.end() );
336  for( size_t i = 1; i < ranges.size(); ++i )
337  {
338  CHECK( ranges[i - 1].second < ranges[i].first );
339  }
340 }
341 
343 {
345  check_order( MBQUAD );
346 }
347 
349 {
350  ErrorCode rval;
351 
352  Tag gid;
353  rval = mb->tag_get_handle( GLOBAL_ID_NAME, 1, MB_TYPE_INTEGER, gid );CHECK_ERR( rval );
354 
355  Range verts;
356  rval = mb->get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
357 
358  std::vector< int > ids( verts.size() );
359  rval = mb->tag_get_data( gid, verts, &ids[0] );CHECK_ERR( rval );
360 
361  std::vector< double > coords( 3 * verts.size() );
362  rval = mb->get_coords( verts, &coords[0] );CHECK_ERR( rval );
363 
364  std::vector< double > expected( 3 * verts.size() );
365  for( size_t i = 0; i < ids.size(); ++i )
366  coords_from_gid( ids[i], &expected[3 * i] );
367 
368  CHECK_EQUAL( expected, coords );
369 }
370 
372 {
373  ErrorCode rval;
374 
375  Tag gid;
376  rval = mb->tag_get_handle( GLOBAL_ID_NAME, 1, MB_TYPE_INTEGER, gid );CHECK_ERR( rval );
377 
378  Tag conn_ids;
379  rval = mb->tag_get_handle( CONN_IDS_NAME, 4, MB_TYPE_INTEGER, conn_ids );CHECK_ERR( rval );
380 
381  std::vector< EntityHandle > quads;
382  rval = mb->get_entities_by_type( 0, MBQUAD, quads );CHECK_ERR( rval );
383 
384  std::vector< EntityHandle > conn;
385  rval = mb->get_connectivity( &quads[0], quads.size(), conn, true );CHECK_ERR( rval );
386 
387  CHECK_EQUAL( 4 * quads.size(), conn.size() );
388  std::vector< int > exp_ids( 4 * quads.size() ), act_ids( 4 * quads.size() );
389  rval = mb->tag_get_data( conn_ids, &quads[0], quads.size(), &exp_ids[0] );CHECK_ERR( rval );
390  rval = mb->tag_get_data( gid, &conn[0], conn.size(), &act_ids[0] );CHECK_ERR( rval );
391 
392  CHECK_EQUAL( exp_ids, act_ids );
393 }
394 
395 void check_meshset_common( bool ordered )
396 {
397  ErrorCode rval;
398 
399  Tag set_ids;
400  rval = mb->tag_get_handle( SET_IDS_NAME, ENTS_PER_SET, MB_TYPE_INTEGER, set_ids );CHECK_ERR( rval );
401 
402  Tag gid;
403  rval = mb->tag_get_handle( GLOBAL_ID_NAME, 1, MB_TYPE_INTEGER, gid );CHECK_ERR( rval );
404 
405  Range sets;
406  rval = mb->get_entities_by_type_and_tag( 0, MBENTITYSET, &set_ids, 0, 1, sets );CHECK_ERR( rval );
407  CHECK( !sets.empty() );
408 
409  EntityHandle set = 0;
410  unsigned flags;
411  for( Range::iterator it = sets.begin(); it != sets.end(); ++it )
412  {
413  rval = mb->get_meshset_options( *it, flags );CHECK_ERR( rval );
414  if( ( ordered && ( flags & MESHSET_ORDERED ) ) || ( !ordered && !( flags & MESHSET_ORDERED ) ) )
415  {
416  set = *it;
417  break;
418  }
419  }
420  CHECK( 0 != set );
421 
422  std::vector< EntityHandle > ents;
423  rval = mb->get_entities_by_handle( set, ents );CHECK_ERR( rval );
424  CHECK_EQUAL( ENTS_PER_SET, (int)ents.size() );
425 
426  int exp[ENTS_PER_SET], act[ENTS_PER_SET];
427  rval = mb->tag_get_data( set_ids, &set, 1, exp );CHECK_ERR( rval );
428  rval = mb->tag_get_data( gid, &ents[0], ENTS_PER_SET, act );CHECK_ERR( rval );
429 
430  if( !ordered )
431  {
432  std::sort( exp, exp + ENTS_PER_SET );
433  std::sort( act, act + ENTS_PER_SET );
434  }
435 
437 
438  if( !( flags & MESHSET_TRACK_OWNER ) ) return;
439 
440  for( int i = 0; i < ENTS_PER_SET; ++i )
441  {
442  std::vector< EntityHandle > adj;
443  rval = mb->get_adjacencies( &ents[i], 1, 4, false, adj );CHECK_ERR( rval );
444  CHECK( std::find( adj.begin(), adj.end(), set ) != adj.end() );
445  }
446 }
447 
449 {
450  check_meshset_common( false );
451 }
452 
454 {
455  check_meshset_common( true );
456 }
457 
459 {
460  // Mesh should have a single set that contains all the vertices.
461  // Find it.
462  Range sets;
463  ErrorCode rval = mb->get_entities_by_type( 0, MBENTITYSET, sets );CHECK_ERR( rval );
464 
465  Range verts;
466  rval = mb->get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
467 
468  bool found = false;
469  for( Range::iterator it = sets.begin(); it != sets.end(); ++it )
470  {
471  Range ents;
472  rval = mb->get_entities_by_handle( *it, ents );CHECK_ERR( rval );
473  if( ents == verts )
474  {
475  found = true;
476  break;
477  }
478  }
479  CHECK( found );
480 }
481 
483 {
484  Range::iterator it;
485  ErrorCode rval;
486 
487  // first check tag on sets, for which the values should have been
488  // updated according to the reordering
489 
490  Tag set_handles;
491  rval = mb->tag_get_handle( SET_HANDLES_NAME, ENTS_PER_SET, MB_TYPE_HANDLE, set_handles );CHECK_ERR( rval );
492 
493  Range sets;
494  rval = mb->get_entities_by_type_and_tag( 0, MBENTITYSET, &set_handles, 0, 1, sets );CHECK_ERR( rval );
495  CHECK( !sets.empty() );
496 
497  for( it = sets.begin(); it != sets.end(); ++it )
498  {
499  std::vector< EntityHandle > ents;
500  rval = mb->get_entities_by_handle( *it, ents );CHECK_ERR( rval );
501 
502  std::vector< EntityHandle > handles( ENTS_PER_SET );
503  rval = mb->tag_get_data( set_handles, &*it, 1, &handles[0] );CHECK_ERR( rval );
504 
505  unsigned flags;
506  rval = mb->get_meshset_options( *it, flags );CHECK_ERR( rval );
507  if( !( flags & MESHSET_ORDERED ) ) std::sort( handles.begin(), handles.end() );
508 
509  CHECK_EQUAL( ents, handles );
510  }
511 
512  // Now check handle tag on quads. This tag need to both be re-ordered
513  // and have the contained handles updated.
514 
515  Tag conn_handles;
516  rval = mb->tag_get_handle( CONN_NAME, 4, MB_TYPE_HANDLE, conn_handles );CHECK_ERR( rval );
517 
518  std::vector< EntityHandle > quads;
519  rval = mb->get_entities_by_type( 0, MBQUAD, quads );CHECK_ERR( rval );
520 
521  std::vector< EntityHandle > conn;
522  rval = mb->get_connectivity( &quads[0], quads.size(), conn, true );CHECK_ERR( rval );
523 
524  std::vector< EntityHandle > tagvals( 4 * quads.size() );
525  rval = mb->tag_get_data( conn_handles, &quads[0], quads.size(), &tagvals[0] );CHECK_ERR( rval );
526 
527  CHECK_EQUAL( conn, tagvals );
528 }
529 
531 {
532  ErrorCode rval;
533 
534  Tag gid;
535  rval = mb->tag_get_handle( GLOBAL_ID_NAME, 1, MB_TYPE_INTEGER, gid );CHECK_ERR( rval );
536 
537  Tag var_data;
538  rval = mb->tag_get_handle( VAR_INTS_NAME, 0, MB_TYPE_INTEGER, var_data );CHECK_ERR( rval );
539 
540  Range verts;
541  rval = mb->get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
542 
543  std::vector< int > gids( verts.size() );
544  rval = mb->tag_get_data( gid, verts, &gids[0] );CHECK_ERR( rval );
545 
546  std::vector< const void* > ptrs( verts.size() );
547  std::vector< int > sizes( verts.size() );
548  rval = mb->tag_get_by_ptr( var_data, verts, &ptrs[0], &sizes[0] );CHECK_ERR( rval );
549 
550  for( size_t i = 0; i < gids.size(); ++i )
551  {
552  std::vector< int > exp;
553  tag_vals_from_gid( gids[i], exp );
554  CHECK_ARRAYS_EQUAL( &exp[0], exp.size(), (const int*)ptrs[i], sizes[i] );
555  }
556 }
557 
559 {
560  ErrorCode rval;
561 
562  Tag gid;
563  rval = mb->tag_get_handle( GLOBAL_ID_NAME, 1, MB_TYPE_INTEGER, gid );CHECK_ERR( rval );
564 
565  Tag bit_data;
566  rval = mb->tag_get_handle( BIT_NAME, BITS_PER_TAG, MB_TYPE_BIT, bit_data );CHECK_ERR( rval );
567 
568  Range verts;
569  rval = mb->get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
570 
571  std::vector< int > gids( verts.size() );
572  rval = mb->tag_get_data( gid, verts, &gids[0] );CHECK_ERR( rval );
573 
574  std::vector< unsigned char > exp( gids.size() ), act( gids.size() );
575  for( size_t i = 0; i < exp.size(); ++i )
576  exp[i] = bits_from_gid( gids[i] );
577 
578  rval = mb->tag_get_data( bit_data, verts, &act[0] );CHECK_ERR( rval );
579 
580  CHECK_EQUAL( exp, act );
581 }