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