MOAB: Mesh Oriented datABase  (version 5.5.0)
exodus_test.cpp
Go to the documentation of this file.
1 #include "TestUtil.hpp"
2 #include "moab/Core.hpp"
3 #include "MBTagConventions.hpp"
4 #include "moab/CN.hpp"
5 #include "moab/Range.hpp"
6 #include "ReadNCDF.hpp"
7 #include "moab/FileOptions.hpp"
8 #define IS_BUILDING_MB
9 #include "ExoIIUtil.hpp"
10 #include <cmath>
11 #include <algorithm>
12 
13 using namespace moab;
14 
15 /* Input test file: ho_test.g
16  *
17  * File is expected to contain at least one block for every
18  * supported higher-order element type. The coordinates of
19  * every higher-order node are expected to be the mean of the
20  * adjacent corner vertices of the element.
21  */
22 #ifdef MESHDIR
23 static const char ho_file[] = STRINGIFY( MESHDIR ) "/io/ho_test.g";
24 static const char file_one[] = STRINGIFY( MESHDIR ) "/mbtest1.g";
25 static const char alt_file[] = STRINGIFY( MESHDIR ) "/io/hex_2x2x2_ss.exo";
26 static const char polyg[] = STRINGIFY( MESHDIR ) "/io/poly8-10.vtk";
27 static const char polyh[] = STRINGIFY( MESHDIR ) "/io/polyhedra.vtk";
28 static const char rpolyg[] = STRINGIFY( MESHDIR ) "/io/polyg.exo";
29 static const char rpolyh[] = STRINGIFY( MESHDIR ) "/io/polyh.exo";
30 #else
31 static const char ho_file[] = "ho_test.g";
32 static const char file_one[] = "mbtest1.g";
33 static const char alt_file[] = "hex_2x2x2_ss.exo";
34 static const char polyg[] = "poly8-10.vtk";
35 static const char polyh[] = "polyhedra.vtk";
36 static const char rpolyg[] = "polyg.exo";
37 static const char rpolyh[] = "polyh.exo";
38 #endif
39 
40 void read_file( Interface& moab, const char* input_file );
41 
42 // Check that element has expected higher-order nodes
43 // and that each higher-order node is at the center
44 // of the sub-entity it is on.
45 void check_ho_element( Interface& moab, EntityHandle entity, int mid_nodes[4] );
46 
47 void test_read_side( int sideset_id, EntityType sideset_type, int sideset_nodes_per_elem, bool shell_side = false );
48 
49 // Validate elements of specified type.
50 // Looks for a block containing the specified entity type
51 // and with the specified mid-node flags set in its
52 // HAS_MID_NODES_TAG.
53 void test_ho_elements( EntityType type, int num_nodes );
54 
55 // Tests originally in MBTest.cpp
62 void mb_write_mesh_test();
63 
64 void test_types();
65 
66 void test_tri6()
67 {
68  test_ho_elements( MBTRI, 6 );
69 }
70 void test_tri7()
71 {
72  test_ho_elements( MBTRI, 7 );
73 }
74 
75 void test_quad5()
76 {
78 }
79 void test_quad8()
80 {
82 }
83 void test_quad9()
84 {
86 }
87 
88 void test_tet8()
89 {
90  test_ho_elements( MBTET, 8 );
91 }
92 void test_tet10()
93 {
94  test_ho_elements( MBTET, 10 );
95 }
96 void test_tet14()
97 {
98  test_ho_elements( MBTET, 14 );
99 }
100 
101 void test_hex9()
102 {
103  test_ho_elements( MBHEX, 9 );
104 }
106 {
107  test_ho_elements( MBHEX, 20 );
108 }
110 {
111  test_ho_elements( MBHEX, 27 );
112 }
113 
115 {
116  test_read_side( 1, MBEDGE, 3 );
117 } // sideset 1
119 {
120  test_read_side( 3, MBQUAD, 9, true );
121 } // sideset 3
123 {
124  test_read_side( 4, MBEDGE, 3 );
125 } // sideset 4
127 {
128  test_read_side( 2, MBQUAD, 8 );
129 } // sideset 2
130 
131 void test_read_block_ids();
132 void test_read_sideset_ids();
133 void test_read_nodeset_ids();
134 void test_write_polygons();
135 void test_write_polyhedra();
136 void test_read_polygons();
137 void test_read_polyhedra();
138 
140 
141 int main()
142 {
143  int result = 0;
144 
145  result += RUN_TEST( mb_vertex_coordinate_test );
146  result += RUN_TEST( mb_bar_connectivity_test );
147  result += RUN_TEST( mb_tri_connectivity_test );
148  result += RUN_TEST( mb_quad_connectivity_test );
149  result += RUN_TEST( mb_hex_connectivity_test );
150  result += RUN_TEST( mb_tet_connectivity_test );
151  result += RUN_TEST( mb_write_mesh_test );
152 
153  result += RUN_TEST( test_types );
154 
155  result += RUN_TEST( test_tri6 );
156  result += RUN_TEST( test_tri7 );
157  result += RUN_TEST( test_quad5 );
158  result += RUN_TEST( test_quad8 );
159  result += RUN_TEST( test_quad9 );
160  result += RUN_TEST( test_tet8 );
161  result += RUN_TEST( test_tet10 );
162  result += RUN_TEST( test_tet14 );
163  result += RUN_TEST( test_hex9 );
164  result += RUN_TEST( test_hex20 );
165  result += RUN_TEST( test_hex27 );
166 
167  result += RUN_TEST( test_read_tri6_side );
168  result += RUN_TEST( test_read_shell_side );
169  result += RUN_TEST( test_read_shell_edge );
170  result += RUN_TEST( test_read_hex20_side );
171 
172  result += RUN_TEST( test_read_block_ids );
173  result += RUN_TEST( test_read_sideset_ids );
174  result += RUN_TEST( test_read_nodeset_ids );
175 
177 
178  result += RUN_TEST( test_write_polygons );
179  result += RUN_TEST( test_write_polyhedra );
180  result += RUN_TEST( test_read_polygons );
181  result += RUN_TEST( test_read_polyhedra );
182 
183  return result;
184 }
185 
187 {
189  if( MB_SUCCESS != error )
190  {
191  std::cout << "Failed to load input file: " << file_one << std::endl;
192  std::string error_reason;
193  iface->get_last_error( error_reason );
194  std::cout << error_reason << std::endl;
195  }
196  CHECK_ERR( error );
197 }
198 
199 /*!
200  @test
201  Vertex Coordinates
202  @li Get coordinates of vertex 1 correctly
203  @li Get coordinates of vertex 8 correctly
204  @li Get coordinates of vertex 6 correctly
205 */
207 {
208  double coords[3];
209  EntityHandle handle;
211  int err;
212 
213  Core moab;
214  Interface* MB = &moab;
215  load_file_one( MB );
216 
217  // coordinate 2 should be {1.5, -1.5, 3.5}
218 
219  handle = CREATE_HANDLE( MBVERTEX, 2, err );
220  error = MB->get_coords( &handle, 1, coords );CHECK_ERR( error );
221  const double exp2[] = { 1.5, -1.5, 3.5 };
222  CHECK_ARRAYS_EQUAL( exp2, 3, coords, 3 );
223 
224  // coordinate 9 should be {1, -2, 3.5}
225  handle = CREATE_HANDLE( MBVERTEX, 9, err );
226  error = MB->get_coords( &handle, 1, coords );CHECK_ERR( error );
227  const double exp9[] = { 1, -2, 3.5 };
228  CHECK_ARRAYS_EQUAL( exp9, 3, coords, 3 );
229 
230  // coordinate 7 should be {0.5, -2, 3.5}
231  handle = CREATE_HANDLE( MBVERTEX, 7, err );
232  error = MB->get_coords( &handle, 1, coords );CHECK_ERR( error );
233  const double exp7[] = { 0.5, -2, 3.5 };
234  CHECK_ARRAYS_EQUAL( exp7, 3, coords, 3 );
235 
236  int node_count = 0;
237  error = MB->get_number_entities_by_type( 0, MBVERTEX, node_count );CHECK_ERR( error );
238  // Number of vertices (node_count) should be 83 assuming no gaps in the handle space
239  CHECK_EQUAL( 47, node_count );
240 }
241 
242 /*!
243  @test
244  MB Bar Element Connectivity Test
245  @li Get coordinates for 2 node bar elements
246 */
247 
249 {
250  Core moab;
251  Interface* MB = &moab;
252  load_file_one( MB );
253 
254  std::vector< EntityHandle > conn;
255  Range bars;
256 
258 
259  // get the connectivity of the second bar
260  EntityHandle handle = *( ++bars.begin() );
261 
262  error = MB->get_connectivity( &handle, 1, conn );CHECK_ERR( error );
263 
264  CHECK_EQUAL( (size_t)2, conn.size() );
265 
266  // from ncdump the connectivity of bar 2 (0 based) is
267  // 14, 13
268  CHECK_EQUAL( (EntityHandle)14, conn[0] );
269  CHECK_EQUAL( (EntityHandle)13, conn[1] );
270 
271  // Now try getting the connectivity of one of the vertices for fun.
272  // just return the vertex in the connectivity
273  handle = conn[0];
274  error = MB->get_connectivity( &handle, 1, conn );
275  CHECK_EQUAL( MB_FAILURE, error );
276 }
277 
279 {
280  Core moab;
281  Interface* MB = &moab;
282  load_file_one( MB );
283 
284  std::vector< EntityHandle > conn;
285  Range tris;
287 
288  // get the connectivity of the second tri
289  EntityHandle handle = *( ++tris.begin() );
290 
291  error = MB->get_connectivity( &handle, 1, conn );CHECK_ERR( error );
292 
293  CHECK_EQUAL( (size_t)3, conn.size() );
294 
295  // from ncdump the connectivity of tri 2 (0 based) is
296  // 45, 37, 38
297 
298  CHECK_EQUAL( (EntityHandle)45, conn[0] );
299  CHECK_EQUAL( (EntityHandle)37, conn[1] );
300  CHECK_EQUAL( (EntityHandle)38, conn[2] );
301 }
302 
304 {
305  Core moab;
306  Interface* MB = &moab;
307  load_file_one( MB );
308 
309  std::vector< EntityHandle > conn;
310  Range quads;
311 
313 
314  // get the connectivity of the second quad
315  EntityHandle handle = *( ++quads.begin() );
316 
317  error = MB->get_connectivity( &handle, 1, conn );CHECK_ERR( error );
318 
319  CHECK_EQUAL( (size_t)4, conn.size() );
320 
321  // from ncdump the connectivity of quad 2 (0 based) is
322  // 20, 11, 12, 26,
323 
324  CHECK_EQUAL( (EntityHandle)20, conn[0] );
325  CHECK_EQUAL( (EntityHandle)11, conn[1] );
326  CHECK_EQUAL( (EntityHandle)12, conn[2] );
327  CHECK_EQUAL( (EntityHandle)26, conn[3] );
328 }
329 
331 {
332  Core moab;
333  Interface* MB = &moab;
334  load_file_one( MB );
335 
336  std::vector< EntityHandle > conn;
337  Range hexes;
338 
340 
341  // get the connectivity of the second hex
342  EntityHandle handle = *( ++hexes.begin() );
343 
344  error = MB->get_connectivity( &handle, 1, conn );CHECK_ERR( error );
345 
346  CHECK_EQUAL( (size_t)8, conn.size() );
347 
348  // from ncdump the connectivity of hex 1 (0 based) is
349  // 19, 13, 16, 23, 21, 14, 18, 27
350 
351  CHECK_EQUAL( (EntityHandle)19, conn[0] );
352  CHECK_EQUAL( (EntityHandle)13, conn[1] );
353  CHECK_EQUAL( (EntityHandle)16, conn[2] );
354  CHECK_EQUAL( (EntityHandle)23, conn[3] );
355  CHECK_EQUAL( (EntityHandle)21, conn[4] );
356  CHECK_EQUAL( (EntityHandle)14, conn[5] );
357  CHECK_EQUAL( (EntityHandle)18, conn[6] );
358  CHECK_EQUAL( (EntityHandle)27, conn[7] );
359 }
360 
362 {
363  Core moab;
364  Interface* MB = &moab;
365  load_file_one( MB );
366 
367  std::vector< EntityHandle > conn;
368  Range tets;
370 
371  // get the connectivity of the second tet
372  EntityHandle handle = *( ++tets.begin() );
373 
374  error = MB->get_connectivity( &handle, 1, conn );CHECK_ERR( error );
375 
376  CHECK_EQUAL( (size_t)4, conn.size() );
377 
378  // from ncdump the connectivity of tet 2 (0 based) is:
379  // 35, 34, 32, 43
380 
381  CHECK_EQUAL( (EntityHandle)35, conn[0] );
382  CHECK_EQUAL( (EntityHandle)34, conn[1] );
383  CHECK_EQUAL( (EntityHandle)32, conn[2] );
384  CHECK_EQUAL( (EntityHandle)43, conn[3] );
385 }
386 
388 {
389  Core moab;
390  Interface* MB = &moab;
391  load_file_one( MB );
392  ErrorCode result;
393 
394  std::string file_name = "mb_write.g";
395 
396  // no need to get lists, write out the whole mesh
397  result = MB->write_mesh( file_name.c_str() );CHECK_ERR( result );
398 
399  //---------The following tests outputting meshsets that are in meshsets of blocks ---/
400 
401  // lets create a block meshset and put some entities and meshsets into it
402  EntityHandle block_ms;
403  result = MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, block_ms );CHECK_ERR( result );
404 
405  // make another meshset to put quads in, so SHELLs can be written out
406  EntityHandle block_of_shells;
407  result = MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, block_of_shells );CHECK_ERR( result );
408 
409  // tag the meshset so it's a block, with id 100
410  int id = 100;
411  Tag tag_handle;
412  const int negone = -1;
413  result = MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handle, 0, &negone );CHECK_ERR( result );
414  result = MB->tag_set_data( tag_handle, &block_ms, 1, &id );CHECK_ERR( result );
415  id = 101;
416  result = MB->tag_set_data( tag_handle, &block_of_shells, 1, &id );CHECK_ERR( result );
417 
418  // set dimension tag on this to ensure shells get output; reuse id variable
419  result = MB->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handle, 0, &negone );CHECK_ERR( result );
420  id = 3;
421  result = MB->tag_set_data( tag_handle, &block_of_shells, 1, &id );CHECK_ERR( result );
422 
423  // get some entities (tets)
424  Range temp_range;
425  result = MB->get_entities_by_type( 0, MBHEX, temp_range );CHECK_ERR( result );
426 
427  Range::iterator iter, end_iter;
428  iter = temp_range.begin();
429  end_iter = temp_range.end();
430 
431  // add evens to 'block_ms'
432  std::vector< EntityHandle > temp_vec;
433  for( ; iter != end_iter; ++iter )
434  {
435  if( ID_FROM_HANDLE( *iter ) % 2 == 0 ) temp_vec.push_back( *iter );
436  }
437  result = MB->add_entities( block_ms, &temp_vec[0], temp_vec.size() );CHECK_ERR( result );
438 
439  // make another meshset
440  EntityHandle ms_of_block_ms;
441  result = MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, ms_of_block_ms );CHECK_ERR( result );
442 
443  // add some entities to it
444  temp_vec.clear();
445  iter = temp_range.begin();
446  for( ; iter != end_iter; ++iter )
447  {
448  if( ID_FROM_HANDLE( *iter ) % 2 ) // add all odds
449  temp_vec.push_back( *iter );
450  }
451  result = MB->add_entities( ms_of_block_ms, &temp_vec[0], temp_vec.size() );CHECK_ERR( result );
452 
453  // add the other meshset to the block's meshset
454  result = MB->add_entities( block_ms, &ms_of_block_ms, 1 );CHECK_ERR( result );
455 
456  //---------------testing sidesets----------------/
457 
458  // lets create a sideset meshset and put some entities and meshsets into it
459  EntityHandle sideset_ms;
460  result = MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, sideset_ms );CHECK_ERR( result );
461 
462  // tag the meshset so it's a sideset, with id 104
463  id = 104;
464  result = MB->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handle, 0, &negone );CHECK_ERR( result );
465 
466  result = MB->tag_set_data( tag_handle, &sideset_ms, 1, &id );CHECK_ERR( result );
467 
468  // get some entities (tris)
469  temp_range.clear();
470  result = MB->get_entities_by_type( 0, MBQUAD, temp_range );CHECK_ERR( result );
471 
472  iter = temp_range.begin();
473  end_iter = temp_range.end();
474 
475  // add evens to 'sideset_ms'
476  temp_vec.clear();
477  for( ; iter != end_iter; ++iter )
478  {
479  if( ID_FROM_HANDLE( *iter ) % 2 == 0 ) temp_vec.push_back( *iter );
480  }
481  result = MB->add_entities( sideset_ms, &temp_vec[0], temp_vec.size() );CHECK_ERR( result );
482 
483  // make another meshset
484  EntityHandle ms_of_sideset_ms;
485  result = MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, ms_of_sideset_ms );CHECK_ERR( result );
486 
487  // add some entities to it
488  temp_vec.clear();
489  iter = temp_range.begin();
490  for( ; iter != end_iter; ++iter )
491  {
492  if( ID_FROM_HANDLE( *iter ) % 2 ) // add all odds
493  temp_vec.push_back( *iter );
494  }
495  result = MB->add_entities( ms_of_sideset_ms, &temp_vec[0], temp_vec.size() );CHECK_ERR( result );
496 
497  // add the other meshset to the sideset's meshset
498  result = MB->add_entities( sideset_ms, &ms_of_sideset_ms, 1 );CHECK_ERR( result );
499 
500  //---------test sense on meshsets (reverse/foward)-------//
501 
502  // get all quads whose x-coord = 2.5 and put them into a meshset_a
503  EntityHandle meshset_a;
504  result = MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, meshset_a );CHECK_ERR( result );
505 
506  temp_range.clear();
507  result = MB->get_entities_by_type( 0, MBQUAD, temp_range );CHECK_ERR( result );
508 
509  std::vector< EntityHandle > nodes1, entity_vec;
510  std::copy( temp_range.begin(), temp_range.end(), std::back_inserter( entity_vec ) );
511  result = MB->get_connectivity( &entity_vec[0], entity_vec.size(), nodes1 );CHECK_ERR( result );
512  assert( nodes1.size() == 4 * temp_range.size() );
513  temp_vec.clear();
514  std::vector< double > coords( 3 * nodes1.size() );
515  result = MB->get_coords( &nodes1[0], nodes1.size(), &coords[0] );CHECK_ERR( result );
516 
517  unsigned int k = 0;
518  for( Range::iterator it = temp_range.begin(); it != temp_range.end(); ++it )
519  {
520  if( coords[12 * k] == 2.5 && coords[12 * k + 3] == 2.5 && coords[12 * k + 6] == 2.5 &&
521  coords[12 * k + 9] == 2.5 )
522  temp_vec.push_back( *it );
523  k++;
524  }
525  result = MB->add_entities( meshset_a, ( temp_vec.empty() ) ? NULL : &temp_vec[0], temp_vec.size() );CHECK_ERR( result );
526  result = MB->add_entities( block_of_shells, ( temp_vec.empty() ) ? NULL : &temp_vec[0], temp_vec.size() );CHECK_ERR( result );
527 
528  // put these quads into a different meshset_b and tag them with a reverse sense tag
529  EntityHandle meshset_b;
530  result = MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, meshset_b );CHECK_ERR( result );
531 
532  result = MB->add_entities( meshset_b, &meshset_a, 1 );CHECK_ERR( result );
533 
534  result = MB->tag_get_handle( "SENSE", 1, MB_TYPE_INTEGER, tag_handle, MB_TAG_SPARSE | MB_TAG_CREAT );CHECK_ERR( result );
535 
536  int reverse_value = -1;
537  result = MB->tag_set_data( tag_handle, &meshset_b, 1, &reverse_value );CHECK_ERR( result );
538 
539  // get some random quad, whose x-coord != 2.5, and put it into a different meshset_c
540  // and tag it with a reverse sense tag
541 
542  iter = temp_range.begin();
543  end_iter = temp_range.end();
544 
545  temp_vec.clear();
546  for( ; iter != end_iter; ++iter )
547  {
548  std::vector< EntityHandle > nodes;
549  result = MB->get_connectivity( &( *iter ), 1, nodes );CHECK_ERR( result );
550 
551  bool not_equal_2_5 = true;
552  for( unsigned int ku = 0; ku < nodes.size(); ku++ )
553  {
554  double coords2[3] = { 0 };
555 
556  result = MB->get_coords( &( nodes[ku] ), 1, coords2 );CHECK_ERR( result );
557 
558  if( coords2[0] == 2.5 )
559  {
560  not_equal_2_5 = false;
561  break;
562  }
563  }
564 
565  if( not_equal_2_5 && nodes.size() > 0 )
566  {
567  temp_vec.push_back( *iter );
568  break;
569  }
570  }
571 
572  EntityHandle meshset_c;
573  MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, meshset_c );
574 
575  result = MB->tag_get_handle( "SENSE", 1, MB_TYPE_INTEGER, tag_handle );CHECK_ERR( result );
576 
577  reverse_value = -1;
578  result = MB->tag_set_data( tag_handle, &meshset_c, 1, &reverse_value );CHECK_ERR( result );
579 
580  MB->add_entities( meshset_c, &temp_vec[0], temp_vec.size() );
581  MB->add_entities( block_of_shells, &temp_vec[0], temp_vec.size() );
582 
583  // create another meshset_abc, adding meshset_a, meshset_b, meshset_c
584  EntityHandle meshset_abc;
585  MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, meshset_abc );
586 
587  temp_vec.clear();
588  temp_vec.push_back( meshset_a );
589  temp_vec.push_back( meshset_b );
590  temp_vec.push_back( meshset_c );
591 
592  MB->add_entities( meshset_abc, &temp_vec[0], temp_vec.size() );
593 
594  // tag it so it's a sideset
595  id = 444;
596  result = MB->tag_get_handle( "NEUMANN_SET", 1, MB_TYPE_INTEGER, tag_handle, 0, &negone );CHECK_ERR( result );
597 
598  result = MB->tag_set_data( tag_handle, &meshset_abc, 1, &id );CHECK_ERR( result );
599 
600  //---------------do nodesets now -----------------//
601 
602  // lets create a nodeset meshset and put some entities and meshsets into it
603  EntityHandle nodeset_ms;
604  MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, nodeset_ms );
605 
606  // tag the meshset so it's a nodeset, with id 119
607  id = 119;
608  result = MB->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handle, 0, &negone );CHECK_ERR( result );
609 
610  result = MB->tag_set_data( tag_handle, &nodeset_ms, 1, &id );CHECK_ERR( result );
611 
612  // get all Quads
613  temp_range.clear();
614  result = MB->get_entities_by_type( 0, MBQUAD, temp_range );CHECK_ERR( result );
615 
616  // get all the nodes of the tris
617  Range nodes_of_quads;
618  iter = temp_range.begin();
619  end_iter = temp_range.end();
620 
621  for( ; iter != end_iter; ++iter )
622  {
623  std::vector< EntityHandle > nodes;
624  result = MB->get_connectivity( &( *iter ), 1, nodes );CHECK_ERR( result );
625 
626  for( unsigned int ku = 0; ku < nodes.size(); ku++ )
627  nodes_of_quads.insert( nodes[ku] );
628  }
629 
630  iter = nodes_of_quads.begin();
631  end_iter = nodes_of_quads.end();
632 
633  // add evens to 'nodeset_ms'
634  temp_vec.clear();
635  for( ; iter != end_iter; ++iter )
636  {
637  if( ID_FROM_HANDLE( *iter ) % 2 == 0 ) temp_vec.push_back( *iter );
638  }
639  MB->add_entities( nodeset_ms, &temp_vec[0], temp_vec.size() );
640 
641  // make another meshset
642  EntityHandle ms_of_nodeset_ms;
643  MB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, ms_of_nodeset_ms );
644 
645  // add some entities to it
646  temp_vec.clear();
647  iter = nodes_of_quads.begin();
648  end_iter = nodes_of_quads.end();
649  for( ; iter != end_iter; ++iter )
650  {
651  if( ID_FROM_HANDLE( *iter ) % 2 ) // add all odds
652  temp_vec.push_back( *iter );
653  }
654  MB->add_entities( ms_of_nodeset_ms, &temp_vec[0], temp_vec.size() );
655 
656  // add the other meshset to the nodeset's meshset
657  MB->add_entities( nodeset_ms, &ms_of_nodeset_ms, 1 );
658 
659  // no need to get lists, write out the whole mesh
660  file_name = "mb_write2.g";
661  std::vector< EntityHandle > output_list;
662  output_list.push_back( block_ms );
663  output_list.push_back( sideset_ms );
664  output_list.push_back( meshset_abc );
665  output_list.push_back( nodeset_ms );
666  output_list.push_back( block_of_shells );
667  result = MB->write_mesh( file_name.c_str(), &output_list[0], output_list.size() );CHECK_ERR( result );
668 }
669 
670 struct TestType
671 {
672  EntityType moab_type;
675  std::string name;
676 };
677 
678 void check_type( const TestType& type )
679 {
680  int has_mid_nodes[4];
681  CN::HasMidNodes( type.moab_type, type.num_nodes, has_mid_nodes );
682 
684  CHECK_EQUAL( type.name, std::string( ExoIIUtil::ElementTypeNames[type.exo_type] ) );
686  auto dim = CN::Dimension( type.moab_type );
687  if( 3 == dim ) CHECK_EQUAL( has_mid_nodes[3], ExoIIUtil::HasMidNodes[type.exo_type][3] );
688  if( 2 <= dim ) CHECK_EQUAL( has_mid_nodes[2], ExoIIUtil::HasMidNodes[type.exo_type][2] );
689  if( 1 <= dim ) CHECK_EQUAL( has_mid_nodes[1], ExoIIUtil::HasMidNodes[type.exo_type][1] );
690 
691  Core moab;
692  ExoIIUtil tool( &moab );
693  CHECK_EQUAL( type.exo_type, tool.element_name_to_type( type.name.c_str() ) );
694  CHECK_EQUAL( type.name, std::string( tool.element_type_name( type.exo_type ) ) );
695 }
696 
698 {
699  const TestType types[] = { { MBVERTEX, EXOII_SPHERE, 1, "SPHERE" },
700  { MBEDGE, EXOII_SPRING, 1, "SPRING" },
701  { MBEDGE, EXOII_BAR, 2, "BAR" },
702  { MBEDGE, EXOII_BAR2, 2, "BAR2" },
703  { MBEDGE, EXOII_BAR3, 3, "BAR3" },
704  { MBEDGE, EXOII_BEAM, 2, "BEAM" },
705  { MBEDGE, EXOII_BEAM2, 2, "BEAM2" },
706  { MBEDGE, EXOII_BEAM3, 3, "BEAM3" },
707  { MBEDGE, EXOII_TRUSS, 2, "TRUSS" },
708  { MBEDGE, EXOII_TRUSS2, 2, "TRUSS2" },
709  { MBEDGE, EXOII_TRUSS3, 3, "TRUSS3" },
710  { MBTRI, EXOII_TRI, 3, "TRI" },
711  { MBTRI, EXOII_TRI3, 3, "TRI3" },
712  { MBTRI, EXOII_TRI6, 6, "TRI6" },
713  { MBTRI, EXOII_TRI7, 7, "TRI7" },
714  { MBQUAD, EXOII_QUAD, 4, "QUAD" },
715  { MBQUAD, EXOII_QUAD4, 4, "QUAD4" },
716  { MBQUAD, EXOII_QUAD5, 5, "QUAD5" },
717  { MBQUAD, EXOII_QUAD8, 8, "QUAD8" },
718  { MBQUAD, EXOII_QUAD9, 9, "QUAD9" },
719  { MBQUAD, EXOII_SHELL, 4, "SHELL" },
720  { MBQUAD, EXOII_SHELL4, 4, "SHELL4" },
721  { MBQUAD, EXOII_SHELL5, 5, "SHELL5" },
722  { MBQUAD, EXOII_SHELL8, 8, "SHELL8" },
723  { MBQUAD, EXOII_SHELL9, 9, "SHELL9" },
724  { MBTET, EXOII_TETRA, 4, "TETRA" },
725  { MBTET, EXOII_TETRA4, 4, "TETRA4" },
726  { MBTET, EXOII_TET4, 4, "TET4" },
727  { MBTET, EXOII_TETRA8, 8, "TETRA8" },
728  { MBTET, EXOII_TETRA10, 10, "TETRA10" },
729  { MBTET, EXOII_TETRA14, 14, "TETRA14" },
730  { MBPYRAMID, EXOII_PYRAMID, 5, "PYRAMID" },
731  { MBPYRAMID, EXOII_PYRAMID5, 5, "PYRAMID5" },
732  { MBPYRAMID, EXOII_PYRAMID10, 10, "PYRAMID10" },
733  { MBPYRAMID, EXOII_PYRAMID13, 13, "PYRAMID13" },
734  { MBPYRAMID, EXOII_PYRAMID18, 18, "PYRAMID18" },
735  { MBPRISM, EXOII_WEDGE, 6, "WEDGE" },
736  { MBKNIFE, EXOII_KNIFE, 7, "KNIFE" },
737  { MBHEX, EXOII_HEX, 8, "HEX" },
738  { MBHEX, EXOII_HEX8, 8, "HEX8" },
739  { MBHEX, EXOII_HEX9, 9, "HEX9" },
740  { MBHEX, EXOII_HEX20, 20, "HEX20" },
741  { MBHEX, EXOII_HEX27, 27, "HEX27" },
742  { MBHEX, EXOII_HEXSHELL, 12, "HEXSHELL" } };
743  const int num_types = sizeof( types ) / sizeof( types[0] );
744  for( int i = 0; i < num_types; ++i )
745  check_type( types[i] );
746 }
747 
748 void read_file( Interface& moab, const char* input_file )
749 {
750  ErrorCode rval = moab.load_file( input_file );CHECK_ERR( rval );
751 }
752 
753 void write_and_read( Interface& write_mb, Interface& read_mb, EntityHandle block = 0 )
754 {
755  const char* tmp_file = "exodus_test_tmp.g";
756  ErrorCode rval;
757 
758  EntityHandle* write_set_list = &block;
759  int write_set_list_len = 0; //(block != 0);
760  rval = write_mb.write_file( tmp_file, "EXODUS", 0, write_set_list, write_set_list_len );
761  if( MB_SUCCESS != rval ) remove( tmp_file );CHECK_ERR( rval );
762 
763  rval = read_mb.load_file( tmp_file );
764  remove( tmp_file );CHECK_ERR( rval );
765 }
766 
767 void check_ho_elements( Interface& moab, EntityHandle block, EntityType type, int mid_nodes[4] )
768 {
769  ErrorCode rval;
770  Range elems;
771  rval = moab.get_entities_by_handle( block, elems, ( type != MBENTITYSET ? true : false ) );CHECK_ERR( rval );
772  CHECK( !elems.empty() );
773  CHECK( elems.all_of_type( type ) );
774  for( Range::const_iterator i = elems.begin(); i != elems.end(); ++i )
775  check_ho_element( moab, *i, mid_nodes );
776 }
777 
778 // Check that element has expected higher-order nodes
779 // and that each higher-order node is at the center
780 // of the sub-entity it is on.
781 void check_ho_element( Interface& moab, EntityHandle entity, int mid_nodes[4] )
782 {
783  // get element info
784  const EntityType type = TYPE_FROM_HANDLE( entity );
785  const EntityHandle* conn;
786  int conn_len;
787  ErrorCode rval = moab.get_connectivity( entity, conn, conn_len );CHECK_ERR( rval );
788  std::vector< double > coords( 3 * conn_len );
789  rval = moab.get_coords( conn, conn_len, &coords[0] );CHECK_ERR( rval );
790 
791  // calculate and verify expected number of mid nodes
792  int num_nodes = CN::VerticesPerEntity( type );
793  for( int d = 1; d <= CN::Dimension( type ); ++d )
794  if( mid_nodes[d] ) num_nodes += CN::NumSubEntities( type, d );
795  CHECK_EQUAL( num_nodes, conn_len );
796 
797  // verify that each higher-order node is at the center
798  // of its respective sub-entity.
799  for( int i = CN::VerticesPerEntity( type ); i < num_nodes; ++i )
800  {
801  // get sub-entity owning ho-node
802  int sub_dim, sub_num;
803  CN::HONodeParent( type, num_nodes, i, sub_dim, sub_num );
804  // get corner vertex indices
805  int sub_conn[8], num_sub;
806  if( sub_dim < CN::Dimension( type ) )
807  {
808  CN::SubEntityVertexIndices( type, sub_dim, sub_num, sub_conn );
809  EntityType sub_type = CN::SubEntityType( type, sub_dim, sub_num );
810  num_sub = CN::VerticesPerEntity( sub_type );
811  }
812  else
813  {
814  num_sub = CN::VerticesPerEntity( type );
815  for( int j = 0; j < num_sub; ++j )
816  sub_conn[j] = j;
817  }
818  // calculate mean of corner vertices
819  double mean[3] = { 0, 0, 0 };
820  for( int j = 0; j < num_sub; ++j )
821  {
822  int co = 3 * sub_conn[j];
823  mean[0] += coords[co];
824  mean[1] += coords[co + 1];
825  mean[2] += coords[co + 2];
826  }
827  mean[0] /= num_sub;
828  mean[1] /= num_sub;
829  mean[2] /= num_sub;
830  // verify that higher-order node is at expected location
831  CHECK_REAL_EQUAL( mean[0], coords[3 * i], 1e-6 );
832  CHECK_REAL_EQUAL( mean[1], coords[3 * i + 1], 1e-6 );
833  CHECK_REAL_EQUAL( mean[2], coords[3 * i + 2], 1e-6 );
834  }
835 }
836 
837 EntityHandle find_block( Interface& mb, EntityType type, const int has_mid_nodes[4] )
838 {
839 
840  ErrorCode rval;
841  Tag ho_tag, block_tag;
842  const int negone = -1;
843  rval = mb.tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, block_tag, 0, &negone );CHECK_ERR( rval );
844  const int mids[] = { -1, -1, -1, -1 };
845  rval = mb.tag_get_handle( HAS_MID_NODES_TAG_NAME, 4, MB_TYPE_INTEGER, ho_tag, 0, mids );CHECK_ERR( rval );
846 
847  // get material sets with expected higher-order nodes
848  Range blocks;
849  Tag tags[2] = { ho_tag, block_tag };
850  const void* vals[2] = { has_mid_nodes, NULL };
851  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, tags, vals, 2, blocks );CHECK_ERR( rval );
852 
853  for( Range::iterator i = blocks.begin(); i != blocks.end(); ++i )
854  {
855  int n;
856  rval = mb.get_number_entities_by_type( *i, type, n );CHECK_ERR( rval );
857  if( n > 0 ) return *i;
858  }
859 
860  CHECK( false ); // no block matching element type description
861  return 0;
862 }
863 
864 EntityHandle find_sideset( Interface& mb, int sideset_id, EntityType /*side_type*/ )
865 {
866  ErrorCode rval;
867  Tag ss_tag;
868  const int negone = -1;
869  rval = mb.tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ss_tag, 0, &negone );CHECK_ERR( rval );
870 
871  const void* tag_vals[] = { &sideset_id };
872  Range side_sets;
873  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &ss_tag, tag_vals, 1, side_sets );CHECK_ERR( rval );
874  CHECK_EQUAL( 1, (int)side_sets.size() );
875  return side_sets.front();
876 }
877 
878 // Validate elements of specified type.
879 // Looks for a block containing the specified entity type
880 // and with the specified mid-node flags set in its
881 // HAS_MID_NODES_TAG.
882 void test_ho_elements( EntityType type, int num_nodes )
883 {
884  Core mb_impl1, mb_impl2;
885  Interface &mb1 = mb_impl1, &mb2 = mb_impl2;
886  int ho_flags[4];
887  CN::HasMidNodes( type, num_nodes, ho_flags );
888 
889  // read file
890  read_file( mb1, ho_file );
891  // test element connectivity order
892  EntityHandle block = find_block( mb1, type, ho_flags );
893  CHECK( block != 0 );
894  check_ho_elements( mb1, block, type, ho_flags );
895 
896  // write block and read it back in
897  write_and_read( mb1, mb2, block );
898  // test element connectivity order on re-read data
899  block = find_block( mb2, type, ho_flags );
900  CHECK( block != 0 );
901  check_ho_elements( mb2, block, type, ho_flags );
902 }
903 
904 void test_read_side( int id, EntityType sideset_type, int sideset_nodes_per_elem, bool shell_side )
905 {
906  // read test file
907  Core mb_impl;
908  Interface& moab = mb_impl;
909  read_file( moab, ho_file );
910 
911  // get side set
912  EntityHandle set = find_sideset( moab, id, sideset_type );
913  CHECK( set != 0 );
914 
915  // check expected element connectivity
916  int ho_flags[4];
917  CN::HasMidNodes( sideset_type, sideset_nodes_per_elem, ho_flags );
918  check_ho_elements( moab, set, sideset_type, ho_flags );
919 
920  if( shell_side ) return;
921 
922  // check that each element is on the boundary of the mesh
923  Range elems;
924  ErrorCode rval = mb_impl.get_entities_by_handle( set, elems );CHECK_ERR( rval );
925 
926  int dim = CN::Dimension( sideset_type );
927  for( Range::iterator i = elems.begin(); i != elems.end(); ++i )
928  {
929  Range adj;
930  rval = mb_impl.get_adjacencies( &*i, 1, dim + 1, false, adj, Interface::UNION );CHECK_ERR( rval );
931  CHECK_EQUAL( 1, (int)adj.size() );
932  }
933 }
934 
935 void test_read_ids_common( const char* file_name, const char* tag_name, const int* expected_vals, int num_expected )
936 {
937  Core mb;
938  ReadNCDF reader( &mb );
939 
940  FileOptions opts( "" );
941  std::vector< int > values;
942  ErrorCode rval = reader.read_tag_values( file_name, tag_name, opts, values );CHECK_ERR( rval );
943 
944  std::vector< int > expected( expected_vals, expected_vals + num_expected );
945  std::sort( values.begin(), values.end() );
946  std::sort( expected.begin(), expected.end() );
947  CHECK_EQUAL( expected, values );
948 }
949 
951 {
952  const int expected[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
953  test_read_ids_common( ho_file, MATERIAL_SET_TAG_NAME, expected, sizeof( expected ) / sizeof( expected[0] ) );
954 }
955 
957 {
958  const int expected[] = { 1, 2, 3, 4 };
959  test_read_ids_common( ho_file, NEUMANN_SET_TAG_NAME, expected, sizeof( expected ) / sizeof( expected[0] ) );
960 }
961 
963 {
965 }
966 
968 {
969  Core moab;
970  Interface& mb = moab;
971  ErrorCode rval = mb.load_file( alt_file );CHECK_ERR( rval );
972 
973  const double exp[] = { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1 };
974 
975  Range hexes;
976  rval = mb.get_entities_by_type( 0, MBHEX, hexes );CHECK_ERR( rval );
977  CHECK_EQUAL( (size_t)1, hexes.size() );
978  EntityHandle hex = hexes.front();
979  const EntityHandle* conn;
980  int len;
981  rval = mb.get_connectivity( hex, conn, len );CHECK_ERR( rval );
982  CHECK_EQUAL( 8, len );
983  double act[3 * 8];
984  rval = mb.get_coords( conn, len, act );CHECK_ERR( rval );
985  CHECK_ARRAYS_EQUAL( exp, 3 * 8, act, 3 * 8 );
986 }
988 {
989  Core moab;
990  Interface& mb = moab;
991  ErrorCode rval = mb.load_file( polyg );CHECK_ERR( rval );
992  rval = mb.write_file( "polyg.exo" );CHECK_ERR( rval );
993 }
994 
996 {
997  Core moab;
998  Interface& mb = moab;
999  ErrorCode rval = mb.load_file( polyh );CHECK_ERR( rval );
1000  rval = mb.write_file( "polyh.exo" );CHECK_ERR( rval );
1001 }
1003 {
1004  Core moab;
1005  Interface& mb = moab;
1006  ErrorCode rval = mb.load_file( rpolyg );CHECK_ERR( rval );
1007 }
1009 {
1010  Core moab;
1011  Interface& mb = moab;
1012  ErrorCode rval = mb.load_file( rpolyh );CHECK_ERR( rval );
1013 }