MOAB: Mesh Oriented datABase  (version 5.5.0)
h5varlen.cpp
Go to the documentation of this file.
1 #include "moab/Core.hpp"
2 #include "TestUtil.hpp"
3 #include "moab/Range.hpp"
4 
5 #ifdef MOAB_HAVE_MPI
6 #include "moab_mpi.h"
7 #endif
8 
9 #include <cstdlib>
10 #include <cstdio>
11 
12 using namespace moab;
13 
14 static bool keep_files = false;
15 
17 
19 
21 
23 
25 
27 
29 
31 
33 
35 
37 
38 void create_mesh( Interface& mb );
39 
41 
42 void compare_tags( const char* name, Interface& mb1, Interface& mb2 );
43 
44 void read_write( const char* filename, Interface& write, Interface& reader );
45 
46 #define CHECK_ERR_FILE( ERRCODE, FILENAME ) \
47  do \
48  { \
49  if( MB_SUCCESS != ( ERRCODE ) && !keep_files ) remove( FILENAME ); \
50  CHECK_ERR( ERRCODE ); \
51  while( false )
52 
53 int main( int argc, char* argv[] )
54 {
55 #ifdef MOAB_HAVE_MPI
56  int fail = MPI_Init( &argc, &argv );
57  if( fail ) return fail;
58 #endif
59 
60  if( argc != 1 )
61  {
62  if( argc != 2 || strcmp( argv[1], "-k" ) != 0 )
63  {
64  fprintf( stderr, "Usage: %s [-k]\n", argv[0] );
65  abort();
66  }
67  keep_files = true;
68  }
69 
70  int err_count = 0;
71  err_count += RUN_TEST( test_var_length_no_data );
72  err_count += RUN_TEST( test_var_length_data );
73  err_count += RUN_TEST( test_var_length_big_data );
74  err_count += RUN_TEST( test_var_length_opaque );
75  err_count += RUN_TEST( test_var_length_mesh_data );
76  err_count += RUN_TEST( test_var_length_default_data );
77  err_count += RUN_TEST( test_var_length_mesh_opaque );
79  err_count += RUN_TEST( test_var_length_handle_tag );
80  err_count += RUN_TEST( test_var_length_data_big );
81 
82  err_count += RUN_TEST( test_huge_var_length );
83 
84 #ifdef MOAB_HAVE_MPI
85  fail = MPI_Finalize();
86  if( fail ) return fail;
87 #endif
88 
89  return err_count;
90 }
91 
93 {
94  ErrorCode rval;
95  Core moab1, moab2;
96  Interface &mb1 = moab1, &mb2 = moab2;
97  Tag tag;
98 
99  create_mesh( mb1 );
100  rval = mb1.tag_get_handle( "test_tag", 0, MB_TYPE_DOUBLE, tag, MB_TAG_EXCL | MB_TAG_VARLEN | MB_TAG_DENSE );CHECK_ERR( rval );
101 
102  read_write( "test_var_length_no_data.h5m", mb1, mb2 );
103  compare_tags( "test_tag", mb1, mb2 );
104 }
105 
106 void test_var_length_data_common( const char* filename, Interface& mb1, bool opaque = false )
107 {
108  // create tag
109  ErrorCode rval;
110  Tag tag;
111  DataType type = opaque ? MB_TYPE_OPAQUE : MB_TYPE_INTEGER;
112  rval = mb1.tag_get_handle( "test_tag", 0, type, tag, MB_TAG_EXCL | MB_TAG_VARLEN | MB_TAG_SPARSE );CHECK_ERR( rval );
113 
114  // get all entities
115  Range entities;
116  rval = mb1.get_entities_by_handle( 0, entities );CHECK_ERR( rval );
117 
118  // Set tag data.
119  // Tag data will be list of integer data as follows:
120  // number of values (counting this value)
121  // step, 2*step, 3*step, ...
122  for( Range::const_iterator i = entities.begin(); i != entities.end(); ++i )
123  {
124  EntityHandle h = *i;
125  // generate some data to write
126  int num_values = h % 6 + 1;
127  EntityType etype = mb1.type_from_handle( h );
128  int step = ( h % 2 ) ? 1 + (int)etype : -1 - (int)etype;
129  std::vector< int > tag_data( num_values, num_values );
130  for( int j = 1; j < num_values; ++j )
131  tag_data[j] = j * step;
132  // set tag data
133  const void* ptrarr[] = { &tag_data[0] };
134  if( opaque ) num_values *= sizeof( int );
135  rval = mb1.tag_set_by_ptr( tag, &h, 1, ptrarr, &num_values );CHECK_ERR( rval );
136  }
137 
138  // write and read tag data
139  Core moab;
140  Interface& mb2 = moab;
141  read_write( filename, mb1, mb2 );
142  compare_tags( "test_tag", mb1, mb2 );
143 
144  // get new tag handle
145  tag = 0;
146  rval = mb2.tag_get_handle( "test_tag", 0, type, tag );CHECK_ERR( rval );
147 
148  // check consistency of tag values
149  entities.clear();
151  // remove sets created during read/write process
152  Range sets;
153  mb2.get_entities_by_type( 0, MBENTITYSET, sets );
154  entities = subtract( entities, sets );
155  for( Range::const_iterator i = entities.begin(); i != entities.end(); ++i )
156  {
157  // get data
158  const void* ptrarr[] = { NULL };
159  int size;
160  rval = mb2.tag_get_by_ptr( tag, &*i, 1, ptrarr, &size );CHECK_ERR( rval );
161  if( opaque )
162  {
163  CHECK_EQUAL( (size_t)0, size % sizeof( int ) );
164  size /= sizeof( int );
165  }
166  const int* dataptr = reinterpret_cast< const int* >( ptrarr[0] );
167  CHECK( NULL != dataptr );
168  // check size
169  CHECK( size > 0 );
170  CHECK_EQUAL( size, dataptr[0] );
171  // check other values
172  if( size > 2 )
173  {
174  int step = dataptr[1];
175  for( int j = 2; j < size; ++j )
176  CHECK_EQUAL( j * step, dataptr[j] );
177  }
178  }
179 }
180 
182 {
183  Core moab;
184  create_mesh( moab );
185  test_var_length_data_common( "test_var_length_data.h5m", moab );
186 }
187 
189 {
190  Core moab;
192  test_var_length_data_common( "test_var_length_data_big.h5m", moab );
193 }
194 
195 void calculate_big_value( Interface& moab, EntityHandle vert, size_t size, double* data )
196 {
197  // Make values like Fibonacci numbers, except use X and Y coords
198  // rather than 0 and 1 as first two values.
199 
200  CHECK( size >= 3 );
201  ErrorCode rval = moab.get_coords( &vert, 1, data );CHECK_ERR( rval );
202 
203  for( size_t j = 2; j < size; ++j )
204  data[j] = data[j - 2] + data[j - 1];CHECK_ERR( rval );
205 }
206 
208 {
209  ErrorCode rval;
210  Core moab1, moab2;
211  Interface &mb1 = moab1, &mb2 = moab2;
212  Tag tag;
213 
214  create_mesh( mb1 );
215  rval = mb1.tag_get_handle( "test_tag", 0, MB_TYPE_DOUBLE, tag, MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_EXCL );CHECK_ERR( rval );
216 
217  // choose 3 vertices upon which to set data
218  Range range;
219  rval = mb1.get_entities_by_type( 0, MBVERTEX, range );CHECK_ERR( rval );
220  EntityHandle verts[3] = { range.front(), *( range.begin() += range.size() / 3 ),
221  *( range.begin() += 2 * range.size() / 3 ) };
222 
223  // set 1-millon value tag data on three vertices
224  std::vector< double > data( 1000000 );
225  for( int i = 0; i < 3; ++i )
226  {
227  calculate_big_value( mb1, verts[i], data.size(), &data[0] );
228  const void* ptr = &data[0];
229  const int size = data.size();
230  rval = mb1.tag_set_by_ptr( tag, verts + i, 1, &ptr, &size );CHECK_ERR( rval );
231  }
232 
233  read_write( "test_var_length_big_data.h5m", mb1, mb2 );
234  compare_tags( "test_tag", mb1, mb2 );
235 
236  // check 3 tagged vertices
237  rval = mb2.tag_get_handle( "test_tag", 0, MB_TYPE_DOUBLE, tag );CHECK_ERR( rval );
238  range.clear();
239  rval = mb2.get_entities_by_type_and_tag( 0, MBVERTEX, &tag, 0, 1, range, Interface::UNION );CHECK_ERR( rval );
240  CHECK_EQUAL( (size_t)3, range.size() );
241 
242  // check tag values
243  for( Range::const_iterator i = range.begin(); i != range.end(); ++i )
244  {
245  // calculate expected value
246  const EntityHandle h = *i;
247  calculate_big_value( mb2, h, data.size(), &data[0] );
248 
249  // get actual value
250  const void* ptr;
251  int size;
252  rval = mb2.tag_get_by_ptr( tag, &h, 1, &ptr, &size );CHECK_ERR( rval );
253  CHECK_EQUAL( data.size(), (size_t)size );
254 
255  // compare values
256  const double* act_data = reinterpret_cast< const double* >( ptr );
257  int wrong_count = 0;
258  for( size_t j = 0; j < data.size(); ++j )
259  if( act_data[j] != data[j] ) ++wrong_count;
260  CHECK_EQUAL( 0, wrong_count );
261  }
262 }
263 
265 {
266  Core moab;
267  create_mesh( moab );
268  test_var_length_data_common( "test_var_length_opaque.h5m", moab, true );
269 }
270 
271 void test_global_value_common( bool mesh_value )
272 {
273  Core moab;
274  Interface& mb = moab;
275  create_mesh( mb );
276 
277  // get three vertices
278  Range vertices;
279  ErrorCode rval = mb.get_entities_by_type( 0, MBVERTEX, vertices );CHECK_ERR( rval );
280  CHECK( vertices.size() >= 3 );
281  EntityHandle handles[3];
282  Range::const_iterator i = vertices.begin();
283  handles[0] = *i;
284  ++i;
285  handles[1] = *i;
286  ++i;
287  handles[2] = *i;
288  ++i;
289 
290  // get vertex coordinates
291  double coords[9];
292  rval = mb.get_coords( handles, 3, coords );CHECK_ERR( rval );
293 
294  // create tag to hold vertex data
295  Tag handle_tag = 0;
296  void* default_val = mesh_value ? 0 : handles;
297  int default_val_size = mesh_value ? 0 : 3;
298  rval = mb.tag_get_handle( "handle_tag", default_val_size, MB_TYPE_HANDLE, handle_tag,
299  MB_TAG_DENSE | MB_TAG_VARLEN | MB_TAG_EXCL, default_val );CHECK_ERR( rval );
300 
301  // create tag to hold vertex coordinates
302  Tag coord_tag = 0;
303  default_val = mesh_value ? 0 : coords;
304  default_val_size = mesh_value ? 0 : 9;
305  rval = mb.tag_get_handle( "coord_tag", default_val_size, MB_TYPE_DOUBLE, coord_tag,
306  MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_EXCL, default_val );CHECK_ERR( rval );
307 
308  // if doing mesh tag, set it
309  if( mesh_value )
310  {
311  int size = 3;
312  const void* ptrarr[] = { handles };
313  const EntityHandle root = 0;
314  rval = mb.tag_set_by_ptr( handle_tag, &root, 1, ptrarr, &size );CHECK_ERR( rval );
315 
316  size = 9;
317  ptrarr[0] = coords;
318  rval = mb.tag_set_by_ptr( coord_tag, &root, 1, ptrarr, &size );CHECK_ERR( rval );
319  }
320 
321  // write and read file
322  Core moab2;
323  Interface& mb2 = moab2;
324  read_write( mesh_value ? "test_var_length_mesh_data.h5m" : "test_var_length_default_data.h5m", mb, mb2 );
325  compare_tags( "handle_tag", mb, mb2 );
326  compare_tags( "coord_tag", mb, mb2 );
327 
328  // get tag handles
329  handle_tag = coord_tag = 0;
330  rval = mb2.tag_get_handle( "handle_tag", 0, MB_TYPE_HANDLE, handle_tag );CHECK_ERR( rval );
331  rval = mb2.tag_get_handle( "coord_tag", 0, MB_TYPE_DOUBLE, coord_tag );CHECK_ERR( rval );
332 
333  // get tag data
334  int handle_tag_size = 0, coord_tag_size = 0;
335  const void* ptrs[2];
336  if( mesh_value )
337  {
338  const EntityHandle root = 0;
339  rval = mb2.tag_get_by_ptr( handle_tag, &root, 1, ptrs, &handle_tag_size );CHECK_ERR( rval );
340  rval = mb2.tag_get_by_ptr( coord_tag, &root, 1, ptrs + 1, &coord_tag_size );CHECK_ERR( rval );
341  }
342  else
343  {
344  rval = mb2.tag_get_default_value( handle_tag, ptrs[0], handle_tag_size );CHECK_ERR( rval );
345  rval = mb2.tag_get_default_value( coord_tag, ptrs[1], coord_tag_size );CHECK_ERR( rval );
346  }
347 
348  // check expected sizes
349  CHECK_EQUAL( 3, handle_tag_size );
350  CHECK_EQUAL( 9, coord_tag_size );
351  CHECK( ptrs[0] != NULL );
352  CHECK( ptrs[1] != NULL );
353 
354  // check valid handles
355  const EntityHandle* handle_vals = reinterpret_cast< const EntityHandle* >( ptrs[0] );
356  CHECK( handle_vals[0] != 0 );
357  CHECK( handle_vals[1] != 0 );
358  CHECK( handle_vals[2] != 0 );
359  CHECK_EQUAL( MBVERTEX, mb2.type_from_handle( handle_vals[0] ) );
360  CHECK_EQUAL( MBVERTEX, mb2.type_from_handle( handle_vals[1] ) );
361  CHECK_EQUAL( MBVERTEX, mb2.type_from_handle( handle_vals[2] ) );
362 
363  // check correct coordinate values
364  const double* coord_vals = reinterpret_cast< const double* >( ptrs[1] );
365  rval = mb2.get_coords( handle_vals, 3, coords );CHECK_ERR( rval );
366  CHECK_REAL_EQUAL( coords[0], coord_vals[0], 1e-12 );
367  CHECK_REAL_EQUAL( coords[1], coord_vals[1], 1e-12 );
368  CHECK_REAL_EQUAL( coords[2], coord_vals[2], 1e-12 );
369  CHECK_REAL_EQUAL( coords[3], coord_vals[3], 1e-12 );
370  CHECK_REAL_EQUAL( coords[4], coord_vals[4], 1e-12 );
371  CHECK_REAL_EQUAL( coords[5], coord_vals[5], 1e-12 );
372  CHECK_REAL_EQUAL( coords[6], coord_vals[6], 1e-12 );
373  CHECK_REAL_EQUAL( coords[7], coord_vals[7], 1e-12 );
374  CHECK_REAL_EQUAL( coords[8], coord_vals[8], 1e-12 );
375 }
376 
378 {
379  test_global_value_common( true );
380 }
381 
383 {
384  test_global_value_common( false );
385 }
386 
387 void test_global_opaque_common( bool mesh_value )
388 {
389  ErrorCode rval;
390  Core moab;
391  Interface& mb = moab;
392  create_mesh( mb );
393 
394  const char data[] = { 'J', 'A', 'S', 'O', 'N' };
395  const int datalen = sizeof( data );
396  CHECK_EQUAL( 5, datalen );
397 
398  // create tag
399  Tag tag = 0;
400  const void* default_val = mesh_value ? 0 : data;
401  int default_val_size = mesh_value ? 0 : datalen;
402  rval = mb.tag_get_handle( "opaque_tag", default_val_size, MB_TYPE_OPAQUE, tag,
403  MB_TAG_DENSE | MB_TAG_VARLEN | MB_TAG_EXCL, default_val );CHECK_ERR( rval );
404 
405  // if doing mesh tag, set it
406  if( mesh_value )
407  {
408  const void* ptrarr[] = { data };
409  const EntityHandle root = 0;
410  rval = mb.tag_set_by_ptr( tag, &root, 1, ptrarr, &datalen );CHECK_ERR( rval );
411  }
412 
413  // write and read file
414  Core moab2;
415  Interface& mb2 = moab2;
416  read_write( mesh_value ? "test_var_length_mesh_opaque.h5m" : "test_var_length_default_opaque.h5m", mb, mb2 );
417  compare_tags( "opaque_tag", mb, mb2 );
418 
419  // get tag handles
420  tag = 0;
421  rval = mb2.tag_get_handle( "opaque_tag", 0, MB_TYPE_OPAQUE, tag );CHECK_ERR( rval );
422 
423  // get tag data
424  int tag_size = 0;
425  const void* ptrs[1];
426  if( mesh_value )
427  {
428  const EntityHandle root = 0;
429  rval = mb2.tag_get_by_ptr( tag, &root, 1, ptrs, &tag_size );CHECK_ERR( rval );
430  }
431  else
432  {
433  rval = mb2.tag_get_default_value( tag, ptrs[0], tag_size );CHECK_ERR( rval );
434  }
435 
436  // check size
437  CHECK_EQUAL( datalen, tag_size );
438  CHECK( ptrs[0] != NULL );
439 
440  // check values
441  const char* tag_data = reinterpret_cast< const char* >( ptrs[0] );
442  for( int i = 0; i < datalen; ++i )
443  CHECK_EQUAL( data[i], tag_data[i] );
444 }
445 
447 {
449 }
450 
452 {
453  test_global_opaque_common( false );
454 }
455 
457 {
458  ErrorCode rval;
459  Core moab1, moab2;
460  Interface &mb1 = moab1, &mb2 = moab2;
461  Tag tag;
463 
464  create_mesh( mb1 );
465  rval = mb1.tag_get_handle( "test_tag", 0, MB_TYPE_HANDLE, tag, MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_EXCL );CHECK_ERR( rval );
466 
467  // Get all entities
468  Range range;
469  rval = mb1.get_entities_by_handle( 0, range );CHECK_ERR( rval );
470 
471  // For each entity, if it is a vertex store its own handle
472  // in its tag. Otherwise store the element connectivity list
473  // in the tag. Skip entity sets.
474  size_t num_tagged_entities = 0;
475  for( i = range.begin(); i != range.end(); ++i )
476  {
477  EntityHandle h = *i;
478  EntityType type = mb1.type_from_handle( h );
479  if( type == MBVERTEX )
480  {
481  const int size = 1;
482  const void* ptr = &h;
483  rval = mb1.tag_set_by_ptr( tag, &h, 1, &ptr, &size );CHECK_ERR( rval );
484  ++num_tagged_entities;
485  }
486  else if( type != MBENTITYSET )
487  {
488  int size = 0;
489  const EntityHandle* conn = 0;
490  rval = mb1.get_connectivity( h, conn, size );CHECK_ERR( rval );
491  const void* ptr = conn;
492  rval = mb1.tag_set_by_ptr( tag, &h, 1, &ptr, &size );CHECK_ERR( rval );
493  ++num_tagged_entities;
494  }
495  }
496 
497  read_write( "test_var_length_handle_tag.h5m", mb1, mb2 );
498  compare_tags( "test_tag", mb1, mb2 );
499 
500  // check number of tagged entities
501  rval = mb2.tag_get_handle( "test_tag", 0, MB_TYPE_HANDLE, tag );CHECK_ERR( rval );
502  range.clear();
503  for( EntityType t = MBVERTEX; t != MBENTITYSET; ++t )
504  {
505  rval = mb2.get_entities_by_type_and_tag( 0, t, &tag, 0, 1, range, Interface::UNION );CHECK_ERR( rval );
506  }
507  CHECK_EQUAL( num_tagged_entities, range.size() );
508 
509  // check tag values
510  for( i = range.begin(); i != range.end(); ++i )
511  {
512  EntityHandle h = *i;
513 
514  const void* ptr;
515  int size;
516  rval = mb2.tag_get_by_ptr( tag, &h, 1, &ptr, &size );CHECK_ERR( rval );
517 
518  const EntityHandle* handles = reinterpret_cast< const EntityHandle* >( ptr );
519 
520  if( mb2.type_from_handle( h ) == MBVERTEX )
521  {
522  CHECK_EQUAL( 1, size );
523  CHECK_EQUAL( h, *handles );
524  }
525  else
526  {
527  int len;
528  const EntityHandle* conn;
529  rval = mb2.get_connectivity( h, conn, len );CHECK_ERR( rval );
530  CHECK_EQUAL( len, size );
531  for( int j = 0; j < len; ++j )
532  CHECK_EQUAL( conn[j], handles[j] );
533  }
534  }
535 }
536 
538 {
539  ErrorCode rval;
540  Core moab1, moab2;
541  Interface &mb1 = moab1, &mb2 = moab2;
542  Tag tag;
544 
545  create_mesh( mb1 );
546  rval = mb1.tag_get_handle( "test_tag", 0, MB_TYPE_DOUBLE, tag, MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_EXCL );CHECK_ERR( rval );
547 
548  // Get all entities
549  Range range;
550  rval = mb1.get_entities_by_handle( 0, range );CHECK_ERR( rval );
551 
552  // For each entity, if it is a vertex store its own handle
553  // in its tag. Otherwise store the element connectivity list
554  // in the tag. Skip entity sets.
555  EntityHandle v1 = range[0]; // first vertex
556  // huge data
557  std::vector< double > dataArr; // larger than the buffer
558  int N = 2000;
559  dataArr.resize( N ); // size will be 8 * N > bufferSize = 10000 set by option during writing
560  for( int j = 0; j < N; j++ )
561  dataArr[j] = j;
562  const void* ptr = &dataArr[0];
563  rval = mb1.tag_set_by_ptr( tag, &v1, 1, &ptr, &N );CHECK_ERR( rval );
564  // second vertex, do a smaller N
565  v1 = range[1];
566  int M = N - 5;
567  ptr = &dataArr[2]; // start with 2
568  rval = mb1.tag_set_by_ptr( tag, &v1, 1, &ptr, &M );CHECK_ERR( rval );
569 
570  // write with a smaller buffer, size controlled by option to test
571  const char* writeOptions = "BUFFER_SIZE=4000;DEBUG_IO=5";
572  rval = mb1.write_file( "test_huge_var_tag.h5m", NULL, writeOptions );CHECK_ERR( rval );
573  rval = mb2.load_file( "test_huge_var_tag.h5m" );CHECK_ERR( rval );
574  compare_tags( "test_tag", mb1, mb2 );
575  // compare some values for the 2nd vertex
576  Tag tag2;
577  rval = mb2.tag_get_handle( "test_tag", tag2 );CHECK_ERR( rval );
578  EntityHandle vertex2 = 2;
579  int len2;
580  const void* ptr2;
581  rval = mb2.tag_get_by_ptr( tag2, &vertex2, 1, &ptr2, &len2 );CHECK_ERR( rval );
582  CHECK_EQUAL( len2, M );
583 
584  CHECK_REAL_EQUAL( dataArr[2], ( (double*)ptr2 )[0], 0.000000001 );
585 
586  if( !keep_files ) remove( "test_huge_var_tag.h5m" );CHECK_ERR( rval );
587 }
589 {
590  ErrorCode rval;
591 
592  const double z = 2.1;
593  std::vector< EntityHandle > verts( ( x + 1 ) * ( y + 1 ) );
594  for( int i = 0; i <= x; ++i )
595  {
596  for( int j = 0; j <= y; ++j )
597  {
598  double coords[3] = { static_cast< double >( i ), static_cast< double >( j ), static_cast< double >( z ) };
599  rval = mb.create_vertex( coords, verts[i + ( x + 1 ) * j] );CHECK_ERR( rval );
600  }
601  }
602 
603  std::vector< EntityHandle > elems( x * y );
604  for( int i = 0; i < x; ++i )
605  {
606  for( int j = 0; j < y; ++j )
607  {
608  EntityHandle conn[4] = { verts[i + ( x + 1 ) * j], verts[i + 1 + ( x + 1 ) * j],
609  verts[i + 1 + ( x + 1 ) * ( j + 1 )], verts[i + ( x + 1 ) * ( j + 1 )] };
610  rval = mb.create_element( MBQUAD, conn, 4, elems[i + x * j] );CHECK_ERR( rval );
611  }
612  }
613 }
614 
616 {
618 }
619 
621 {
622  create_structured_quad_mesh( mb, 300, 300 );
623 }
624 
625 void compare_tags( const char* name, Interface& mb1, Interface& mb2 )
626 {
627  ErrorCode rval;
628  Tag tag1, tag2;
629  rval = mb1.tag_get_handle( name, 0, MB_TYPE_OPAQUE, tag1, MB_TAG_ANY );CHECK_ERR( rval );
630  rval = mb2.tag_get_handle( name, 0, MB_TYPE_OPAQUE, tag2, MB_TAG_ANY );CHECK_ERR( rval );
631 
632  int size;
635 
636  TagType storage1, storage2;
637  rval = mb1.tag_get_type( tag1, storage1 );CHECK_ERR( rval );
638  rval = mb2.tag_get_type( tag2, storage2 );CHECK_ERR( rval );
639  CHECK_EQUAL( storage1, storage2 );
640 
641  DataType type1, type2;
642  rval = mb1.tag_get_data_type( tag1, type1 );CHECK_ERR( rval );
643  rval = mb2.tag_get_data_type( tag2, type2 );CHECK_ERR( rval );
644 
645  const void *defval1, *defval2;
646  int defsize1, defsize2;
647  ErrorCode rval1 = mb1.tag_get_default_value( tag1, defval1, defsize1 );
648  ErrorCode rval2 = mb2.tag_get_default_value( tag2, defval2, defsize2 );
649  if( MB_SUCCESS == rval1 )
650  {
651  CHECK_ERR( rval2 );
652 
653  CHECK_EQUAL( defsize1, defsize2 );
654  CHECK( !memcmp( defval1, defval2, defsize1 ) );
655  }
656  else if( MB_ENTITY_NOT_FOUND == rval1 || MB_TAG_NOT_FOUND == rval1 )
657  CHECK_EQUAL( rval1, rval2 );
658  else
659  CHECK_ERR( rval1 );
660 }
661 
662 void read_write( const char* filename, Interface& writer, Interface& reader )
663 {
664  ErrorCode rval = writer.write_file( filename );
665  if( !keep_files && MB_SUCCESS != rval ) remove( filename );CHECK_ERR( rval );
666  rval = reader.load_mesh( filename );
667  if( !keep_files ) remove( filename );CHECK_ERR( rval );
668 }