MOAB: Mesh Oriented datABase  (version 5.5.0)
cub_file_test.cpp
Go to the documentation of this file.
1 #include "TestUtil.hpp"
2 #include "moab/Core.hpp"
3 #include "MBTagConventions.hpp"
4 #include "moab/CN.hpp"
5 #include "moab/Range.hpp"
6 #include "moab/GeomTopoTool.hpp"
7 #include <cmath>
8 #include <algorithm>
9 
10 using namespace moab;
11 
12 /**\brief Input test file: test.cub
13  * Cubit 10.2 file.
14  * File contains:
15  * Two merged 10x10x10 bricks sharing a single surface (surface 6).
16  * - Each brick is meshed with 8 5x5x5 hexes.
17  * - Each surface is meshed with 4 5x5 quads.
18  * - Each curve is meshed with 2 5-unit edges.
19  * A single block containing both bricks.
20  * Two side sets
21  * - sideset 1: surfaces 1 and 7
22  * - sideset 2: surfaces 5 and 11
23  * Two node sets:
24  * - nodeset 1: surfaces 2 and 8
25  * - nodeset 2: surfaces 3 and 9
26  *
27  * Surfaces:
28  * 2 8
29  * / /
30  * o----------o----------o
31  * /. / /. / /|
32  * / . (5)/ / . (11)/ / |
33  * / . L / . L / |
34  * o----------o----------o |
35  * | . | . |(12)
36  * 4--|-> o . . .|. .o. . . | . o
37  * | . (1) | . (9) | /
38  * | . ^ | . ^ | /
39  * |. | |. | |/
40  * o----------o----------o
41  * | |
42  * 3 9
43  *
44  * Curves:
45  *
46  * o----8-----o----20----o
47  * /. /. /|
48  * 12 . 11 . 24 |
49  * / 7 / 5 / 17
50  * o----2-----o----14----o |
51  * | . | . | |
52  * | o . .6.|. .o. . 18| . o
53  * 3 . 1 . 13 /
54  * | 9 | 10 | 22
55  * |. |. |/
56  * o----4-----o----16----o
57  *
58  * Vertices:
59  *
60  * 8----------5----------13
61  * /. /. /|
62  * / . / . / |
63  * / . / . / |
64  * 3----------2----------10 |
65  * | . | . | |
66  * | 7 . . .|. .6. . . | . 14
67  * | . | . | /
68  * | . | . | /
69  * |. |. |/
70  * 4----------1----------9
71  */
72 
73 /* Input test file: ho_test.cub
74  *
75  * File is expected to contain at least one block for every
76  * supported higher-order element type. The coordinates of
77  * every higher-order node are expected to be the mean of the
78  * adjacent corner vertices of the element.
79  */
80 static const std::string input_file_1 = std::string( TestDir + "unittest/io/test.cub" );
81 static const std::string ho_file = std::string( TestDir + "unittest/io/ho_test.cub" );
82 static const std::string cubit12_file = std::string( TestDir + "unittest/io/cubtest12.cub" );
83 static const std::string cubit14_file = std::string( TestDir + "unittest/io/cubtest14.cub" );
84 
85 void read_file( Interface& moab, const std::string& input_file );
86 
87 // Check that adjacent lower-order entities have
88 // higher-order nodes consitent with input entity.
90 
91 // Check that element has expected higher-order nodes
92 // and that each higher-order node is at the center
93 // of the sub-entity it is on.
94 void check_ho_element( Interface& moab, EntityHandle entity, int mid_nodes[4] );
95 
96 // Validate elements of specified type.
97 // Looks for a block containing the specified entity type
98 // and with the specified mid-node flags set in its
99 // HAS_MID_NODES_TAG.
100 void test_ho_elements( EntityType type, int num_nodes );
101 
102 void test_vertices();
103 
104 void test_edges();
105 
106 void test_quads();
107 
108 void test_hexes();
109 
111 
112 void test_geometric_sets();
113 
114 void test_blocks();
115 
116 void test_side_sets();
117 
118 void test_node_sets();
119 
120 void test_tri6()
121 {
122  test_ho_elements( MBTRI, 6 );
123 }
124 void test_tri7()
125 {
126  test_ho_elements( MBTRI, 7 );
127 }
128 
130 {
131  test_ho_elements( MBQUAD, 5 );
132 }
134 {
135  test_ho_elements( MBQUAD, 8 );
136 }
138 {
139  test_ho_elements( MBQUAD, 9 );
140 }
141 
142 void test_tet8()
143 {
144  test_ho_elements( MBTET, 8 );
145 }
147 {
148  test_ho_elements( MBTET, 10 );
149 }
151 {
152  test_ho_elements( MBTET, 14 );
153 }
154 
155 void test_hex9()
156 {
157  test_ho_elements( MBHEX, 9 );
158 }
160 {
161  test_ho_elements( MBHEX, 20 );
162 }
164 {
165  test_ho_elements( MBHEX, 27 );
166 }
167 
168 void test_multiple_files();
169 
170 void test_cubit12();
171 void test_cubit14();
172 
173 int main()
174 {
175  int result = 0;
176 
177  result += RUN_TEST( test_vertices );
178  result += RUN_TEST( test_edges );
179  result += RUN_TEST( test_quads );
180  result += RUN_TEST( test_hexes );
181  result += RUN_TEST( test_geometric_topology );
182  result += RUN_TEST( test_geometric_sets );
183  result += RUN_TEST( test_blocks );
184  result += RUN_TEST( test_side_sets );
185  result += RUN_TEST( test_node_sets );
186  result += RUN_TEST( test_tri6 );
187  result += RUN_TEST( test_tri7 );
188  result += RUN_TEST( test_quad5 );
189  result += RUN_TEST( test_quad8 );
190  result += RUN_TEST( test_quad9 );
191  result += RUN_TEST( test_tet8 );
192  result += RUN_TEST( test_tet10 );
193  result += RUN_TEST( test_tet14 );
194  result += RUN_TEST( test_hex9 );
195  result += RUN_TEST( test_hex20 );
196  result += RUN_TEST( test_hex27 );
197  result += RUN_TEST( test_multiple_files );
198  result += RUN_TEST( test_cubit12 );
199  result += RUN_TEST( test_cubit14 );
200  return result;
201 }
202 
203 void read_file( Interface& moab, const std::string& input_file )
204 {
205  ErrorCode rval = moab.load_file( input_file.c_str() );CHECK_ERR( rval );
206 }
207 
209 {
210  /* Node coordinates, in order of node ID, beginning with 1. */
211  const double node_coords[] = {
212  5, -5, 5, // 1
213  5, 5, 5, 5, 0, 5, -5, 5, 5, 0, 5, 5, // 5
214  -5, -5, 5, -5, 0, 5, 0, -5, 5, 0, 0, 5, 5, 5, -5, // 10
215  5, -5, -5, 5, 0, -5, -5, -5, -5, 0, -5, -5, -5, 5, -5, // 15
216  -5, 0, -5, 0, 5, -5, 0, 0, -5, -5, -5, 0, 5, -5, 0, // 20
217  0, -5, 0, -5, 5, 0, -5, 0, 0, 5, 5, 0, 0, 5, 0, // 25
218  5, 0, 0, 0, 0, 0, 15, -5, 5, 15, 5, 5, 15, 0, 5, // 30
219  10, 5, 5, 10, -5, 5, 10, 0, 5, 15, 5, -5, 15, -5, -5, // 35
220  15, 0, -5, 10, -5, -5, 10, 5, -5, 10, 0, -5, 15, -5, 0, // 40
221  10, -5, 0, 15, 5, 0, 10, 5, 0, 15, 0, 0, 10, 0, 0 // 45
222  };
223 
224  ErrorCode rval;
225  Core mb_impl;
226  Interface& mb = mb_impl;
228 
229  // get vertex handles and check correct number of vertices
230  const size_t num_nodes = sizeof( node_coords ) / ( 3 * sizeof( double ) );
231  Range verts;
232  rval = mb.get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
233  CHECK_EQUAL( num_nodes, (size_t)verts.size() );
234 
235  // check global ids (should be 1 to 45 for vertices.)
236  Tag gid_tag;
237  rval = mb.tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gid_tag );CHECK_ERR( rval );
238  std::vector< int > ids( num_nodes );
239  rval = mb.tag_get_data( gid_tag, verts, &ids[0] );CHECK_ERR( rval );
240  std::vector< int > sorted( ids );
241  std::sort( sorted.begin(), sorted.end() );
242  for( size_t i = 0; i < num_nodes; ++i )
243  CHECK_EQUAL( (int)( i + 1 ), sorted[i] );
244 
245  // check coordinates of each vertex
246  std::vector< double > coords( 3 * num_nodes );
247  rval = mb.get_coords( verts, &coords[0] );CHECK_ERR( rval );
248  for( size_t i = 0; i < num_nodes; ++i )
249  {
250  const double* exp = node_coords + 3 * ( ids[i] - 1 );
251  const double* act = &coords[3 * i];
252  CHECK_REAL_EQUAL( exp[0], act[0], 1e-8 );
253  CHECK_REAL_EQUAL( exp[1], act[1], 1e-8 );
254  CHECK_REAL_EQUAL( exp[2], act[2], 1e-8 );
255  }
256 }
257 
258 void test_element( const std::string& filename, EntityType type, int num_elem, int node_per_elem, const int* conn_list )
259 {
260  ErrorCode rval;
261  Core mb_impl;
262  Interface& mb = mb_impl;
263  read_file( mb, filename );
264 
265  Range elems;
266  rval = mb.get_entities_by_type( 0, type, elems );CHECK_ERR( rval );
267  CHECK_EQUAL( num_elem, (int)elems.size() );
268 
269  // get global ids
270  Tag gid_tag;
271  rval = mb.tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gid_tag );CHECK_ERR( rval );
272  std::vector< int > ids( num_elem );
273  rval = mb.tag_get_data( gid_tag, elems, &ids[0] );CHECK_ERR( rval );
274 
275  // check that global ids are consecutive, beginning with 1
276  std::vector< int > sorted( ids );
277  std::sort( sorted.begin(), sorted.end() );
278  for( int i = 0; i < num_elem; ++i )
279  CHECK_EQUAL( i + 1, sorted[i] );
280 
281  // check connectivity of each element
282  std::vector< int > conn_ids( node_per_elem );
283  std::vector< EntityHandle > conn_h;
284  Range::iterator j = elems.begin();
285  for( int i = 0; i < num_elem; ++i, ++j )
286  {
287  conn_h.clear();
288  rval = mb.get_connectivity( &*j, 1, conn_h );CHECK_ERR( rval );
289  CHECK_EQUAL( node_per_elem, (int)conn_h.size() );
290  rval = mb.tag_get_data( gid_tag, &conn_h[0], node_per_elem, &conn_ids[0] );CHECK_ERR( rval );
291  const int* exp = conn_list + node_per_elem * ( ids[i] - 1 );
292  for( int k = 0; k < node_per_elem; ++k )
293  CHECK_EQUAL( exp[k], conn_ids[k] );
294  }
295 }
296 
298 {
299  const int edge_conn[] = { 1, 3, // 1
300  3, 2, 2, 5, 5, 4, 4, 7, 7, 6, 6, 8, 8, 1, 3, 9, 9, 8, // 10
301  5, 9, 9, 7, 10, 12, 12, 11, 11, 14, 14, 13, 13, 16, 16, 15, 15, 17, 17, 10, // 20
302  12, 18, 18, 17, 14, 18, 18, 16, 6, 19, 19, 13, 1, 20, 20, 11, 19, 21, 21, 8, // 30
303  14, 21, 21, 20, 4, 22, 22, 15, 22, 23, 23, 7, 16, 23, 23, 19, 2, 24, 24, 10, // 40
304  24, 25, 25, 5, 17, 25, 25, 22, 20, 26, 26, 3, 12, 26, 26, 24, 28, 30, 30, 29, // 50
305  29, 31, 31, 2, 1, 32, 32, 28, 30, 33, 33, 32, 31, 33, 33, 3, 34, 36, 36, 35, // 60
306  35, 37, 37, 11, 10, 38, 38, 34, 36, 39, 39, 38, 37, 39, 39, 12, 28, 40, 40, 35, // 70
307  20, 41, 41, 32, 37, 41, 41, 40, 29, 42, 42, 34, 42, 43, 43, 31, 38, 43, 43, 24, // 80
308  40, 44, 44, 30, 36, 44, 44, 42 };
309  test_element( input_file_1, MBEDGE, 84, 2, edge_conn );
310 }
311 
313 {
314  const int quad_conn[] = {
315  1, 3, 9, 8, // 1
316  3, 2, 5, 9, 8, 9, 7, 6, 9, 5, 4, 7, 10, 12, 18, 17, 12, 11, 14, 18,
317  17, 18, 16, 15, 18, 14, 13, 16, 6, 19, 21, 8, 19, 13, 14, 21, // 10
318  8, 21, 20, 1, 21, 14, 11, 20, 4, 22, 23, 7, 22, 15, 16, 23, 7, 23, 19, 6,
319  23, 16, 13, 19, 2, 24, 25, 5, 24, 10, 17, 25, 5, 25, 22, 4, 25, 17, 15, 22, // 20
320  1, 20, 26, 3, 20, 11, 12, 26, 3, 26, 24, 2, 26, 12, 10, 24, 28, 30, 33, 32,
321  30, 29, 31, 33, 32, 33, 3, 1, 33, 31, 2, 3, 34, 36, 39, 38, 36, 35, 37, 39, // 30
322  38, 39, 12, 10, 39, 37, 11, 12, 1, 20, 41, 32, 20, 11, 37, 41, 32, 41, 40, 28,
323  41, 37, 35, 40, 29, 42, 43, 31, 42, 34, 38, 43, 31, 43, 24, 2, 43, 38, 10, 24, // 40
324  28, 40, 44, 30, 40, 35, 36, 44, 30, 44, 42, 29, 44, 36, 34, 42,
325  };
326  test_element( input_file_1, MBQUAD, 44, 4, quad_conn );
327 }
328 
330 {
331  const int hex_conn[] = { 6, 19, 23, 7, 8, 21, 27, 9, 19, 13, 16, 23, 21, 14, 18, 27, 7, 23, 22, 4, 9, 27,
332  25, 5, 23, 16, 15, 22, 27, 18, 17, 25, 8, 21, 27, 9, 1, 20, 26, 3, 21, 14, 18, 27,
333  20, 11, 12, 26, 9, 27, 25, 5, 3, 26, 24, 2, 27, 18, 17, 25, 26, 12, 10, 24, 1, 20,
334  26, 3, 32, 41, 45, 33, 20, 11, 12, 26, 41, 37, 39, 45, 3, 26, 24, 2, 33, 45, 43, 31,
335  26, 12, 10, 24, 45, 39, 38, 43, 32, 41, 45, 33, 28, 40, 44, 30, 41, 37, 39, 45, 40, 35,
336  36, 44, 33, 45, 43, 31, 30, 44, 42, 29, 45, 39, 38, 43, 44, 36, 34, 42 };
337  test_element( input_file_1, MBHEX, 16, 8, hex_conn );
338 }
339 
340 template < int L >
341 std::vector< int > find_parents( const int parent_conn[][L], int num_parent, int id )
342 {
343  std::vector< int > results;
344  for( int i = 0; i < num_parent; ++i )
345  {
346  for( int j = 0; j < L; ++j )
347  {
348  if( parent_conn[i][j] == id ) results.push_back( i + 1 );
349  }
350  }
351  return results;
352 }
353 
355  int dim,
356  int id,
357  const int* children,
358  int num_children,
359  std::vector< int > parents )
360 {
361  ErrorCode rval;
362  Tag gid_tag, dim_tag;
363 
364  rval = moab.tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gid_tag );CHECK_ERR( rval );
365  rval = moab.tag_get_handle( "GEOM_DIMENSION", 1, MB_TYPE_INTEGER, dim_tag );CHECK_ERR( rval );
366  void* tag_vals[] = { &dim, &id };
367  Tag tags[] = { dim_tag, gid_tag };
368  Range ents;
369  rval = moab.get_entities_by_type_and_tag( 0, MBENTITYSET, tags, tag_vals, 2, ents );CHECK_ERR( rval );
370  CHECK_EQUAL( 1u, (unsigned)ents.size() );
371 
372  const EntityHandle geom = ents.front();
373  std::vector< int > exp_rel, act_rel;
374  std::vector< EntityHandle > rel;
375 
376  if( num_children )
377  {
378  exp_rel.resize( num_children );
379  std::copy( children, children + num_children, exp_rel.begin() );
380  std::sort( exp_rel.begin(), exp_rel.end() );
381  rel.clear();
382  rval = moab.get_child_meshsets( geom, rel );CHECK_ERR( rval );
383  CHECK_EQUAL( num_children, (int)rel.size() );
384  act_rel.resize( rel.size() );
385  rval = moab.tag_get_data( gid_tag, &rel[0], rel.size(), &act_rel[0] );CHECK_ERR( rval );
386  std::sort( act_rel.begin(), act_rel.end() );
387  CHECK( exp_rel == act_rel );
388  }
389 
390  if( !parents.empty() )
391  {
392  exp_rel = parents;
393  std::sort( exp_rel.begin(), exp_rel.end() );
394  rel.clear();
395  rval = moab.get_parent_meshsets( geom, rel );CHECK_ERR( rval );
396  CHECK_EQUAL( parents.size(), rel.size() );
397  act_rel.resize( rel.size() );
398  rval = moab.tag_get_data( gid_tag, &rel[0], rel.size(), &act_rel[0] );CHECK_ERR( rval );
399  std::sort( act_rel.begin(), act_rel.end() );
400  CHECK( exp_rel == act_rel );
401  }
402 
403  return 0;
404 }
405 
407 {
408  Core mb_impl;
409  Interface& mb = mb_impl;
411  // expected geometric vertices, specified by global ID
412  const int vertex_ids[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13, 14 };
413  // List of global IDs of surfacs in geometric volumes, indexed by ID-1
414  const int volume_surfs[2][6] = { { 1, 2, 3, 4, 5, 6 }, { 7, 8, 9, 6, 11, 12 } };
415  // List of global IDs of curves in geometric surfaces, indexed by ID-1
416  // Curve IDs of zero indicates that corresponding surface doesn't exist.
417  const int surf_curves[12][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 6, 10, 4 }, { 11, 7, 9, 3 },
418  { 12, 8, 11, 2 }, { 10, 5, 12, 1 }, { 13, 14, 1, 16 }, { 17, 18, 5, 20 },
419  { 10, 18, 22, 16 }, { 0, 0, 0, 0 }, // no surf 10
420  { 24, 20, 12, 14 }, { 22, 17, 24, 13 } };
421  // List of global IDs of vertices in geometric curves, indexed by ID-1
422  // Vertex IDs of zero indicates that corresponding curve doesn't exist.
423  const int curve_verts[24][2] = { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 1 }, { 5, 6 }, // 5
424  { 6, 7 }, { 7, 8 }, { 8, 5 }, { 4, 7 }, { 1, 6 }, // 10
425  { 3, 8 }, { 2, 5 }, { 9, 10 }, // 13
426  { 10, 2 }, { 0, 0 }, // no curve 15
427  { 1, 9 }, { 13, 14 }, { 14, 6 }, { 0, 0 }, // no curve 19
428  { 5, 13 }, { 0, 0 }, // no curve 21
429  { 9, 14 }, { 0, 0 }, // no curve 23
430  { 10, 13 } };
431 
432  // check all vertices
433  for( unsigned i = 0; i < ( sizeof( vertex_ids ) / sizeof( vertex_ids[0] ) ); ++i )
434  check_geometric_set( mb, 0, vertex_ids[i], 0, 0, find_parents< 2 >( curve_verts, 24, vertex_ids[i] ) );
435 
436  // check all curves
437  for( int i = 1; i <= 24; ++i )
438  if( curve_verts[i - 1][0] )
439  check_geometric_set( mb, 1, i, curve_verts[i - 1], 2, find_parents< 4 >( surf_curves, 12, i ) );
440 
441  // check all surfs
442  for( int i = 1; i <= 12; ++i )
443  if( surf_curves[i - 1][0] )
444  check_geometric_set( mb, 2, i, surf_curves[i - 1], 4, find_parents< 6 >( volume_surfs, 2, i ) );
445 
446  // check all volumes
447  std::vector< int > empty;
448  for( int i = 1; i <= 2; ++i )
449  check_geometric_set( mb, 3, i, volume_surfs[i - 1], 6, empty );
450 }
451 
453 {
454  ErrorCode rval;
455  Core mb_impl;
456  Interface& mb = mb_impl;
458  Tag gid_tag, dim_tag;
459  rval = mb.tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gid_tag );CHECK_ERR( rval );
460  rval = mb.tag_get_handle( "GEOM_DIMENSION", 1, MB_TYPE_INTEGER, dim_tag );CHECK_ERR( rval );
461 
462  // verify mesh entity counts
463  Range verts, curves, surfs, vols;
464  int dim = 0;
465  // Cppcheck warning (false positive): variable dim is assigned a value that is never used
466  // Cppcheck warning (false positive): variable dim is reassigned a value before the old one has
467  // been used
468  const void* vals[] = { &dim };
469  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &dim_tag, vals, 1, verts );CHECK_ERR( rval );
470  dim = 1;
471  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &dim_tag, vals, 1, curves );CHECK_ERR( rval );
472  dim = 2;
473  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &dim_tag, vals, 1, surfs );CHECK_ERR( rval );
474  dim = 3;
475  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &dim_tag, vals, 1, vols );CHECK_ERR( rval );
476 
477  CHECK_EQUAL( 12u, (unsigned)verts.size() );
478  CHECK_EQUAL( 20u, (unsigned)curves.size() );
479  CHECK_EQUAL( 11u, (unsigned)surfs.size() );
480  CHECK_EQUAL( 2u, (unsigned)vols.size() );
481 
482  // check that each vertex has a single node, and that the
483  // node is also contained in any parent curve
484  Range ents;
485  Range::iterator i;
486  for( i = verts.begin(); i != verts.end(); ++i )
487  {
488  ents.clear();
489  rval = mb.get_entities_by_handle( *i, ents );CHECK_ERR( rval );
490  CHECK_EQUAL( 1u, (unsigned)ents.size() );
491  CHECK( ents.all_of_type( MBVERTEX ) );
492  }
493 
494  // check that each curve has one node and two edges
495  for( i = curves.begin(); i != curves.end(); ++i )
496  {
497  ents.clear();
498  rval = mb.get_entities_by_handle( *i, ents );CHECK_ERR( rval );
499  CHECK_EQUAL( 1u, (unsigned)ents.num_of_type( MBVERTEX ) );
500  CHECK_EQUAL( 2u, (unsigned)ents.num_of_type( MBEDGE ) );
501  CHECK_EQUAL( 3u, (unsigned)ents.size() );
502  }
503 
504  // check that each surface has 1 node, 4 edges, 4 quads
505  for( i = surfs.begin(); i != surfs.end(); ++i )
506  {
507  ents.clear();
508  rval = mb.get_entities_by_handle( *i, ents );CHECK_ERR( rval );
509  CHECK_EQUAL( 1u, (unsigned)ents.num_of_type( MBVERTEX ) );
510  CHECK_EQUAL( 4u, (unsigned)ents.num_of_type( MBEDGE ) );
511  CHECK_EQUAL( 4u, (unsigned)ents.num_of_type( MBQUAD ) );
512  CHECK_EQUAL( 9u, (unsigned)ents.size() );
513  }
514 
515  // check that each volume has 1 node and 8 hexes.
516  for( i = vols.begin(); i != vols.end(); ++i )
517  {
518  ents.clear();
519  rval = mb.get_entities_by_handle( *i, ents );CHECK_ERR( rval );
520  CHECK_EQUAL( 1u, (unsigned)ents.num_of_type( MBVERTEX ) );
521  CHECK_EQUAL( 8u, (unsigned)ents.num_of_type( MBHEX ) );
522  CHECK_EQUAL( 9u, (unsigned)ents.size() );
523  }
524 
525  // Check that for each geometric entity, any contained vertices
526  // are adjacent to some entity in one of its parents.
527  Range parents, geom, nodes, tmp;
528  for( int d = 0; d < 3; ++d )
529  {
530  const void* vals1[] = { &d };
531  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &dim_tag, vals1, 1, geom );CHECK_ERR( rval );
532 
533  for( i = geom.begin(); i != geom.end(); ++i )
534  {
535  nodes.clear();
536  ents.clear();
537  parents.clear();
538  rval = mb.get_entities_by_type( *i, MBVERTEX, nodes );CHECK_ERR( rval );
539  rval = mb.get_parent_meshsets( *i, parents );CHECK_ERR( rval );
540  for( Range::iterator j = parents.begin(); j != parents.end(); ++j )
541  {
542  tmp.clear();
543  rval = mb.get_entities_by_dimension( *j, d + 1, tmp );CHECK_ERR( rval );
544  ents.merge( tmp );
545  }
546  tmp.clear();
547  rval = mb.get_adjacencies( ents, 0, false, tmp, Interface::UNION );CHECK_ERR( rval );
548  nodes = subtract( nodes, tmp );
549  CHECK( nodes.empty() );
550  }
551  }
552 }
553 
554 // expect one block containing entire mesh, with id == 1
556 {
557  ErrorCode rval;
558  Core mb_impl;
559  Interface& mb = mb_impl;
561  Tag mat_tag;
562  rval = mb.tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mat_tag );CHECK_ERR( rval );
563 
564  Range blocks;
565  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &mat_tag, 0, 1, blocks );CHECK_ERR( rval );
566  CHECK_EQUAL( 1u, (unsigned)blocks.size() );
567  EntityHandle block = blocks.front();
568  int id;
569  rval = mb.tag_get_data( mat_tag, &block, 1, &id );CHECK_ERR( rval );
570  CHECK_EQUAL( 1, id );
571 
572  Range block_hexes, mesh_hexes;
573  rval = mb.get_entities_by_dimension( 0, 3, mesh_hexes );CHECK_ERR( rval );
574  rval = mb.get_entities_by_dimension( block, 3, block_hexes, true );CHECK_ERR( rval );
575  CHECK( mesh_hexes == block_hexes );
576 }
577 
578 // Common code for test_side_sets and test_node sets
579 //\param tag_name NEUMANN_SET_TAG_NAME or DIRICHLET_SET_TAG_NAME
580 //\param count Number of expected sets
581 //\param ids Expected IDs of sets
582 //\param set_surfs One list for each id in "ids" containing the
583 // ids of the geometric surfaces expected to be
584 // contained in the boundary condition set.
585 void test_bc_sets( const char* tag_name, unsigned count, const int* ids, const std::vector< int > set_surfs[] )
586 {
587  ErrorCode rval;
588  Core mb_impl;
589  Interface& mb = mb_impl;
591  Tag ss_tag, gid_tag, dim_tag;
592  rval = mb.tag_get_handle( tag_name, 1, MB_TYPE_INTEGER, ss_tag );CHECK_ERR( rval );
593  rval = mb.tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gid_tag );CHECK_ERR( rval );
594  rval = mb.tag_get_handle( "GEOM_DIMENSION", 1, MB_TYPE_INTEGER, dim_tag );CHECK_ERR( rval );
595 
596  // check number of sidesets and IDs
597  Range sidesets;
598  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &ss_tag, 0, 1, sidesets );CHECK_ERR( rval );
599  CHECK_EQUAL( count, (unsigned)sidesets.size() );
600  std::vector< EntityHandle > handles( count, 0 );
601  for( Range::iterator i = sidesets.begin(); i != sidesets.end(); ++i )
602  {
603  int id;
604  rval = mb.tag_get_data( ss_tag, &*i, 1, &id );CHECK_ERR( rval );
605  unsigned idx;
606  for( idx = 0; idx < count; ++idx )
607  if( ids[idx] == id ) break;
608  CHECK( idx != count );
609  CHECK( handles[idx] == 0 );
610  handles[idx] = *i;
611  }
612 
613  // get surface faces
614  std::vector< Range > exp( count );
615  Range surfs, tmp;
616  Tag tags[] = { dim_tag, gid_tag };
617  for( unsigned i = 0; i < count; ++i )
618  {
619  exp[i].clear();
620  surfs.clear();
621  const int two = 2;
622  for( unsigned j = 0; j < set_surfs[i].size(); ++j )
623  {
624  const void* vals[] = { &two, &set_surfs[i][j] };
625  surfs.clear();
626  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, tags, vals, 2, surfs );CHECK_ERR( rval );
627  CHECK_EQUAL( 1u, (unsigned)surfs.size() );
628  tmp.clear();
629  rval = mb.get_entities_by_dimension( surfs.front(), 2, tmp, true );CHECK_ERR( rval );
630  exp[i].merge( tmp );
631  }
632  }
633 
634  // check each bc set
635  Range act;
636  for( unsigned i = 0; i < count; ++i )
637  {
638  act.clear();
639  rval = mb.get_entities_by_dimension( handles[i], 2, act, true );CHECK_ERR( rval );
640  CHECK( exp[i] == act );
641  }
642 }
643 
644 // expect two sidesets containing two geometric surfaces each:
645 // sideset 1 : surfaces 1 and 7
646 // sideset 2 : surfaces 5 and 11
648 {
649  int ids[] = { 1, 2 };
650  std::vector< int > surfs[2];
651  surfs[0].push_back( 1 );
652  surfs[0].push_back( 7 );
653  surfs[1].push_back( 5 );
654  surfs[1].push_back( 11 );
655  test_bc_sets( NEUMANN_SET_TAG_NAME, 2, ids, surfs );
656 }
657 
659 {
660  int ids[] = { 1, 2 };
661  std::vector< int > surfs[2];
662  surfs[0].push_back( 2 );
663  surfs[0].push_back( 8 );
664  surfs[1].push_back( 3 );
665  surfs[1].push_back( 9 );
666  test_bc_sets( DIRICHLET_SET_TAG_NAME, 2, ids, surfs );
667 }
668 
669 static EntityHandle find_side( Interface& moab, EntityHandle entity, int side_dim, int side_num )
670 {
671  ErrorCode rval;
672 
673  std::vector< EntityHandle > adj;
674  rval = moab.get_adjacencies( &entity, 1, side_dim, false, adj );CHECK_ERR( rval );
675 
676  int sub_ent_indices[4];
677  CN::SubEntityVertexIndices( TYPE_FROM_HANDLE( entity ), side_dim, side_num, sub_ent_indices );
678  EntityType subtype = CN::SubEntityType( TYPE_FROM_HANDLE( entity ), side_dim, side_num );
679  int sub_ent_corners = CN::VerticesPerEntity( subtype );
680 
681  const EntityHandle* conn;
682  int conn_len;
683  rval = moab.get_connectivity( entity, conn, conn_len );CHECK_ERR( rval );
684 
685  for( size_t i = 0; i < adj.size(); ++i )
686  {
687  if( TYPE_FROM_HANDLE( adj[i] ) != subtype ) continue;
688 
689  const EntityHandle* sub_conn;
690  int sub_len;
691  rval = moab.get_connectivity( adj[i], sub_conn, sub_len );CHECK_ERR( rval );
692 
693  int n = std::find( sub_conn, sub_conn + sub_len, conn[sub_ent_indices[0]] ) - sub_conn;
694  if( n == sub_len ) // no vertex in common
695  continue;
696 
697  // check forward direction
698  int j;
699  for( j = 1; j < sub_ent_corners; ++j )
700  if( conn[sub_ent_indices[j]] != sub_conn[( j + n ) % sub_ent_corners] ) break;
701  if( j == sub_ent_corners ) return adj[i];
702 
703  // check reverse direction
704  for( j = 1; j < sub_ent_corners; ++j )
705  if( conn[sub_ent_indices[j]] != sub_conn[( n + sub_ent_corners - j ) % sub_ent_corners] ) break;
706  if( j == sub_ent_corners ) return adj[i];
707  }
708 
709  // no match
710  return 0;
711 }
712 
714 {
715  EntityType type = TYPE_FROM_HANDLE( entity );
716  const EntityHandle* conn;
717  int conn_len;
718  ErrorCode rval = moab.get_connectivity( entity, conn, conn_len );CHECK_ERR( rval );
719 
720  int ho[4];
721  CN::HasMidNodes( type, conn_len, ho );
722  for( int dim = CN::Dimension( type ) - 1; dim > 0; --dim )
723  {
724  if( !ho[dim] ) continue;
725 
726  for( int j = 0; j < CN::NumSubEntities( type, dim ); ++j )
727  {
728  EntityHandle side = find_side( moab, entity, dim, j );
729  if( !side ) continue;
730 
731  const EntityHandle* side_conn;
732  int side_len;
733  rval = moab.get_connectivity( side, side_conn, side_len );CHECK_ERR( rval );
734 
735  int this_idx = CN::HONodeIndex( type, conn_len, dim, j );
736  int side_idx = CN::HONodeIndex( TYPE_FROM_HANDLE( side ), side_len, dim, 0 );
737  CHECK_EQUAL( side_conn[side_idx], conn[this_idx] );
738  }
739  }
740 }
741 
742 // Check that element has expected higher-order nodes
743 // and that each higher-order node is at the center
744 // of the sub-entity it is on.
745 void check_ho_element( Interface& moab, EntityHandle entity, int mid_nodes[4] )
746 {
747  // get element info
748  const EntityType type = TYPE_FROM_HANDLE( entity );
749  const EntityHandle* conn;
750  int conn_len;
751  ErrorCode rval = moab.get_connectivity( entity, conn, conn_len );CHECK_ERR( rval );
752  std::vector< double > coords( 3 * conn_len );
753  rval = moab.get_coords( conn, conn_len, &coords[0] );CHECK_ERR( rval );
754 
755  // calculate and verify expected number of mid nodes
756  int num_nodes = CN::VerticesPerEntity( type );
757  for( int d = 1; d <= CN::Dimension( type ); ++d )
758  if( mid_nodes[d] ) num_nodes += CN::NumSubEntities( type, d );
759  CHECK_EQUAL( num_nodes, conn_len );
760 
761  // verify that each higher-order node is at the center
762  // of its respective sub-entity.
763  for( int i = CN::VerticesPerEntity( type ); i < num_nodes; ++i )
764  {
765  // get sub-entity owning ho-node
766  int sub_dim, sub_num;
767  CN::HONodeParent( type, num_nodes, i, sub_dim, sub_num );
768  // get corner vertex indices
769  int sub_conn[8], num_sub;
770  if( sub_dim < CN::Dimension( type ) )
771  {
772  CN::SubEntityVertexIndices( type, sub_dim, sub_num, sub_conn );
773  EntityType sub_type = CN::SubEntityType( type, sub_dim, sub_num );
774  num_sub = CN::VerticesPerEntity( sub_type );
775  }
776  else
777  {
778  num_sub = CN::VerticesPerEntity( type );
779  for( int j = 0; j < num_sub; ++j )
780  sub_conn[j] = j;
781  }
782  // calculate mean of corner vertices
783  double mean[3] = { 0, 0, 0 };
784  for( int j = 0; j < num_sub; ++j )
785  {
786  int co = 3 * sub_conn[j];
787  mean[0] += coords[co];
788  mean[1] += coords[co + 1];
789  mean[2] += coords[co + 2];
790  }
791  mean[0] /= num_sub;
792  mean[1] /= num_sub;
793  mean[2] /= num_sub;
794  // verify that higher-order node is at expected location
795  CHECK_REAL_EQUAL( mean[0], coords[3 * i], 1e-6 );
796  CHECK_REAL_EQUAL( mean[1], coords[3 * i + 1], 1e-6 );
797  CHECK_REAL_EQUAL( mean[2], coords[3 * i + 2], 1e-6 );
798  }
799 }
800 
801 // Validate elements of specified type.
802 // Looks for a block containing the specified entity type
803 // and with the specified mid-node flags set in its
804 // HAS_MID_NODES_TAG.
805 void test_ho_elements( EntityType type, int num_nodes )
806 {
807  Core mb_impl;
808  Interface& mb = mb_impl;
809  read_file( mb, ho_file );
810 
811  ErrorCode rval;
812  Tag ho_tag, block_tag;
813  rval = mb.tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, block_tag );CHECK_ERR( rval );
814  rval = mb.tag_get_handle( HAS_MID_NODES_TAG_NAME, 4, MB_TYPE_INTEGER, ho_tag );CHECK_ERR( rval );
815 
816  // get material sets with expected higher-order nodes
817  Range blocks;
818  int ho_flags[4];
819  CN::HasMidNodes( type, num_nodes, ho_flags );
820  Tag tags[2] = { ho_tag, block_tag };
821  void* vals[2] = { ho_flags, NULL };
822  rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, tags, vals, 2, blocks );CHECK_ERR( rval );
823 
824  Range::iterator i;
825  Range entities;
826  for( i = blocks.begin(); i != blocks.end(); ++i )
827  {
828  rval = mb.get_entities_by_type( *i, type, entities, true );CHECK_ERR( rval );
829  }
830  // test file should contain all types of HO entities
831  CHECK( !entities.empty() );
832  // test ho node positions -- expect to be at center of adj corners
833  for( i = entities.begin(); i != entities.end(); ++i )
834  check_ho_element( mb, *i, ho_flags );
835  // test ho node handles consistent with adjacent entities
836  for( i = entities.begin(); i != entities.end(); ++i )
837  check_adj_ho_nodes( mb, *i );
838 }
839 
841 {
842  // load two surface meshes, one at z=+5 at z=-5.
843  ErrorCode rval;
844  Core mb_impl;
845  Interface& mb = mb_impl;
846  Range file1_ents, file2_ents;
848  mb.get_entities_by_handle( 0, file1_ents );
850  mb.get_entities_by_handle( 0, file2_ents );
851  file2_ents = subtract( file2_ents, file1_ents );
852  EntityHandle file1, file2;
853  mb.create_meshset( MESHSET_SET, file1 );
854  mb.create_meshset( MESHSET_SET, file2 );
855  mb.add_entities( file1, file1_ents );
856  mb.add_entities( file2, file2_ents );
857 
858  // first check that we get the same number of verts from
859  // each file and that they are distinct vertices
860  Range file1_verts, file2_verts;
861  rval = mb.get_entities_by_type( file1, MBVERTEX, file1_verts );CHECK_ERR( rval );
862  CHECK( !file1_verts.empty() );
863  rval = mb.get_entities_by_type( file2, MBVERTEX, file2_verts );CHECK_ERR( rval );
864  CHECK( !file2_verts.empty() );
865  CHECK_EQUAL( file1_verts.size(), file2_verts.size() );
866  CHECK( intersect( file1_verts, file2_verts ).empty() );
867 
868  // now check that we get the same number of elements from
869  // each file and that they are distinct
870  Range file1_elems, file2_elems;
871  rval = mb.get_entities_by_dimension( file1, 3, file1_elems );CHECK_ERR( rval );
872  CHECK( !file1_elems.empty() );
873  rval = mb.get_entities_by_dimension( file2, 3, file2_elems );CHECK_ERR( rval );
874  CHECK( !file2_elems.empty() );
875  CHECK_EQUAL( file1_elems.size(), file2_elems.size() );
876  CHECK( intersect( file1_elems, file2_elems ).empty() );
877 
878  // now check that the connectivity for each element is
879  // defined using the appropriate vertex instances
880  Range file1_elem_verts, file2_elem_verts;
881  rval = mb.get_adjacencies( file1_elems, 0, false, file1_elem_verts, Interface::UNION );CHECK_ERR( rval );
882  rval = mb.get_adjacencies( file2_elems, 0, false, file2_elem_verts, Interface::UNION );CHECK_ERR( rval );
883  CHECK_EQUAL( file1_elem_verts.size(), file2_elem_verts.size() );
884  CHECK( intersect( file1_elem_verts, file1_verts ) == file1_elem_verts );
885  CHECK( intersect( file2_elem_verts, file2_verts ) == file2_elem_verts );
886 }
887 
889 {
890  Core mb_impl;
891  Interface& mb = mb_impl;
893 }
894 
896 {
897  Core mb_impl;
898  Interface& mb = mb_impl;
900  // check the global id for some geometry sets
901  GeomTopoTool gtt( &mb_impl );
902  Range ranges[5];
903  ErrorCode rval = gtt.find_geomsets( ranges );CHECK_ERR( rval );
904  EntityHandle set0 = ranges[0][0]; // does it have a global id > 0?
905  Tag gid_tag;
906  rval = mb.tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, gid_tag );CHECK_ERR( rval );
907 
908  int val;
909  rval = mb.tag_get_data( gid_tag, &set0, 1, &val );
910  CHECK( val != 0 );
911 }