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