1 #include "moab/Core.hpp"
2 #include "moab/Range.hpp"
3 #include "TestRunner.hpp"
4 #include "ReadHDF5.hpp"
5 #include "MBTagConventions.hpp"
6 #include "moab/FileOptions.hpp"
7 
8 #ifdef MOAB_HAVE_MPI
9 #include "moab_mpi.h"
10 #endif
11 
12 #include <vector>
13 #include <stdlib.h>
14 #include <iostream>
15 #include <algorithm>
16 #include <limits>
17 
18 using namespace moab;
19 
20 const char TEST_FILE[] = "partial.h5m";
21 #define READ_OPTS "BUFFER_SIZE=256"
22 const char ID_TAG_NAME[] = "test_id_tag";
23 
24 
25 static void test_read_nothing_common( bool non_existant );
26 static void test_read_nodes_common( int num_read_sets, bool blocked_coordinate_io );
27 static void test_read_handle_tag_common( bool var_len );
28 
29 const int MBQUAD_INT = 20;
30 const int NUM_SETS = 10;
31 const int SET_WIDTH = (MBQUAD_INT + NUM_SETS - 1) / NUM_SETS; // ceil(MBQUAD_INT/NUM_SETS)
32 const char LOGICAL_NAME[] = "logical";   // tag storing logical (i,j) coordinates
33 const char CENTROID_NAME[] = "centroid"; // tag storing position of centroid (x,y,0)
34 //! Create a regular MBQUAD_INT^2 element quad mesh with regularly
35 //! spaced coordinates in the range [1,100].  Group elements
36 //! into 10 vertical strips MBQUAD_INT/10 elements wide.  Tag elements,
37 //! vertices and/or sets with ID in [1,10] stored in ID_TAG_NAME
38 //! tag.  Write new mesh to TEST_FILE.
39 void create_mesh( bool create_element_sets,
40                   bool create_vertex_sets,
41                   bool tag_elements_with_id,
42                   bool tag_vertices_with_id,
43                   const char* adj_elem_tag_name = 0,
44                   bool var_len_adj_elems = false );
45 // Given a list of vertices adjacent to a quad strip, identify it as one of the
46 // NUM_SETS strips of quads written by create_mesh.
47 int identify_set( Interface& mb, const Range& verts );
48 int identify_set( Interface& mb, EntityHandle set );
49 
50 static Tag check_tag( Interface& mb,
51                         const char* name,
52                         TagType storage,
53                         DataType type,
54                         int size );
55 
56 enum GatherTestMode { GATHER_SETS, GATHER_CONTENTS, GATHER_NONE };
57 void test_gather_sets_common( bool contained_sets, GatherTestMode mode, bool no_parent_containing_sets = false );
58 void test_gather_sets_ranged( bool contained_sets, GatherTestMode mode, bool no_parent_containing_sets = false );
59 
60 
61 //! Read a set containing no entities
test_read_empty_set()62 void test_read_empty_set()
63   { test_read_nothing_common( false ); }
64 
65 //! Specify ID that doesn't exist in file
test_read_non_existant_set()66 void test_read_non_existant_set()
67   { test_read_nothing_common( true ); }
68 
69 //! Read in the nodes contained in a set.
test_read_one_set_nodes()70 void test_read_one_set_nodes()
71   { test_read_nodes_common(1, false); }
72 
73 //! Read in the nodes contained in a set.
test_read_one_set_nodes_blocked()74 void test_read_one_set_nodes_blocked()
75   { test_read_nodes_common(1, true); }
76 
77 //! Read in the elems contained in a set
78 void test_read_one_set_elems();
79 
80 //! Read in the polyhedra contained in a set
81 void test_read_one_set_polyhedra();
82 
83 //! Read in the sets contained in a set.
84 //! Should read all sets containing read elements or nodes
85 //! and all sets that are contained the the specified "read"
86 //! set.  Test the later here.
87 void test_read_set_sets();
88 
89 //! Read in the nodes contained in a sets.
test_read_two_sets_nodes()90 void test_read_two_sets_nodes()
91   { test_read_nodes_common(2,false); }
92 
93 //! Read in the elems contained in a sets
94 void test_read_two_sets_elems();
95 
96 //! For any set selected to be read by either explicit designation,
97 //! containing read entities, or contained in an explcitly designated
98 //! set, any child sets are also read.  Check that here.
test_read_child_sets_only()99 void test_read_child_sets_only()
100 { test_gather_sets_common( false, GATHER_SETS);
101   test_gather_sets_ranged( false, GATHER_SETS); }
test_read_child_set_contents()102 void test_read_child_set_contents()
103 { test_gather_sets_common( false, GATHER_CONTENTS);
104   test_gather_sets_ranged( false, GATHER_CONTENTS); }
test_read_no_child_sets()105 void test_read_no_child_sets()
106 { test_gather_sets_common( false, GATHER_NONE);
107   test_gather_sets_ranged( false, GATHER_NONE); }
108 
109 //! For any set selected to be read by either explicit designation,
110 //! containing read entities, or contained in an explcitly designated
111 //! set, any contained sets are also read.  Check that here.
test_read_contained_sets_only()112 void test_read_contained_sets_only()
113 { test_gather_sets_common( true, GATHER_SETS, true);
114   test_gather_sets_ranged( true, GATHER_SETS); }
test_read_contained_set_contents()115 void test_read_contained_set_contents()
116 { test_gather_sets_common( true, GATHER_CONTENTS, true );
117   test_gather_sets_ranged( true, GATHER_CONTENTS); }
test_read_no_contained_sets()118 void test_read_no_contained_sets()
119 { test_gather_sets_common( true, GATHER_NONE, true );
120   test_gather_sets_ranged( true, GATHER_NONE); }
121 
122 //! Read in the sets contained in a set.
123 //! Should read all sets containing read elements or nodes
124 //! and all sets that are contained the the specified "read"
125 //! set.  Test the former here.
126 void test_read_containing_sets();
127 
128 //! Test reading of explicit adjacencies
129 void test_read_adjacencies();
130 
131 //! Test reading of sparse double tag data
132 void test_read_double_tag();
133 
134 //! Test reading of sparse opaque tag data
135 void test_read_opaque_tag();
136 
137 //! Test reading of sparse handle tag data
test_read_handle_tag()138 void test_read_handle_tag()
139   { test_read_handle_tag_common(false); }
140 
141 //! Test reading of variable-length tag data
test_var_len_tag()142 void test_var_len_tag()
143   { test_read_handle_tag_common(true); }
144 
145 void test_read_tagged_elems();
146 
147 void test_read_tagged_nodes();
148 
149 void test_read_sides();
150 
151 void test_read_ids();
152 
153 void test_read_partial_ids();
154 
main(int argc,char * argv[])155 int main( int argc, char* argv[] )
156 {
157 #ifdef MOAB_HAVE_MPI
158   int fail = MPI_Init(&argc, &argv);
159   if (fail) return fail;
160 #endif
161 
162   REGISTER_TEST(test_read_empty_set);
163   REGISTER_TEST(test_read_non_existant_set);
164   REGISTER_TEST(test_read_one_set_nodes);
165   REGISTER_TEST(test_read_one_set_nodes_blocked);
166   REGISTER_TEST(test_read_one_set_elems);
167   REGISTER_TEST(test_read_one_set_polyhedra);
168   REGISTER_TEST(test_read_set_sets);
169   REGISTER_TEST(test_read_two_sets_nodes);
170   REGISTER_TEST(test_read_two_sets_elems);
171   REGISTER_TEST(test_read_child_sets_only);
172   REGISTER_TEST(test_read_child_set_contents);
173   REGISTER_TEST(test_read_no_child_sets);
174   REGISTER_TEST(test_read_contained_sets_only);
175   REGISTER_TEST(test_read_contained_set_contents);
176   REGISTER_TEST(test_read_no_contained_sets);
177   REGISTER_TEST(test_read_containing_sets);
178   REGISTER_TEST(test_read_double_tag);
179   REGISTER_TEST(test_read_opaque_tag);
180   REGISTER_TEST(test_read_handle_tag);
181   REGISTER_TEST(test_var_len_tag);
182   REGISTER_TEST(test_read_adjacencies);
183   REGISTER_TEST(test_read_tagged_elems);
184   REGISTER_TEST(test_read_tagged_nodes);
185   REGISTER_TEST(test_read_sides);
186   REGISTER_TEST(test_read_ids);
187   REGISTER_TEST(test_read_partial_ids);
188   int result = RUN_TESTS( argc, argv );
189 
190 #ifdef MOAB_HAVE_MPI
191   fail = MPI_Finalize();
192   if (fail) return fail;
193 #endif
194 
195   return result;
196 }
197 
test_read_nothing_common(bool non_existant)198 void test_read_nothing_common( bool non_existant )
199 {
200   ErrorCode rval;
201   Core moab;
202   Interface& mb = moab;
203 
204   // create a few nodes to write to file
205   std::vector<double> coords( 3000 );
206   Range verts;
207   rval= mb.create_vertices( &coords[0], coords.size()/3, verts );
208   CHECK_ERR(rval);
209 
210   // create three entity sets
211   EntityHandle sets[3];
212   rval = mb.create_meshset( MESHSET_SET, sets[0] );
213   CHECK_ERR(rval);
214   rval = mb.create_meshset( MESHSET_SET, sets[1] );
215   CHECK_ERR(rval);
216   rval = mb.create_meshset( MESHSET_ORDERED, sets[2] );
217   CHECK_ERR(rval);
218 
219   // put all vertices into two of the sets
220   rval = mb.add_entities( sets[0], verts );
221   CHECK_ERR(rval);
222   rval = mb.add_entities( sets[2], verts );
223   CHECK_ERR(rval);
224 
225   // tag all three sets
226   Tag id_tag;
227   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
228   CHECK_ERR(rval);
229   int ids[3] = { 5, 7, 9 };
230   rval = mb.tag_set_data( id_tag, sets, 3, ids );
231   CHECK_ERR(rval);
232 
233   // write mesh
234   rval = mb.write_file( TEST_FILE, "MOAB" );
235   CHECK_ERR(rval);
236   rval = mb.delete_mesh();
237   CHECK_ERR(rval);
238 
239   // now read back in only the empty set
240   EntityHandle file_set;
241   int id = non_existant ? 8 : 7;
242   rval = mb.create_meshset( MESHSET_SET, file_set );
243   CHECK_ERR(rval);
244   rval = mb.load_file( TEST_FILE, &file_set, READ_OPTS, ID_TAG_NAME, &id, 1 );
245   if (non_existant) {
246     CHECK_EQUAL( MB_ENTITY_NOT_FOUND, rval );
247     return;
248   }
249   else
250     CHECK_ERR( rval );
251 
252   // the file should contain exactly two sets (the specified one and the new
253   // file set, and nothing else.)
254   for (EntityType t = MBVERTEX; t < MBENTITYSET; ++t) {
255     int count = -1;
256     rval = mb.get_number_entities_by_type( 0, t, count );
257     CHECK_ERR(rval);
258     CHECK_EQUAL( 0, count );
259   }
260   Range setrange;
261   rval = mb.get_entities_by_type( 0, MBENTITYSET, setrange );
262   CHECK_ERR(rval);
263   CHECK_EQUAL( (non_existant ? 1 : 2), (int)setrange.size() );
264   CHECK( setrange.find(file_set) != setrange.end() );
265 }
266 
267 
vtx_coords(int set_id,int j,int num_sets,double coords[3])268 static void vtx_coords( int set_id, int j, int num_sets, double coords[3] )
269 {
270   int i = num_sets*j + set_id;
271   coords[0] = i;
272   coords[1] = i+0.25;
273   coords[2] = i+0.5;
274 }
275 
test_read_nodes_common(int num_read_sets,bool blocked)276 void test_read_nodes_common( int num_read_sets, bool blocked )
277 {
278   ErrorCode rval;
279   Core moab;
280   Interface& mb = moab;
281 
282     // create 1000 nodes
283   const int num_sets = 2*num_read_sets;
284   std::vector<EntityHandle> verts(1000);
285   std::vector< std::vector<EntityHandle> > set_verts(num_sets);
286   for (size_t i = 0; i < verts.size(); ++i) {
287     double coords[3];
288     int j = i % num_sets;
289     vtx_coords( j+1, set_verts[j].size(), num_sets, coords );
290     rval = mb.create_vertex( coords, verts[i] );
291     set_verts[ j ].push_back( verts[i] );
292     CHECK_ERR(rval);
293   }
294 
295     // create two sets, each containing half of the nodes
296   std::vector<EntityHandle> sets(num_sets);
297   for (int i = 0; i < num_sets; ++i) {
298     rval = mb.create_meshset( MESHSET_ORDERED, sets[i] );
299     CHECK_ERR(rval);
300     rval = mb.add_entities( sets[i], &set_verts[i][0], set_verts[i].size() );
301     CHECK_ERR(rval);
302   }
303 
304     // tag both sets
305   Tag id_tag;
306   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
307   CHECK_ERR(rval);
308   std::vector<int> values( num_sets );
309   for (int i = 0; i < num_sets; ++i) values[i] = i+1;
310   rval = mb.tag_set_data( id_tag, &sets[0], num_sets, &values[0] );
311   CHECK_ERR(rval);
312 
313     // write file
314   rval = mb.write_file( TEST_FILE, "MOAB" );
315   CHECK_ERR(rval);
316   rval = mb.delete_mesh();
317   CHECK_ERR(rval);
318 
319     // now read back in only the specified number of sets
320   std::string opts(READ_OPTS);
321   if (!opts.empty())
322     opts += ';';
323   if (blocked)
324     opts += "BLOCKED_COORDINATE_IO=yes";
325   else
326     opts += "BLOCKED_COORDINATE_IO=no";
327 
328   values.resize( num_read_sets );
329   for (int i = 0; i < num_read_sets; ++i) values[i] = 2*(i+1);
330   EntityHandle file_set;
331   rval = mb.create_meshset( MESHSET_SET, file_set );
332   CHECK_ERR(rval);
333   rval = mb.load_file( TEST_FILE, &file_set, opts.c_str(), ID_TAG_NAME, &values[0], num_read_sets );
334   CHECK_ERR(rval);
335 
336   int count, expected = 0;
337   rval = mb.get_number_entities_by_dimension( 0, 0, count );
338   CHECK_ERR(rval);
339   for (int i = 0; i < num_sets; ++i)
340     if (i % 2)
341       expected += set_verts[i].size();
342   CHECK_EQUAL( expected, count );
343 
344   Range sets2;
345   rval = mb.get_entities_by_type( 0, MBENTITYSET, sets2 );
346   CHECK_ERR(rval);
347   CHECK_EQUAL( 1+num_read_sets, (int)sets2.size() );
348   Range::iterator it = sets2.find( file_set );
349   CHECK( it != sets2.end() );
350   sets2.erase( it );
351 
352   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag );
353   CHECK_ERR(rval);
354   while (!sets2.empty()) {
355     EntityHandle set = sets2.pop_front();
356     int id;
357     rval = mb.tag_get_data( id_tag, &set, 1, &id );
358     CHECK_ERR(rval);
359     CHECK( std::find(values.begin(), values.end(), id) != values.end() );
360     CHECK( id > 0 );
361     CHECK( (unsigned)id <= set_verts.size() );
362 
363     std::vector<EntityHandle> verts2;
364     rval = mb.get_entities_by_handle( set, verts2 );
365     CHECK_ERR(rval);
366     CHECK_EQUAL( set_verts[id-1].size(), verts2.size() );
367 
368     for (size_t i = 0; i < verts2.size(); ++i) {
369       double exp_coords[3], coords[3];
370       vtx_coords( id, i, num_sets, exp_coords );
371       rval = mb.get_coords( &verts2[i], 1, coords );
372       CHECK_ERR(rval);
373       CHECK_REAL_EQUAL( exp_coords[0], coords[0], 1e-12 );
374       CHECK_REAL_EQUAL( exp_coords[1], coords[1], 1e-12 );
375       CHECK_REAL_EQUAL( exp_coords[2], coords[2], 1e-12 );
376     }
377   }
378 }
379 
380 //! Create a regular MBQUAD_INT^2 element quad mesh with regularly
381 //! spaced coordinates in the range [1,100].  Group elements
382 //! into 10 vertical strips MBQUAD_INT/10 elements wide.  Tag elements,
383 //! vertices and/or sets with ID in [1,10] stored in ID_TAG_NAME
384 //! tag.  Write new mesh to TEST_FILE.
create_mesh(bool create_element_sets,bool create_vertex_sets,bool tag_elements_with_id,bool tag_vertices_with_id,const char * adj_elem_tag_name,bool var_len_adj_elems)385 void create_mesh( bool create_element_sets,
386                   bool create_vertex_sets,
387                   bool tag_elements_with_id,
388                   bool tag_vertices_with_id,
389                   const char* adj_elem_tag_name,
390                   bool var_len_adj_elems )
391 {
392   Core moab;
393   Interface& mb = moab;
394   ErrorCode rval;
395 
396     // create tags
397   Tag logical_tag, centroid_tag, id_tag;
398   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
399   CHECK_ERR(rval);
400   rval = mb.tag_get_handle( LOGICAL_NAME, 2*sizeof(int), MB_TYPE_OPAQUE, logical_tag, MB_TAG_DENSE|MB_TAG_EXCL );
401   CHECK_ERR(rval);
402   rval = mb.tag_get_handle( CENTROID_NAME, 3, MB_TYPE_DOUBLE, centroid_tag, MB_TAG_DENSE|MB_TAG_EXCL );
403   CHECK_ERR(rval);
404 
405   EntityHandle sets[NUM_SETS];
406   if (create_element_sets || create_vertex_sets) {
407     for (int i = 0; i < NUM_SETS; ++i) {
408       rval = mb.create_meshset( MESHSET_ORDERED, sets[i] );
409       CHECK_ERR(rval);
410       int id = i+1;
411       rval = mb.tag_set_data( id_tag, &sets[i], 1, &id );
412       CHECK_ERR(rval);
413     }
414   }
415 
416     // create elements
417   EntityHandle verts[MBQUAD_INT+1][MBQUAD_INT+1], quads[MBQUAD_INT][MBQUAD_INT];
418   for (int i = 0; i <= MBQUAD_INT; ++i) for(int j = 0; j <= MBQUAD_INT; ++j) {
419       double coords[3] = { static_cast<double>(i), static_cast<double>(j), 0 };
420     rval = mb.create_vertex( coords, verts[j][i] );
421     CHECK_ERR(rval);
422     int logical[2] = { i, j };
423     rval = mb.tag_set_data( logical_tag, &verts[j][i], 1, logical );
424     CHECK_ERR(rval);
425     rval = mb.tag_set_data( centroid_tag, &verts[j][i], 1, coords );
426     CHECK_ERR(rval);
427     int id = (i-1)/SET_WIDTH + 1; // Note: assumes SET_WIDTH > 1
428     if (tag_vertices_with_id) {
429       rval = mb.tag_set_data( id_tag, &verts[j][i], 1, &id );
430       CHECK_ERR(rval);
431     }
432     if (create_vertex_sets) {
433       rval = mb.add_entities( sets[id-1], &verts[j][i], 1 );
434       CHECK_ERR(rval);
435         // Some vertices are shared by quads in different sets.
436         // put such vertices in both sets.
437       int id2 = i/SET_WIDTH + 1;
438       if (id2 != id && id2 <= NUM_SETS) {
439         rval = mb.add_entities( sets[id2-1], &verts[j][i], 1 );
440         CHECK_ERR(rval);
441       }
442     }
443   }
444   for (int i = 0; i < MBQUAD_INT; ++i) for(int j = 0; j < MBQUAD_INT; ++j) {
445     EntityHandle conn[4] = { verts[j  ][i  ],
446                                verts[j  ][i+1],
447                                verts[j+1][i+1],
448                                verts[j+1][i  ] };
449     rval = mb.create_element( MBQUAD, conn, 4, quads[j][i] );
450     CHECK_ERR(rval);
451     int logical[2] = { i, j };
452     rval = mb.tag_set_data( logical_tag, &quads[j][i], 1, logical );
453     CHECK_ERR(rval);
454     double centroid[3] = { i + 0.5, j + 0.5, 0 };
455     rval = mb.tag_set_data( centroid_tag, &quads[j][i], 1, centroid );
456     CHECK_ERR(rval);
457     int id = i/SET_WIDTH + 1;
458     if (tag_elements_with_id) {
459       rval = mb.tag_set_data( id_tag, &quads[j][i], 1, &id );
460       CHECK_ERR(rval);
461     }
462     if (create_element_sets) {
463       rval = mb.add_entities( sets[id-1], &quads[j][i], 1 );
464       CHECK_ERR(rval);
465     }
466   }
467 
468   if (adj_elem_tag_name && !var_len_adj_elems) {
469     Tag handle_tag;
470     rval = mb.tag_get_handle( adj_elem_tag_name,
471                               4,
472                               MB_TYPE_HANDLE,
473                               handle_tag,
474                               MB_TAG_DENSE|MB_TAG_EXCL );
475     CHECK_ERR(rval);
476     for (int i = 0; i <= MBQUAD_INT; ++i) for(int j = 0; j <= MBQUAD_INT; ++j) {
477       EntityHandle val[4] = { (i > 0        && j > 0       ) ? quads[j-1][i-1] : 0,
478                                 (i > 0        && j < MBQUAD_INT) ? quads[j  ][i-1] : 0,
479                                 (i < MBQUAD_INT && j < MBQUAD_INT) ? quads[j  ][i  ] : 0,
480                                 (i < MBQUAD_INT && j > 0       ) ? quads[j-1][i  ] : 0 };
481       rval = mb.tag_set_data( handle_tag, &verts[j][i], 1, val );
482       CHECK_ERR(rval);
483     }
484   }
485   else if (adj_elem_tag_name && var_len_adj_elems) {
486     Tag handle_tag;
487     rval = mb.tag_get_handle( adj_elem_tag_name,
488                               0, MB_TYPE_HANDLE,
489                               handle_tag,
490                               MB_TAG_DENSE|MB_TAG_VARLEN|MB_TAG_EXCL );
491     CHECK_ERR(rval);
492     for (int i = 0; i <= MBQUAD_INT; ++i) for(int j = 0; j <= MBQUAD_INT; ++j) {
493       EntityHandle val[4];
494       int num = 0;
495       if (i > 0        && j > 0       ) val[num++] = quads[j-1][i-1];
496       if (i > 0        && j < MBQUAD_INT) val[num++] = quads[j  ][i-1];
497       if (i < MBQUAD_INT && j < MBQUAD_INT) val[num++] = quads[j  ][i  ];
498       if (i < MBQUAD_INT && j > 0       ) val[num++] = quads[j-1][i  ];
499       const void* ptr = val;
500       rval = mb.tag_set_by_ptr( handle_tag, &verts[j][i], 1, &ptr, &num );
501       CHECK_ERR(rval);
502     }
503   }
504 
505   rval = mb.write_file( TEST_FILE, "MOAB" );
506   CHECK_ERR(rval);
507 }
508 
509 // Given a list of vertices adjacent to a quad strip, identify it as one of the
510 // NUM_SETS strips of quads written by create_mesh.
identify_set(Interface & mb,const Range & verts)511 int identify_set( Interface& mb, const Range& verts )
512 {
513   const int COL = SET_WIDTH+1;
514   CHECK_EQUAL( (1+MBQUAD_INT)*COL, (int)verts.size() );
515 
516     // Get X range of vertices
517   int min_x = std::numeric_limits<int>::max();
518   int max_x = std::numeric_limits<int>::min();
519   for (Range::const_iterator i = verts.begin(); i != verts.end(); ++i) {
520     double coords[3];
521     ErrorCode rval = mb.get_coords( &*i, 1, coords );
522     CHECK_ERR(rval);
523       // Expect whole-valued coorindates
524     int int_x = (int)coords[0];
525     CHECK( fabs( coords[0] - (double)int_x ) < 1e-12 );
526 
527     if (int_x < min_x) min_x = int_x;
528     if (int_x > max_x) max_x = int_x;
529   }
530   CHECK( max_x - min_x < COL );
531 
532     // Calculate ID (return value) from coordinate range)
533   const int ID = min_x / SET_WIDTH + 1;
534 
535     // Now verify that all vertices correctly form a grid
536   EntityHandle grid[MBQUAD_INT+1][COL];
537   memset( grid, 0, sizeof(grid) );
538   for (Range::const_iterator i = verts.begin(); i != verts.end(); ++i) {
539     double coords[3];
540     ErrorCode rval = mb.get_coords( &*i, 1, coords );
541     CHECK_ERR(rval);
542       // Expect whole-valued coorindates
543     int x = (int)coords[0] - (ID-1)*SET_WIDTH, y = (int)coords[1];
544     CHECK( fabs( coords[1] - (double)y ) < 1e-12 );
545     CHECK( fabs( coords[2] ) < 1e-12 );
546     CHECK( y >= 0 && y <= MBQUAD_INT );
547     CHECK_EQUAL( (EntityHandle)0, grid[y][x] );
548     grid[y][x] = *i;
549   }
550 
551   return ID;
552 }
identify_set(Interface & mb,EntityHandle set)553 int identify_set( Interface& mb, EntityHandle set )
554 {
555   ErrorCode rval;
556   Range verts, elems;
557   rval = mb.get_entities_by_handle( set, elems );
558   CHECK_ERR(rval);
559   Range::iterator it = elems.upper_bound( MBVERTEX );
560   verts.merge( elems.begin(), it );
561   elems.erase( elems.begin(), it );
562   it = elems.lower_bound( MBENTITYSET );
563   elems.erase( it, elems.end() );
564   rval = mb.get_adjacencies( elems, 0, false, verts, Interface::UNION );
565   CHECK_ERR(rval);
566   return identify_set( mb, verts );
567 }
568 
569 //! Read in the elems contained in a set
test_read_one_set_elems()570 void test_read_one_set_elems()
571 {
572   ErrorCode rval;
573   Core moab;
574   Interface& mb = moab;
575 
576   create_mesh( true, false, false, false );
577 
578   for (int id = 1; id <= NUM_SETS; ++id) {
579     rval = mb.delete_mesh();
580     CHECK_ERR(rval);
581     rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, &id, 1 );
582     CHECK_ERR(rval);
583     Range verts;
584     rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
585     int act_id = identify_set( mb, verts );
586     CHECK_EQUAL( id, act_id );
587   }
588 }
589 
590 //! Read in the elems contained in a sets
test_read_two_sets_elems()591 void test_read_two_sets_elems()
592 {
593   ErrorCode rval;
594   Core moab;
595   Interface& mb = moab;
596 
597   create_mesh( true, false, false, false );
598   int ids[2] = { 2, 8 };
599   EntityHandle file_set;
600   rval = mb.create_meshset( MESHSET_SET, file_set );
601   CHECK_ERR(rval);
602   rval = mb.load_file( TEST_FILE, &file_set, READ_OPTS, ID_TAG_NAME, ids, 2 );
603   CHECK_ERR(rval);
604 
605   Range sets;
606   rval = mb.get_entities_by_type( 0, MBENTITYSET, sets );
607   CHECK_ERR(rval);
608   CHECK_EQUAL( 3, (int)sets.size() );
609   Range::iterator it = sets.find( file_set );
610   CHECK( it != sets.end() );
611   sets.erase( it );
612 
613   int id1 = identify_set( mb, sets.front() );
614   int id2 = identify_set( mb, sets.back() );
615   if (id1 == ids[0]) {
616     CHECK_EQUAL( ids[1], id2 );
617   }
618   else {
619     CHECK_EQUAL( ids[1], id1 );
620     CHECK_EQUAL( ids[0], id2 );
621   }
622 }
623 
check_tag(Interface & mb,const char * name,TagType storage,DataType type,int size)624 Tag check_tag( Interface& mb,
625                  const char* name,
626                  TagType storage,
627                  DataType type,
628                  int size )
629 {
630 
631   Tag tag;
632   ErrorCode rval = mb.tag_get_handle( name, size, type, tag );
633   CHECK_ERR(rval);
634 
635   TagType storage1;
636   rval = mb.tag_get_type( tag, storage1 );
637   CHECK_ERR(rval);
638   CHECK_EQUAL( storage, storage1 );
639 
640   DataType type1;
641   rval = mb.tag_get_data_type( tag, type1 );
642   CHECK_ERR(rval);
643   CHECK_EQUAL( type, type1 );
644 
645   int size1;
646   rval = mb.tag_get_length( tag, size1 );
647   if (size <= 0) { // variable-length tag
648     CHECK_EQUAL( MB_VARIABLE_DATA_LENGTH, rval );
649   }
650   else {
651     CHECK_ERR(rval);
652     CHECK_EQUAL( size, size1 );
653   }
654 
655   return tag;
656 }
657 
658 //! Test reading of sparse double tag data
test_read_double_tag()659 void test_read_double_tag()
660 {
661   ErrorCode rval;
662   Core moab;
663   Interface& mb = moab;
664 
665   create_mesh( true, false, false, false );
666   int ids[2] = { 1, 4 };
667   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, ids, 2 );
668   CHECK_ERR(rval);
669 
670   Tag tag = check_tag( mb, CENTROID_NAME, MB_TAG_DENSE, MB_TYPE_DOUBLE, 3 );
671   Range verts;
672   rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
673   CHECK_ERR(rval);
674   CHECK( !verts.empty() );
675   for (Range::iterator i = verts.begin(); i != verts.end(); ++i) {
676     double coords[3], data[3];
677     rval = mb.get_coords( &*i, 1, coords );
678     CHECK_ERR(rval);
679     rval = mb.tag_get_data( tag, &*i, 1, data );
680     CHECK_ERR(rval);
681     CHECK_REAL_EQUAL( coords[0], data[0], 1e-12 );
682     CHECK_REAL_EQUAL( coords[1], data[1], 1e-12 );
683     CHECK_REAL_EQUAL( coords[2], data[2], 1e-12 );
684   }
685 }
686 
687 //! Test reading of sparse opaque tag data
test_read_opaque_tag()688 void test_read_opaque_tag()
689 {
690   ErrorCode rval;
691   Core moab;
692   Interface& mb = moab;
693 
694   create_mesh( true, false, false, false );
695   int ids[2] = { 1, 4 };
696   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, ids, 2 );
697   CHECK_ERR(rval);
698 
699   Tag tag = check_tag( mb, LOGICAL_NAME, MB_TAG_DENSE, MB_TYPE_OPAQUE, 2*sizeof(int) );
700   Range verts;
701   rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
702   CHECK_ERR(rval);
703   CHECK( !verts.empty() );
704   for (Range::iterator i = verts.begin(); i != verts.end(); ++i) {
705     double coords[3];
706     int data[2];
707     rval = mb.get_coords( &*i, 1, coords );
708     CHECK_ERR(rval);
709     rval = mb.tag_get_data( tag, &*i, 1, data );
710     CHECK_ERR(rval);
711     CHECK_REAL_EQUAL( coords[0], (double)data[0], 1e-12 );
712     CHECK_REAL_EQUAL( coords[1], (double)data[1], 1e-12 );
713   }
714 }
715 
test_read_handle_tag_common(bool var_len)716 static void test_read_handle_tag_common( bool var_len )
717 {
718   ErrorCode rval;
719   Core moab;
720   Interface& mb = moab;
721 
722   const char tag_name[] = "VTX_ADJ";
723   create_mesh( true, false, false, false, tag_name, var_len );
724   int ids[2] = { 7, 10 };
725   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, ids, 2 );
726   CHECK_ERR(rval);
727 
728   Tag tag = check_tag( mb, tag_name, MB_TAG_DENSE, MB_TYPE_HANDLE,
729                          var_len ? 0 : 4 );
730   Range verts;
731   rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
732   CHECK_ERR(rval);
733   CHECK( !verts.empty() );
734   for (Range::iterator i = verts.begin(); i != verts.end(); ++i) {
735     std::vector<EntityHandle> adj, val;
736     rval = mb.get_adjacencies( &*i, 1, 2, false, adj, Interface::UNION );
737     CHECK_ERR(rval);
738     CHECK(!adj.empty());
739 
740     int num;
741     const void* ptr;
742     rval = mb.tag_get_by_ptr( tag, &*i, 1, &ptr, &num );
743     CHECK_ERR(rval);
744 
745     if (var_len) {
746       CHECK( num > 0 );
747       CHECK( num < 5 );
748     }
749     else {
750       CHECK_EQUAL( 4, num );
751     }
752 
753     val.clear();
754     const EntityHandle* dat = (const EntityHandle*)ptr;
755     for (const EntityHandle* end = dat+num; dat != end; ++dat)
756       if (*dat)
757         val.push_back(*dat);
758 
759     CHECK_EQUAL( adj.size(), val.size() );
760     std::sort( adj.begin(), adj.end() );
761     std::sort( val.begin(), val.end() );
762     CHECK( adj == val );
763   }
764 }
765 
766 
test_read_tagged_elems()767 void test_read_tagged_elems()
768 {
769   ErrorCode rval;
770   Core moab;
771   Interface& mb = moab;
772 
773   create_mesh( false, false, true, false );
774   int id = 5;
775   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, &id, 1 );
776   CHECK_ERR(rval);
777 
778   Range verts;
779   rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
780   CHECK_ERR(rval);
781   int id2 = identify_set( mb, verts );
782   CHECK_EQUAL( id, id2 );
783 
784   int elems;
785   rval = mb.get_number_entities_by_type( 0, MBQUAD, elems );
786   CHECK_ERR(rval);
787   CHECK_EQUAL( MBQUAD_INT*MBQUAD_INT/NUM_SETS, elems );
788 }
789 
test_read_tagged_nodes()790 void test_read_tagged_nodes()
791 {
792   ErrorCode rval;
793   Core moab;
794   Interface& mb = moab;
795 
796   create_mesh( false, false, false, true );
797   int id = 1; // NOTE: this test will only succeed for ID == 1
798   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, &id, 1 );
799   CHECK_ERR(rval);
800 
801   Range verts;
802   rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
803   CHECK_ERR(rval);
804   int id2 = identify_set( mb, verts );
805   CHECK_EQUAL( id, id2 );
806 
807   int elems;
808   rval = mb.get_number_entities_by_type( 0, MBQUAD, elems );
809   CHECK_ERR(rval);
810   CHECK_EQUAL( MBQUAD_INT*MBQUAD_INT/NUM_SETS, elems );
811 }
812 
813 
814 //! Read in the polyhedra contained in a set
test_read_one_set_polyhedra()815 void test_read_one_set_polyhedra()
816 {
817   ErrorCode rval;
818   Core instance;
819   Interface& mb = instance;
820 
821     // create a 2x2x1 block of hexes, splitting each hex face
822     // into two triangles to form an 12-sided polyhedron
823   EntityHandle verts[18], hexes[4];
824   double coords[18][3] = { {0, 0, 0},
825                            {1, 0, 0},
826                            {2, 0, 0},
827                            {0, 1, 0},
828                            {1, 1, 0},
829                            {2, 1, 0},
830                            {0, 0, 1},
831                            {1, 0, 1},
832                            {2, 0, 1},
833                            {0, 1, 1},
834                            {1, 1, 1},
835                            {2, 1, 1},
836                            {0, 0, 2},
837                            {1, 0, 2},
838                            {2, 0, 2},
839                            {0, 1, 2},
840                            {1, 1, 2},
841                            {2, 1, 2} };
842   int hexconn[4][8] = {  { 0, 1, 4, 3, 6, 7, 10, 9 },
843                          { 1, 2, 5, 4, 7, 8, 11, 10 },
844                          { 6, 7, 10, 9, 12, 13, 16, 15 },
845                          { 7, 8, 11, 10, 13, 14, 17, 16 } };
846   for (int i = 0; i < 18; ++i) {
847     rval = mb.create_vertex( coords[i], verts[i] );
848     CHECK_ERR(rval);
849   }
850   for (int i = 0; i < 4; ++i) {
851     EntityHandle conn[8];
852     for (int j = 0; j < 8; ++j)
853       conn[j] = verts[hexconn[i][j]];
854     rval = mb.create_element( MBHEX, conn, 8, hexes[i] );
855     CHECK_ERR(rval);
856   }
857 
858   Tag tri_tag;
859   rval = mb.tag_get_handle( "tris", 2, MB_TYPE_HANDLE, tri_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
860   CHECK_ERR(rval);
861 
862   std::vector<EntityHandle> quads;
863   EntityHandle tris[12], poly[4];
864   for (int i = 0; i < 4; ++i) {
865     quads.clear();
866     rval = mb.get_adjacencies( &hexes[i], 1, 2, true, quads );
867     CHECK_ERR(rval);
868     CHECK_EQUAL( 6, (int)quads.size() );
869 
870     for (int j = 0; j < 6; ++j) {
871       rval = mb.tag_get_data( tri_tag, &quads[j], 1, tris + 2*j );
872       if (MB_SUCCESS == rval)
873         continue;
874       CHECK_EQUAL( MB_TAG_NOT_FOUND, rval );
875       const EntityHandle* conn;
876       int len;
877       rval = mb.get_connectivity( quads[j], conn, len );
878       CHECK_ERR(rval);
879       CHECK_EQUAL( 4, len );
880       EntityHandle tri_conn[2][3] = {  { conn[0], conn[1], conn[2] },
881                                          { conn[2], conn[3], conn[0] } };
882       rval = mb.create_element( MBTRI, tri_conn[0], 3, tris[2*j  ] ); CHECK_ERR(rval);
883       rval = mb.create_element( MBTRI, tri_conn[1], 3, tris[2*j+1] ); CHECK_ERR(rval);
884       rval = mb.tag_set_data( tri_tag, &quads[j], 1, tris + 2*j ); CHECK_ERR(rval);
885     }
886 
887     rval = mb.create_element( MBPOLYHEDRON, tris, 12, poly[i] );
888     CHECK_ERR(rval);
889   }
890 
891   Range all_tri;
892   rval = mb.get_entities_by_type( 0, MBTRI, all_tri );
893   CHECK_ERR(rval);
894   CHECK_EQUAL( 40, (int)all_tri.size() );
895 
896   rval = mb.delete_entities( hexes, 4 ); CHECK_ERR(rval);
897   rval = mb.delete_entities( &quads[0], quads.size() ); CHECK_ERR(rval);
898 
899   EntityHandle sets[2];
900   rval = mb.create_meshset( 0, sets[0] ); CHECK_ERR(rval);
901   rval = mb.add_entities( sets[0], poly, 2 ); CHECK_ERR(rval);
902   rval = mb.create_meshset( 0, sets[1] ); CHECK_ERR(rval);
903   rval = mb.add_entities( sets[1], poly+2, 2 ); CHECK_ERR(rval);
904 
905   Tag id_tag;
906   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
907   CHECK_ERR(rval);
908   int ids[2] = { 2, 3 };
909   rval = mb.tag_set_data( id_tag, sets, 2, ids ); CHECK_ERR(rval);
910 
911   rval = mb.write_file( TEST_FILE, "MOAB" );
912   CHECK_ERR(rval);
913   rval = mb.delete_mesh();
914   CHECK_ERR(rval);
915 
916   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, ids, 1 );
917   CHECK_ERR(rval);
918 
919   Range rpoly;
920   rval = mb.get_entities_by_type( 0, MBPOLYHEDRON, rpoly );
921   CHECK_ERR(rval);
922   CHECK_EQUAL( 2, (int)rpoly.size() );
923 
924   Range polyverts;
925   rval = mb.get_adjacencies( rpoly, 0, false, polyverts, Interface::UNION );
926   CHECK_ERR(rval);
927   CHECK_EQUAL( 12, (int)polyverts.size() );
928 
929   for (Range::iterator it = polyverts.begin(); it != polyverts.end(); ++it) {
930     double coords2[3];
931     rval = mb.get_coords( &*it, 1, coords2 );
932     CHECK_ERR(rval);
933     CHECK( coords2[0] > -1e-12 && coords2[0]-2 < 1e-12 );
934     CHECK( coords2[1] > -1e-12 && coords2[1]-1 < 1e-12 );
935     CHECK( coords2[2] > -1e-12 && coords2[2]-1 < 1e-12 );
936   }
937 }
938 
939 //! Read in the sets contained in a set.
940 //! Should read all sets containing read elements or nodes
941 //! and all sets that are contained the the specified "read"
942 //! set.  Test the later here.
test_read_set_sets()943 void test_read_set_sets()
944 {
945   ErrorCode rval;
946   Core instance;
947   Interface& mb = instance;
948 
949   Tag id_tag;
950   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
951   CHECK_ERR(rval);
952 
953     // create sets and assign an ID to each
954   const int len = 5;
955   EntityHandle set[2*len+2];
956   for (int i = 0; i < 2*len+2; ++i) {
957     rval = mb.create_meshset( MESHSET_SET, set[i] );
958     CHECK_ERR(rval);
959     int id = i + 1;
960     rval = mb.tag_set_data( id_tag, set + i, 1, &id );
961     CHECK_ERR(rval);
962   }
963 
964     // make set containment as follows (values are assigned IDs):
965   int cont_ids[2][len] = { { 3, 4, 5, 9, 10 }, { 6, 7, 8, 11, 12 } };
966   for (int i = 0; i < 2; ++i) {
967     EntityHandle contents[len] = { set[cont_ids[i][0] - 1],
968                                      set[cont_ids[i][1] - 1],
969                                      set[cont_ids[i][2] - 1],
970                                      set[cont_ids[i][3] - 1],
971                                      set[cont_ids[i][4] - 1] };
972     rval = mb.add_entities( set[i], contents, len );
973     CHECK_ERR(rval);
974   }
975 
976   rval = mb.write_file( TEST_FILE, "MOAB" );
977   CHECK_ERR(rval);
978 
979   for (int i = 0; i < 2; ++i) {
980     rval = mb.delete_mesh();
981     CHECK_ERR(rval);
982 
983     EntityHandle file;
984     rval = mb.create_meshset( MESHSET_SET, file );
985     CHECK_ERR(rval);
986     int id = i+1;
987     rval = mb.load_file( TEST_FILE, &file, READ_OPTS ";SETS=NONE", ID_TAG_NAME, &id, 1 );
988     CHECK_ERR(rval);
989 
990       // check that the total number of sets read is as expected
991     Range sets;
992     rval = mb.get_entities_by_type( 0, MBENTITYSET, sets );
993     CHECK_ERR(rval);
994     Range::iterator it = sets.find( file );
995     if (it != sets.end())
996       sets.erase( it );
997     CHECK_EQUAL( len+1, (int)sets.size() );
998 
999       // check that we read in the set specified by ID to the reader
1000     rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag );
1001     CHECK_ERR(rval);
1002     sets.clear();
1003     const void* data[] = { &id };
1004     rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &id_tag, data, 1, sets );
1005     CHECK_ERR(rval);
1006     CHECK_EQUAL( 1, (int)sets.size() );
1007 
1008       // check that it contains the expected sets
1009     EntityHandle owner = sets.front();
1010     sets.clear();
1011     rval = mb.get_entities_by_type( owner, MBENTITYSET, sets );
1012     CHECK_ERR(rval);
1013     CHECK_EQUAL( len, (int)sets.size() );
1014 
1015     std::vector<int> expected( cont_ids[i], cont_ids[i] + len );
1016     std::vector<int> actual( len );
1017     rval = mb.tag_get_data( id_tag, sets, &actual[0] );
1018     CHECK_ERR(rval);
1019     std::sort( expected.begin(), expected.end() );
1020     std::sort( actual.begin(), actual.end() );
1021     CHECK( expected == actual );
1022   }
1023 }
1024 
check_children(bool contents,GatherTestMode mode,Interface & mb,int id,Tag id_tag,EntityHandle file)1025 static void check_children( bool contents, GatherTestMode mode, Interface& mb, int id, Tag id_tag, EntityHandle file )
1026 {
1027     // Increase number of expected sets by one if contents is true because
1028     // we always read immediately contained (depth 1) sets.
1029   const int exp_num_sets = (mode == GATHER_NONE) ? 1+contents : id;
1030   const int exp_num_edges = (mode == GATHER_CONTENTS) ? id : 1;
1031 
1032   ErrorCode rval;
1033   Range range;
1034   rval = mb.get_entities_by_type( 0, MBEDGE , range );
1035   CHECK_ERR(rval);
1036   CHECK_EQUAL( exp_num_edges, (int)range.size() );
1037   range.clear();
1038   rval = mb.get_entities_by_type( 0, MBENTITYSET , range );
1039   CHECK_ERR(rval);
1040   Range::iterator it = range.find( file );
1041   CHECK( it != range.end() );
1042   range.erase( it );
1043   CHECK_EQUAL( exp_num_sets, (int)range.size() );
1044 
1045   EntityHandle set;
1046   const void* val[] = {&id};
1047   range.clear();
1048   rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &id_tag, val, 1, range );
1049   CHECK_ERR(rval);
1050   CHECK_EQUAL( 1, (int)range.size() );
1051   set = range.front();
1052 
1053   if (mode == GATHER_NONE) {
1054     range.clear();
1055     rval = mb.get_entities_by_type( set, MBEDGE , range );
1056     CHECK_ERR(rval);
1057     CHECK_EQUAL( 1, (int)range.size() );
1058     return;
1059   }
1060 
1061   for (int i = id; i > 0; --i) {
1062     int act_id;
1063     rval = mb.tag_get_data( id_tag, &set, 1, &act_id );
1064     CHECK_ERR(rval);
1065     CHECK_EQUAL( i, act_id );
1066 
1067     range.clear();
1068     rval = mb.get_entities_by_type( set, MBEDGE, range );
1069     CHECK_ERR(rval);
1070     if (mode == GATHER_CONTENTS || i == id) {
1071       CHECK_EQUAL( 1, (int)range.size() );
1072       const EntityHandle* conn;
1073       int len;
1074       rval = mb.get_connectivity( range.front(), conn, len );
1075       CHECK_ERR(rval);
1076       CHECK_EQUAL( 2, len );
1077       double coords[3];
1078       rval = mb.get_coords( conn + 1, 1, coords );
1079       CHECK_ERR(rval);
1080       CHECK_EQUAL( i, (int)coords[0] );
1081     }
1082     else {
1083       CHECK( range.empty() );
1084     }
1085 
1086     std::vector<EntityHandle> children;
1087     if (contents)
1088       rval = mb.get_entities_by_type( set, MBENTITYSET, children );
1089     else
1090       rval = mb.get_child_meshsets( set, children );
1091     CHECK_ERR(rval);
1092     if (i == 1) {
1093       CHECK( children.empty() );
1094     }
1095     else {
1096       CHECK_EQUAL( 1, (int)children.size() );
1097       set = children[0];
1098     }
1099   }
1100 }
1101 
1102 
1103 const char* set_read_opts[] = { "SETS", "CONTENTS", "NONE" };
test_gather_sets_common(bool contents,GatherTestMode mode,bool no_parent_containing_sets)1104 void test_gather_sets_common( bool contents, GatherTestMode mode, bool no_parent_containing_sets )
1105 {
1106   ErrorCode rval;
1107   Core instance;
1108   Interface& mb = instance;
1109 
1110   Tag id_tag;
1111   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
1112   CHECK_ERR(rval);
1113 
1114     // Create a string of edges from [0,INT] along the X axis each 1 unit in length.
1115     // Create a set for edge edge containing the edge and make it the parent of the
1116     // set containing the previous (closer to origin) edge.  Assign each set an
1117     // ID that is the X coordinate of the larger of the two vertices of the edge
1118     // contained in the set.
1119   const int INT = 64;
1120   EntityHandle verts[INT+1], edges[INT], sets[INT];
1121   double coords[] = { 0, 0, 0 };
1122   rval = mb.create_vertex( coords, verts[0] );
1123   CHECK_ERR(rval);
1124   for (int i = 0; i < INT; ++i) {
1125     const int id = i + 1;
1126     coords[0] = id;
1127     rval = mb.create_vertex( coords, verts[id] );
1128     CHECK_ERR(rval);
1129     rval = mb.create_element( MBEDGE, verts + i, 2, edges[i] );
1130     CHECK_ERR(rval);
1131     rval = mb.create_meshset( MESHSET_SET, sets[i] );
1132     CHECK_ERR(rval);
1133     rval = mb.add_entities( sets[i], edges + i, 1 );
1134     CHECK_ERR(rval);
1135     rval = mb.tag_set_data( id_tag, sets + i, 1, &id );
1136     CHECK_ERR(rval);
1137     if (i > 0) {
1138       if (contents)
1139         rval = mb.add_entities( sets[i], sets + (i-1), 1 );
1140       else
1141         rval = mb.add_child_meshset( sets[i], sets[i-1] );
1142       CHECK_ERR(rval);
1143     }
1144   }
1145 
1146     // Write the data
1147   rval = mb.write_file( TEST_FILE, "MOAB" );
1148   CHECK_ERR(rval);
1149 
1150   EntityHandle file;
1151   std::string opt( READ_OPTS );
1152   if (contents)
1153     opt += ";CHILDREN=NONE;SETS=";
1154   else
1155     opt += ";SETS=NONE;CHILDREN=";
1156   opt += set_read_opts[mode];
1157 
1158   if (no_parent_containing_sets) opt += ";NO_SET_CONTAINING_PARENTS";
1159 
1160   const int test_ids[] = { 2, 7, INT/3-1, INT/2+1, INT-3 };
1161   const int num_test_ids = sizeof(test_ids)/sizeof(int);
1162   for (int i = 0; i < num_test_ids; ++i) {
1163     CHECK (test_ids[i] <= INT);
1164 
1165     rval = mb.delete_mesh();
1166     CHECK_ERR(rval);
1167 
1168     rval = mb.create_meshset( MESHSET_SET, file );
1169     CHECK_ERR(rval);
1170 
1171     rval = mb.load_file( TEST_FILE, 0, opt.c_str(), ID_TAG_NAME, test_ids+i, 1 );
1172     CHECK_ERR(rval);
1173     rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag );
1174     CHECK_ERR(rval);
1175 
1176     check_children( contents, mode, mb, test_ids[i], id_tag, file );
1177   }
1178 }
1179 
1180 
test_gather_sets_ranged(bool contents,GatherTestMode mode,bool no_parent_containing_sets)1181 void test_gather_sets_ranged( bool contents, GatherTestMode mode, bool no_parent_containing_sets )
1182 {
1183   ErrorCode rval;
1184   Core instance;
1185   Interface& mb = instance;
1186 
1187   Range verts;
1188   Tag id_tag;
1189   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
1190   CHECK_ERR(rval);
1191 
1192     // create four groups of vertices, where all vertices in the same group
1193     // have the same x-coordinate
1194   const int NUM_GRP_VTX = 20;
1195   const int NUM_GRP = 4;
1196   EntityHandle sets[NUM_GRP];
1197   for (int i = 0; i < NUM_GRP; ++i) {
1198     double coords[3*NUM_GRP_VTX];
1199     for (int j = 0; j < NUM_GRP_VTX; ++j) {
1200       coords[3*j  ] = i;
1201       coords[3*j+1] = j;
1202       coords[3*j+2] = 0;
1203     }
1204     rval = mb.create_vertices( coords, NUM_GRP_VTX, verts );
1205     CHECK_ERR(rval);
1206 
1207     rval = mb.create_meshset( MESHSET_SET, sets[i] );
1208     CHECK_ERR(rval);
1209     rval = mb.add_entities( sets[i], verts );
1210     CHECK_ERR(rval);
1211     int id = i + 1;
1212     rval = mb.tag_set_data( id_tag, sets+i, 1, &id );
1213     CHECK_ERR(rval);
1214   }
1215 
1216     // place two of the sets inside the others
1217   if (contents) {
1218     rval = mb.add_entities( sets[0], &sets[1], 1 ); CHECK_ERR(rval);
1219     rval = mb.add_entities( sets[2], &sets[3], 1 ); CHECK_ERR(rval);
1220   }
1221   else {
1222     rval = mb.add_child_meshset( sets[0], sets[1] ); CHECK_ERR(rval);
1223     rval = mb.add_child_meshset( sets[2], sets[3] ); CHECK_ERR(rval);
1224   }
1225 
1226     // Write the data
1227   rval = mb.write_file( TEST_FILE, "MOAB" );
1228   CHECK_ERR(rval);
1229 
1230     // Read the data
1231   std::string opt( READ_OPTS );
1232   if (contents)
1233     opt += ";CHILDREN=NONE;SETS=";
1234   else
1235     opt += ";SETS=NONE;CHILDREN=";
1236   opt += set_read_opts[mode];
1237 
1238   if (no_parent_containing_sets) opt += ";NO_PARENT_CONTAINING_SETS";
1239 
1240   EntityHandle file;
1241   const int read_id = 3;
1242   rval = mb.delete_mesh(); CHECK_ERR(rval);
1243   rval = mb.create_meshset( MESHSET_SET, file ); CHECK_ERR(rval);
1244   rval = mb.load_file( TEST_FILE, &file, opt.c_str(), ID_TAG_NAME, &read_id, 1 );
1245   CHECK_ERR(rval);
1246 
1247     // get any sets that were read it
1248   Range read_sets;
1249   rval = mb.get_entities_by_type( file, MBENTITYSET, read_sets );
1250   CHECK_ERR(rval);
1251 
1252     // count number of vertices in each group
1253   int counts[NUM_GRP];
1254   memset( counts, 0, sizeof(counts) );
1255   verts.clear();
1256   rval = mb.get_entities_by_type( 0, MBVERTEX, verts );
1257   CHECK_ERR(rval);
1258   for (Range::iterator it = verts.begin(); it != verts.end(); ++it) {
1259     double coords[3];
1260     rval = mb.get_coords( &*it, 1, coords );
1261     CHECK_ERR(rval);
1262     int i = (int)(coords[0]+1e-12);
1263     CHECK( i >= 0 && i < NUM_GRP );
1264     counts[i]++;
1265   }
1266 
1267     // check expected counts
1268   CHECK_EQUAL( 0, counts[0] );
1269   CHECK_EQUAL( 0, counts[1] );
1270   CHECK_EQUAL( NUM_GRP_VTX, counts[2] );
1271   switch (mode) {
1272     case GATHER_NONE:
1273       CHECK_EQUAL( 0, counts[3] );
1274       CHECK_EQUAL( 1+contents, (int)read_sets.size() );
1275       break;
1276     case GATHER_SETS:
1277       CHECK_EQUAL( 0, counts[3] );
1278       CHECK_EQUAL( 2, (int)read_sets.size() );
1279       break;
1280     case GATHER_CONTENTS:
1281       CHECK_EQUAL( NUM_GRP_VTX, counts[3] );
1282       CHECK_EQUAL( 2, (int)read_sets.size() );
1283       break;
1284   }
1285 }
1286 
check_num_verts(Interface & mb,Tag tag,int id,int num_vtx)1287 static void check_num_verts( Interface& mb, Tag tag, int id, int num_vtx )
1288 {
1289   ErrorCode rval;
1290   const void* val[] = {&id};
1291   Range range;
1292   rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, val, 1, range );
1293   CHECK_ERR(rval);
1294   CHECK_EQUAL( 1, (int)range.size() );
1295 
1296   EntityHandle set = range.front();
1297   range.clear();
1298   rval = mb.get_entities_by_type( set, MBVERTEX, range );
1299   CHECK_ERR(rval);
1300   CHECK_EQUAL( num_vtx, (int)range.size() );
1301 }
1302 
1303 
1304 //! Read in the sets contained in a set.
1305 //! Should read all sets containing read elements or nodes
1306 //! and all sets that are contained the the specified "read"
1307 //! set.  Test the former here.
test_read_containing_sets()1308 void test_read_containing_sets()
1309 {
1310     // create mesh decomposed by elements but create
1311     // sets containing all vertices of decomposed elements
1312     // such that adjacent sets share vertices.
1313   create_mesh( false, true, false, false );
1314 
1315   ErrorCode rval;
1316   Core instance;
1317   Interface& mb = instance;
1318 
1319     // read some sets
1320   const int ids[] = { 1, 5, 9 };
1321   const int num_sets = sizeof(ids)/sizeof(int);
1322   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, ids, num_sets );
1323   CHECK_ERR(rval);
1324 
1325   Tag id_tag;
1326   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag );
1327   CHECK_ERR(rval);
1328 
1329     // expect all sets adjacent to the specified sets because
1330     // they share vertices.
1331   Range verts;
1332   for (int i = 0; i < num_sets; ++i) {
1333     if (ids[i] > 1)
1334       check_num_verts( mb, id_tag, ids[i]-1, MBQUAD_INT+1 );
1335     check_num_verts( mb, id_tag, ids[i], (MBQUAD_INT+1)*(SET_WIDTH+1) );
1336     if (ids[i] < NUM_SETS)
1337       check_num_verts( mb, id_tag, ids[i]+1, MBQUAD_INT+1 );
1338   }
1339 }
1340 
1341 //! Test reading of explicit adjacencies
test_read_adjacencies()1342 void test_read_adjacencies()
1343 {
1344   ErrorCode rval;
1345   Core instance;
1346   Interface& mb = instance;
1347 
1348     // create four hexes sharing an edge
1349   EntityHandle verts[3][3][2], hexes[2][2];
1350   for (int k = 0; k < 2; ++k) {
1351     for (int j = 0; j < 3; ++j) {
1352       for (int i = 0; i < 3; ++i) {
1353         double coords[] = { static_cast<double>(i), static_cast<double>(j), static_cast<double>(k) };
1354         rval = mb.create_vertex( coords, verts[i][j][k] );
1355         CHECK_ERR(rval);
1356       }
1357     }
1358   }
1359   for (int j = 0; j < 2; ++j) {
1360     for (int i = 0; i < 2; ++i) {
1361       EntityHandle conn[] = { verts[i  ][j  ][0],
1362                                 verts[i+1][j  ][0],
1363                                 verts[i+1][j+1][0],
1364                                 verts[i  ][j+1][0],
1365                                 verts[i  ][j  ][1],
1366                                 verts[i+1][j  ][1],
1367                                 verts[i+1][j+1][1],
1368                                 verts[i  ][j+1][1] };
1369       rval = mb.create_element( MBHEX, conn, 8, hexes[i][j] );
1370       CHECK_ERR(rval);
1371     }
1372   }
1373 
1374     // create two duplicate edges that connect the vertices common to all four hexes
1375   EntityHandle edge_conn[2] = { verts[1][1][0], verts[1][1][1] };
1376   EntityHandle edges[2];
1377   rval = mb.create_element( MBEDGE, edge_conn, 2, edges[0] ); CHECK_ERR(rval);
1378   rval = mb.create_element( MBEDGE, edge_conn, 2, edges[1] ); CHECK_ERR(rval);
1379     // mark one edge as adjacent to the left two hexes and the
1380     // other as adjacent to the right two
1381   rval = mb.add_adjacencies( edges[0], hexes[0], 2, true ); CHECK_ERR(rval);
1382   rval = mb.add_adjacencies( edges[1], hexes[1], 2, true ); CHECK_ERR(rval);
1383     // create two sets containing the front two and the rear two
1384     // hexes, respectively.
1385   EntityHandle sets[2];
1386   rval = mb.create_meshset( MESHSET_SET, sets[0] ); CHECK_ERR(rval);
1387   rval = mb.create_meshset( MESHSET_SET, sets[1] ); CHECK_ERR(rval);
1388   EntityHandle set1[4] = { hexes[0][0], hexes[1][0], edges[0], edges[1] };
1389   EntityHandle set2[4] = { hexes[0][1], hexes[1][1], edges[0], edges[1] };
1390   rval = mb.add_entities( sets[0], set1, 4 ); CHECK_ERR(rval);
1391   rval = mb.add_entities( sets[1], set2, 4 ); CHECK_ERR(rval);
1392 
1393     // assign IDs to sets
1394   Tag id_tag;
1395   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
1396   CHECK_ERR(rval);
1397   int ids[2] = { 1, 2 };
1398   rval = mb.tag_set_data( id_tag, sets, 2, ids );
1399   CHECK_ERR(rval);
1400 
1401     // write mesh
1402   rval = mb.write_file( TEST_FILE, "MOAB" );
1403   CHECK_ERR(rval);
1404 
1405     // read mesh
1406   rval = mb.delete_mesh(); CHECK_ERR(rval);
1407   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, ids, 1 );
1408   CHECK_ERR(rval);
1409 
1410     // expect two hexes and two edges
1411   Range range;
1412   rval = mb.get_entities_by_type( 0, MBHEX, range );
1413   CHECK_ERR(rval);
1414   CHECK_EQUAL( 2, (int)range.size() );
1415   EntityHandle h1 = range.front(), h2 = range.back();
1416   range.clear();
1417   rval = mb.get_entities_by_type( 0, MBEDGE, range );
1418   CHECK_ERR(rval);
1419   CHECK_EQUAL( 2, (int)range.size() );
1420 
1421     // expecte each edge to have one of the hexes
1422   range.clear();
1423   rval = mb.get_adjacencies( &h1, 1, 1, false, range );
1424   CHECK_ERR(rval);
1425   CHECK_EQUAL( 1, (int)range.size() );
1426   EntityHandle e1 = range.front();
1427   range.clear();
1428   rval = mb.get_adjacencies( &h2, 1, 1, false, range );
1429   CHECK_ERR(rval);
1430   CHECK_EQUAL( 1, (int)range.size() );
1431   EntityHandle e2 = range.front();
1432 
1433   CHECK( e1 != e2 );
1434 }
1435 
1436 
test_read_sides()1437 void test_read_sides()
1438 {
1439   ErrorCode rval;
1440   Core instance;
1441   Interface& mb = instance;
1442 
1443     // create 4x4 grid of quads with edges
1444   const int INT = 4;
1445   EntityHandle verts[INT+1][INT+1];
1446   for (int j = 0; j <= INT; ++j) {
1447     for (int i = 0; i <= INT; ++i) {
1448       double coords[3] = { static_cast<double>(i), static_cast<double>(j), 0 };
1449       rval = mb.create_vertex( coords, verts[INT-j][i] );
1450       CHECK_ERR(rval);
1451     }
1452   }
1453   EntityHandle quads[INT][INT];
1454   for (int j = 0; j < INT; ++j) {
1455     for (int i = 0; i < INT; ++i) {
1456       EntityHandle conn[4] = { verts[INT-j][i],
1457                                  verts[INT-j][i+1],
1458                                  verts[INT-j-1][i+1],
1459                                  verts[INT-j-1][i] };
1460       rval = mb.create_element( MBQUAD, conn, 4, quads[INT-j-1][i] );
1461       CHECK_ERR(rval);
1462     }
1463   }
1464   Range edges;
1465   rval = mb.get_adjacencies( &quads[0][0], INT*INT, 1, true, edges, Interface::UNION );
1466   CHECK_ERR(rval);
1467   CHECK_EQUAL( 40, (int)edges.size() );
1468 
1469     // group quads into two sets
1470   EntityHandle sets[2];
1471   rval = mb.create_meshset( MESHSET_SET, sets[0] ); CHECK_ERR(rval);
1472   rval = mb.create_meshset( MESHSET_SET, sets[1] ); CHECK_ERR(rval);
1473   rval = mb.add_entities( sets[0], quads[0], INT ); CHECK_ERR(rval);
1474   rval = mb.add_entities( sets[1], quads[1], INT ); CHECK_ERR(rval);
1475   rval = mb.add_entities( sets[0], quads[2], INT ); CHECK_ERR(rval);
1476   rval = mb.add_entities( sets[1], quads[3], INT ); CHECK_ERR(rval);
1477 
1478     // assign IDS
1479   Tag id_tag;
1480   rval = mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, MB_TAG_SPARSE|MB_TAG_EXCL );
1481   CHECK_ERR(rval);
1482   int ids[2] = { 4, 5 };
1483   rval = mb.tag_set_data( id_tag, sets, 2, ids );
1484   CHECK_ERR(rval);
1485 
1486     // write mesh
1487   rval = mb.write_file( TEST_FILE, "MOAB" );
1488   CHECK_ERR(rval);
1489 
1490     // read first set back in
1491   rval = mb.delete_mesh(); CHECK_ERR(rval);
1492   rval = mb.load_file( TEST_FILE, 0, READ_OPTS, ID_TAG_NAME, ids, 1 );
1493   CHECK_ERR(rval);
1494 
1495     // check expected counts
1496   int count;
1497   rval = mb.get_number_entities_by_type( 0, MBVERTEX, count );
1498   CHECK_ERR(rval);
1499   CHECK_EQUAL( (INT+1)*INT, count );
1500   rval = mb.get_number_entities_by_type( 0, MBQUAD, count );
1501   CHECK_ERR(rval);
1502   CHECK_EQUAL( INT*INT/2, count );
1503   rval = mb.get_number_entities_by_type( 0, MBEDGE, count );
1504   CHECK_ERR(rval);
1505   CHECK_EQUAL( 2*(INT+1) + INT*INT, count );
1506 
1507     // check edges adjacent to each quad
1508   Range elems;
1509   rval = mb.get_entities_by_type( 0, MBQUAD, elems );
1510   CHECK_ERR(rval);
1511   for (Range::iterator it = elems.begin(); it != elems.end(); ++it) {
1512     edges.clear();
1513     rval = mb.get_adjacencies( &*it, 1, 1, false, edges );
1514     CHECK_ERR(rval);
1515     CHECK_EQUAL( 4, (int)edges.size() );
1516   }
1517 }
1518 
1519 const int expected_ids[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18 };
1520 const int expected_vols[] = { 3, 7, 10 };
1521 
write_id_test_file()1522 void write_id_test_file()
1523 {
1524   Core moab;
1525   Interface& mb = moab;
1526   ErrorCode rval;
1527 
1528     // create 12 entity sets
1529   EntityHandle sets[12];
1530   for (int i = 0; i < 12; ++i) {
1531     rval = mb.create_meshset( MESHSET_SET, sets[i] );
1532     CHECK_ERR(rval);
1533   }
1534 
1535     // create tag handles
1536   Tag id = 0, gid = 0, dim = 0;
1537   mb.tag_get_handle( ID_TAG_NAME, 1, MB_TYPE_INTEGER, id, MB_TAG_SPARSE|MB_TAG_EXCL );
1538   mb.tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, dim, MB_TAG_SPARSE|MB_TAG_EXCL );
1539   mb.tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE|MB_TAG_EXCL );
1540 
1541     // set ID tag on first 10 sets
1542   rval = mb.tag_set_data( id, sets, sizeof(expected_ids)/sizeof(int), expected_ids );
1543   CHECK_ERR(rval);
1544     // set geom dim on all sets, only three of them have dim == 3
1545   int num_vol = sizeof(expected_vols)/sizeof(int);
1546   int dims[12], ids[12];
1547   int v = 0;
1548   for (int i = 0; i < 12; ++i) {
1549     dims[i] = i % 3 + 1;
1550     if (dims[i] == 3) {
1551       if (v < num_vol)
1552         ids[i] = expected_vols[v++];
1553       else
1554         ids[i] = expected_vols[0];
1555     }
1556     else
1557       ids[i] = 100;
1558   }
1559   rval = mb.tag_set_data( gid, sets, 12, ids );
1560   CHECK_ERR(rval);
1561   rval = mb.tag_set_data( dim, sets, 12, dims );
1562   CHECK_ERR(rval);
1563 
1564   rval = mb.write_file( TEST_FILE, "MOAB" );
1565   CHECK_ERR(rval);
1566 }
1567 
test_read_ids()1568 void test_read_ids()
1569 {
1570   write_id_test_file();
1571 
1572   Core moab;
1573   ReadHDF5 reader(&moab);
1574   FileOptions opts("");
1575   ErrorCode rval;
1576   std::vector<int> values;
1577   rval = reader.read_tag_values( TEST_FILE, ID_TAG_NAME, opts, values );
1578   remove( TEST_FILE );
1579   CHECK_ERR(rval);
1580 
1581   std::sort( values.begin(), values.end() );
1582   std::vector<int> expected( expected_ids, expected_ids+sizeof(expected_ids)/sizeof(int) );
1583   CHECK_EQUAL( expected, values );
1584 }
1585 
test_read_partial_ids()1586 void test_read_partial_ids()
1587 {
1588   write_id_test_file();
1589 
1590   const int three = 3;
1591   ReaderIface::IDTag vols = { GEOM_DIMENSION_TAG_NAME, &three, 1 };
1592   ReaderIface::SubsetList subset = { &vols, 1, 0, 0 };
1593 
1594   Core moab;
1595   ReadHDF5 reader(&moab);
1596   FileOptions opts("");
1597   ErrorCode rval;
1598   std::vector<int> values;
1599   rval = reader.read_tag_values( TEST_FILE, GLOBAL_ID_TAG_NAME, opts, values, &subset );
1600   remove( TEST_FILE );
1601   CHECK_ERR(rval);
1602 
1603   std::sort( values.begin(), values.end() );
1604   std::vector<int> expected( expected_ids, expected_ids+sizeof(expected_ids)/sizeof(int) );
1605 }
1606