MOAB: Mesh Oriented datABase  (version 5.5.0)
MBTest.cpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 /*!
17  MBTest.cpp
18  Test Harness for MB mesh database system
19 */
20 
21 #ifdef WIN32
22 #ifdef _DEBUG
23 // turn off warnings that say they debugging identifier has been truncated
24 // this warning comes up when using some STL containers
25 #pragma warning( disable : 4786 )
26 #endif
27 #endif
28 
29 #include <iostream>
30 #include <fstream>
31 #include <algorithm>
32 #include <cstdio>
33 #include <ctime>
34 #include <cassert>
35 #include <cmath>
36 #include <cstdio>
37 #include "moab/Interface.hpp"
38 #include "MBTagConventions.hpp"
39 #include "moab/Range.hpp"
40 #include "moab/Skinner.hpp"
41 #include "moab/MeshTopoUtil.hpp"
42 #include "moab/CN.hpp"
43 #include "moab/OrientedBox.hpp"
44 #include "moab/CartVect.hpp"
45 #include "moab/WriteUtilIface.hpp"
46 
47 #ifdef MOAB_HAVE_MPI
48 #include "moab_mpi.h"
49 #endif
50 
51 #ifndef IS_BUILDING_MB
52 #define IS_BUILDING_MB
53 #endif
54 #include "Internals.hpp"
55 #include "moab/Core.hpp"
56 #include "SequenceManager.hpp"
57 #include "EntitySequence.hpp"
59 #include "moab/Error.hpp"
60 #include "moab/ScdInterface.hpp"
61 
62 /* Use the following define to specify that our tests
63  return an error code and not the default void */
64 #define TEST_USES_ERR_CODES
65 #include "TestUtil.hpp"
66 
67 using namespace std;
68 using namespace moab;
69 
70 #define CHKERR( A ) \
71  do \
72  { \
73  if( MB_SUCCESS != ( A ) ) \
74  { \
75  std::cerr << "Failure (error code " << ( A ) << ") at " __FILE__ ":" << __LINE__ << std::endl; \
76  return A; \
77  } \
78  } while( false )
79 
80 #ifdef MOAB_HAVE_NETCDF
82 {
83  std::string file_name = TestDir + "unittest/mbtest1.g";
84  ErrorCode error = iface->load_mesh( file_name.c_str() );
85  if( MB_SUCCESS != error )
86  {
87  std::cout << "Failed to load input file: " << file_name << std::endl;
88  std::string error_reason;
89  iface->get_last_error( error_reason );
90  cout << error_reason << std::endl;
91  }
92  return error;
93 }
94 #endif
95 
96 /* Create a regular 2x2x2 hex mesh */
98 
100 
101 /*!
102  @test
103  Vertex Coordinates
104  @li Get coordinates of vertex 1 correctly
105  @li Get coordinates of vertex 8 correctly
106  @li Get coordinates of vertex 6 correctly
107 */
109 {
110  Core moab;
111  Interface* MB = &moab;
113 
114  Range vertices;
115  error = MB->get_entities_by_type( 0, MBVERTEX, vertices );MB_CHK_ERR( error );
116 
117  std::vector< double > all_coords( 3 * vertices.size() );
118  double* coord_iter = &all_coords[0];
119  for( Range::iterator iter = vertices.begin(); iter != vertices.end(); ++iter )
120  {
121  error = MB->get_coords( &( *iter ), 1, coord_iter );MB_CHK_ERR( error );
122  coord_iter += 3;
123  }
124 
125  // check blocked coordinates
126  const size_t N = vertices.size() + 1;
127  std::vector< double > x( N ), y( N ), z( N );
128  // set last value so we can check later that nothing wrote past the
129  // intended end of an array
130  x[vertices.size()] = y[vertices.size()] = z[vertices.size()] = -3.14159;
131  error = MB->get_coords( vertices, &x[0], &y[0], &z[0] );
132  for( size_t i = 0; i < vertices.size(); ++i )
133  {
134  CHECK_REAL_EQUAL( all_coords[3 * i], x[i], 1E-12 );
135  CHECK_REAL_EQUAL( all_coords[3 * i + 1], y[i], 1E-12 );
136  CHECK_REAL_EQUAL( all_coords[3 * i + 2], z[i], 1E-12 );
137  }
138  // checkthat get_coords did not write past intended end of arrays
139  CHECK_REAL_EQUAL( -3.14159, x[vertices.size()], 1E-12 );
140  CHECK_REAL_EQUAL( -3.14159, y[vertices.size()], 1E-12 );
141  CHECK_REAL_EQUAL( -3.14159, z[vertices.size()], 1E-12 );
142 
143  // add invalid handle to end of range and try query again
144  vertices.insert( vertices.back() + 1 );
145  error = MB->get_coords( vertices, &x[0], &y[0], &z[0] );
147 
148  // Try getting coordinates for a hex (should fail)
149  Range hexes;
150  error = MB->get_entities_by_type( 0, MBHEX, hexes );MB_CHK_ERR( error );
151  EntityHandle handle = hexes.front();
152  error = MB->get_coords( &handle, 1, &x[0] );MB_CHK_ERR( error );
153  CHECK_REAL_EQUAL( 0.5, x[0], 1E-12 );
154  CHECK_REAL_EQUAL( 0.5, x[1], 1E-12 );
155  CHECK_REAL_EQUAL( 0.5, x[2], 1E-12 );
156 
157  return MB_SUCCESS;
158 }
159 
160 /*!
161  @test
162  MB Vertex Tag Test
163  @li Add, Set and correctly get an int tag
164  @li Add, Set and correctly get a boolean tag
165  @li Add, Set and correctly get a double tag
166  @li Add, Set and correctly get a struct tag
167 */
169 {
170  Core moab;
171  Interface* MB = &moab;
173  if( MB_SUCCESS != error ) return error;
174 
175  // Add an int Vertex Tag to the database
176 
177  Tag tag_id;
178 
179  // Create a dense tag for all vertices
180  error = MB->tag_get_handle( "int_tag", 1, MB_TYPE_INTEGER, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
181  if( error != MB_SUCCESS ) return error;
182 
183  // put a value in vertex 1 and retrieve
184  std::vector< EntityHandle > verts;
185  error = MB->get_entities_by_type( 0, MBVERTEX, verts );
186  if( MB_SUCCESS != error ) return error;
187  EntityHandle handle = verts[0];
188  int input_value = 11;
189  error = MB->tag_set_data( tag_id, &handle, 1, &input_value );
190  if( MB_SUCCESS != error ) return error;
191 
192  int output_value;
193  error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
194  if( MB_SUCCESS != error )
195  return error;
196  else if( output_value != input_value )
197  return MB_FAILURE;
198 
199  // put a value in vertex 5 and retrieve
200 
201  handle = verts[5];
202  input_value = 11;
203  error = MB->tag_set_data( tag_id, &handle, 1, &input_value );
204  if( MB_SUCCESS != error ) return error;
205  error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
206  if( MB_SUCCESS != error )
207  return error;
208  else if( output_value != input_value )
209  return MB_FAILURE;
210 
211  // put a value in vertex 98088234 which doesn't exist
212  handle = *std::max_element( verts.begin(), verts.end() ) + 1;
213  input_value = 11;
214 
215  error = MB->tag_set_data( tag_id, &handle, 1, &input_value );
216  if( error == MB_SUCCESS ) return error;
217 
218  error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
219  if( error == MB_SUCCESS ) return error;
220 
221  if( output_value != input_value ) return MB_FAILURE;
222 
223  // Add a bool Vertex Tag to the database
224 
225  error = MB->tag_get_handle( "bool_tag", sizeof( bool ), MB_TYPE_OPAQUE, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
226  if( error != MB_SUCCESS ) return error;
227 
228  // put a value in vertex 5 and retrieve
229 
230  handle = verts[5];
231  bool bool_input_value = true;
232  bool bool_output_value = false;
233  error = MB->tag_set_data( tag_id, &handle, 1, &bool_input_value );
234  if( error != MB_SUCCESS ) return error;
235  error = MB->tag_get_data( tag_id, &handle, 1, &bool_output_value );
236  if( error != MB_SUCCESS )
237  return error;
238  else if( bool_output_value != bool_input_value )
239  return MB_FAILURE;
240 
241  // Add a double Vertex Tag to the database
242 
243  error = MB->tag_get_handle( "double_tag", 1, MB_TYPE_DOUBLE, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
244  if( error != MB_SUCCESS ) return error;
245 
246  // put a value in vertex 8: and retrieve
247 
248  handle = verts[8];
249  double double_input_value = 1.0;
250  double double_output_value = 0.0;
251  error = MB->tag_set_data( tag_id, &handle, 1, &double_input_value );
252  if( error != MB_SUCCESS ) return error;
253 
254  error = MB->tag_get_data( tag_id, &handle, 1, &double_output_value );
255  if( error != MB_SUCCESS )
256  return error;
257  else if( double_output_value != double_input_value )
258  return MB_FAILURE;
259 
260  // Add a struct Vertex Tag to the database
261 
262  struct TagStruct
263  {
264  int test_int;
265  double test_double;
266  };
267  error =
268  MB->tag_get_handle( "struct_tag", sizeof( TagStruct ), MB_TYPE_OPAQUE, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
269  if( error != MB_SUCCESS ) return error;
270 
271  // put a value in vertex 7 and retrieve
272 
273  handle = verts[7];
274  TagStruct input_tag_struct;
275  input_tag_struct.test_int = 55;
276  input_tag_struct.test_double = -1.2345;
277  TagStruct output_tag_struct;
278  error = MB->tag_set_data( tag_id, &handle, 1, &input_tag_struct );
279  if( error != MB_SUCCESS ) return error;
280  error = MB->tag_get_data( tag_id, &handle, 1, &output_tag_struct );
281  if( error != MB_SUCCESS )
282  return error;
283  else if( output_tag_struct.test_int != input_tag_struct.test_int ||
284  output_tag_struct.test_double != input_tag_struct.test_double )
285  return MB_FAILURE;
286 
287  // Create sparse tags for 10 random entities including some outside the
288  // range of allowable entities.
289 
290  error = MB->tag_get_handle( "sparse_int_tag", 1, MB_TYPE_INTEGER, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
291 
292  if( error != MB_SUCCESS ) return error;
293 
294  // print_yes = true;
295  int i;
296  for( i = 0; i < 10; i++ )
297  {
298  // use invalid handles for odd values
299 
300  if( i % 2 )
301  handle = verts[i] + *std::max_element( verts.begin(), verts.end() );
302  else
303  handle = verts[i];
304 
305  input_value = 11;
306  error = MB->tag_set_data( tag_id, &handle, 1, &input_value );
307 
308  // should fail on odd values of i
309  if( !( i % 2 ) )
310  {
311  if( error != MB_SUCCESS ) // even case and if failed
312  return error;
313  }
314  else
315  {
316  if( error == MB_SUCCESS ) // odd case and it says it worked!
317  return MB_FAILURE;
318  }
319 
320  error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
321  if( ( i % 2 ) && error != MB_FAILURE && error != MB_TAG_NOT_FOUND ) return error;
322 
323  if( ( i % 2 ) && output_value != input_value ) return MB_FAILURE;
324  }
325 
326  // get the tag_name of the last tag created above
327  std::string int_tag_name;
328  error = MB->tag_get_name( tag_id, int_tag_name );
329  if( error != MB_SUCCESS ) return error;
330 
331  if( int_tag_name != "sparse_int_tag" ) return MB_FAILURE;
332 
333  // get the tag handle of the last tag created above
334  Tag int_tag_handle;
335  error = MB->tag_get_handle( int_tag_name.c_str(), 1, MB_TYPE_INTEGER, int_tag_handle );
336  if( MB_SUCCESS != error ) return error;
337 
338  if( int_tag_handle != tag_id ) return MB_FAILURE;
339 
340  // test tag_get_tags_on_entity and tag_delete_data
341  std::vector< Tag > all_tags;
342  handle = verts[0];
343  error = MB->tag_get_tags_on_entity( handle, all_tags );
344  if( MB_SUCCESS != error ) return error;
345 
346  if( !all_tags.empty() )
347  {
348  error = MB->tag_delete_data( all_tags[0], &handle, 1 );
349  if( MB_SUCCESS != error ) return error;
350 
351  error = MB->tag_delete( all_tags[0] );
352  if( MB_SUCCESS != error ) return error;
353  }
354  // delete tags test
355 
356  // delete 2 of the sparse tags that were created above.
357  handle = verts[2];
358  error = MB->tag_delete_data( tag_id, &handle, 1 );
359  if( error != MB_SUCCESS ) return error;
360 
361  handle = verts[6];
362  error = MB->tag_delete_data( tag_id, &handle, 1 );
363  if( error != MB_SUCCESS ) return error;
364 
365  // delete all the rest of the sparse tags.
366 
367  error = MB->tag_delete( tag_id );
368  if( error != MB_SUCCESS ) return error;
369 
370  // delete the dense tag named bool_tag
371  Tag bool_tag_handle;
372  error = MB->tag_get_handle( "bool_tag", sizeof( bool ), MB_TYPE_OPAQUE, bool_tag_handle );
373  if( error != MB_SUCCESS ) return error;
374 
375  error = MB->tag_delete( bool_tag_handle );
376  if( error != MB_SUCCESS ) return error;
377 
378  return error;
379 }
380 
382 {
383  Core moab;
384  Interface* gMB = &moab;
385 
386  double array[3] = { 0.0, 0.0, 0.0 };
387  EntityHandle h_node1;
388  ErrorCode result = gMB->create_vertex( array, h_node1 );
389  if( MB_SUCCESS != result ) return result;
390 
391  EntityHandle ordered_meshset1;
392  result = gMB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, ordered_meshset1 );
393  if( MB_SUCCESS != result ) return result;
394 
395  EntityHandle ordered_meshset2;
396  result = gMB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, ordered_meshset2 );
397  if( MB_SUCCESS != result ) return result;
398 
399  result = gMB->add_entities( ordered_meshset1, &h_node1, 1 );
400  if( MB_SUCCESS != result ) return result;
401 
402  result = gMB->remove_entities( ordered_meshset1, &h_node1, 1 );
403  if( MB_SUCCESS != result ) return result;
404 
405  result = gMB->add_entities( ordered_meshset2, &h_node1, 1 );
406  if( MB_SUCCESS != result ) return result;
407 
408  bool create_if_missing = false;
409  std::vector< EntityHandle > meshsets;
410  result = gMB->get_adjacencies( &h_node1, 1, 4, create_if_missing, meshsets );
411  if( MB_SUCCESS != result ) return result;
412 
413  if( 1u != meshsets.size() ) return MB_FAILURE;
414 
415  return MB_SUCCESS;
416 }
417 
419 {
420  Core moab;
421  Interface* mb = &moab;
422  ErrorCode rval = create_some_mesh( mb );
423  if( MB_SUCCESS != rval ) return rval;
424 
425  Range hexes, expt_vert, got_vert, some_hexes;
427  int n;
428 
429  // get all hexes
430  rval = mb->get_entities_by_type( 0, MBHEX, hexes );
431  if( rval != MB_SUCCESS ) return rval;
432  if( hexes.empty() ) // can't do test if no elements
433  return MB_FAILURE;
434 
435  // get every third hex and its vertices
436  n = 0;
437  for( i = hexes.begin(); i != hexes.end(); ++i )
438  {
439  if( ++n % 3 ) continue;
440  some_hexes.insert( *i );
441  const EntityHandle* conn;
442  int len;
443  rval = mb->get_connectivity( *i, conn, len );
444  if( MB_SUCCESS != rval ) return rval;
445  for( int k = 0; k < len; ++k )
446  expt_vert.insert( conn[k] );
447  }
448 
449  // use get_adjacencies to get vertices
450  rval = mb->get_adjacencies( some_hexes, 0, false, got_vert, Interface::UNION );
451  if( MB_SUCCESS != rval )
452  {
453  std::cout << "get_adjacencies failed with error code " << rval << std::endl;
454  return rval;
455  }
456 
457  i = expt_vert.begin();
458  j = got_vert.begin();
459  while( i != expt_vert.end() && j != got_vert.end() )
460  {
461  if( *i < *j )
462  {
463  std::cout << "Result missing vertex: " << *i << std::endl;
464  return MB_FAILURE;
465  }
466  else if( *j < *i )
467  {
468  std::cout << "Result contains extra vertex: " << *j << std::endl;
469  return MB_FAILURE;
470  }
471  ++i;
472  ++j;
473  }
474 
475  if( i != expt_vert.end() )
476  {
477  std::cout << "Result missing vertex: " << *i << std::endl;
478  return MB_FAILURE;
479  }
480  else if( j != got_vert.end() )
481  {
482  std::cout << "Result contains extra vertex: " << *j << std::endl;
483  return MB_FAILURE;
484  }
485 
486  return MB_SUCCESS;
487 }
488 #ifdef MOAB_HAVE_NETCDF
489 ErrorCode mb_adjacencies_test()
490 {
491  Core moab;
492  Interface* mb = &moab;
493  ErrorCode result = load_file_one( mb );
494  if( MB_SUCCESS != result ) return result;
495 
496  // this test does the following:
497  // 1. For each element, creates vertex-element adjacencies (only for
498  // lowest-id vertex)
499  // 2. Creates all lower-order ancillary entities
500  // 3. Checks for proper number of same
501  //
502  // assume mesh has already been read
503 
504  EntityType seq_type;
505  Range handle_range;
506 
507  // lets create a skin of the hexes
508  // this may be far from being the most efficient, but
509  // it certainly does exercise the adjacency routines
510 
511  Range::iterator iter;
513 
514  // first get the hexes
515  Range hexes;
516  result = mb->get_entities_by_type( 0, MBHEX, hexes );
517  if( MB_SUCCESS != result ) return result;
518 
519  unsigned int num_hexes = hexes.size();
520 
521  // make sure we got hexes
522  for( riter = hexes.rbegin(); riter != hexes.rend(); ++riter )
523  {
524  if( TYPE_FROM_HANDLE( *riter ) != MBHEX ) return MB_FAILURE;
525  }
526 
527  // get all the nodes that these hexes are connected to
528  Range nodes;
529  result = mb->get_adjacencies( hexes, 0, false, nodes, Interface::UNION );
530  if( MB_SUCCESS != result ) return result;
531 
532  // make sure we got nodes
533  for( iter = nodes.begin(); iter != nodes.end(); ++iter )
534  {
535  if( TYPE_FROM_HANDLE( *iter ) != MBVERTEX ) return MB_FAILURE;
536  }
537 
538  // find the interior nodes; assume a structured mesh
539  Range interior_nodes;
540  std::vector< EntityHandle > attached_hexes;
541  for( iter = nodes.begin(); iter != nodes.end(); )
542  {
543  attached_hexes.clear();
544  result = mb->get_adjacencies( &( *iter ), 1, 3, false, attached_hexes );
545  if( MB_SUCCESS != result ) return result;
546  attached_hexes.erase( std::remove_if( attached_hexes.begin(), attached_hexes.end(),
547  type_not_equals( mb, MBHEX ) ),
548  attached_hexes.end() );
549 
550  // if this node has less than 8 hexes attached to it, it is not
551  // an interior node
552  if( attached_hexes.size() == 8 )
553  {
554  // add to the interior nodes list and remove from the nodes list
555  interior_nodes.insert( *iter );
556  iter = nodes.erase( iter );
557  }
558  else
559  ++iter;
560  }
561 
562  // get interior quads from interior nodes
563  Range interior_quads;
564  result = mb->get_adjacencies( interior_nodes, 2, true, interior_quads, Interface::UNION );
565  if( MB_SUCCESS != result ) return result;
566 
567  // get a list of quads generated adjacent to the exterior nodes
568  Range temp_quads, exterior_quads;
569  result = mb->get_adjacencies( nodes, 2, true, temp_quads, Interface::UNION );
570  if( MB_SUCCESS != result ) return result;
571 
572  // now remove any interior quads from the previous quads list
573  // and we should be left with exterior quads
574  std::set_difference( temp_quads.begin(), temp_quads.end(), interior_quads.begin(), interior_quads.end(),
575  range_inserter( exterior_quads ) );
576 
577  // check to make sure we have the right number of quads; for hexes, should be
578  // .5(6*num_hexes - num_exterior_quads)
579  unsigned int num_expected_int_quads = ( 6 * num_hexes - exterior_quads.size() ) / 2;
580  if( num_expected_int_quads != interior_quads.size() ) return MB_FAILURE;
581 
582  // delete the interior quads
583  result = mb->delete_entities( interior_quads );
584  if( MB_SUCCESS != result ) return result;
585 
586  Range remaining_quads;
587  result = mb->get_entities_by_type( 0, MBQUAD, remaining_quads );
588  if( MB_SUCCESS != result ) return result;
589 
590  if( remaining_quads.size() != exterior_quads.size() ) return MB_FAILURE;
591 
592  // 3. Checks for proper number of same
593  // re-retrieve and store the handle ranges for all element types
594 
595  int num_ents;
596 
597  for( seq_type = MBEDGE; seq_type != MBENTITYSET; seq_type++ )
598  {
599  handle_range.clear();
600 
601  result = mb->get_entities_by_type( 0, seq_type, handle_range );
602  if( MB_SUCCESS != result ) return result;
603 
604  result = mb->get_number_entities_by_type( 0, seq_type, num_ents );
605  if( MB_SUCCESS != result ) return result;
606 
607  if( handle_range.size() != (unsigned int)num_ents ) return MB_FAILURE;
608  }
609 
610  return result;
611 }
612 
613 #endif
614 
616 {
617  Core moab;
618  Interface* mb = &moab;
619  ErrorCode rval;
620 
621  double coords[] = { 0, 0, 0, 2, 0, 0, 1, 2, 0 };
622  Range verts;
623  rval = mb->create_vertices( coords, 3, verts );
624  if( MB_SUCCESS != rval ) return rval;
625  if( verts.size() != 3 ) return MB_FAILURE;
626  EntityHandle vert_arr[3];
627 
628  EntityHandle tri;
629  std::copy( verts.begin(), verts.end(), vert_arr );
630  rval = mb->create_element( MBTRI, vert_arr, 3, tri );
631  if( MB_SUCCESS != rval ) return rval;
632 
633  vert_arr[2] = vert_arr[0];
634  EntityHandle forward_edge, reverse_edge;
635  rval = mb->create_element( MBEDGE, vert_arr, 2, forward_edge );
636  if( MB_SUCCESS != rval ) return rval;
637 
638  std::vector< EntityHandle > results;
639  rval = mb->get_adjacencies( &forward_edge, 1, 2, false, results );
640  if( results.size() != 1 || results.front() != tri )
641  {
642  std::cerr << "Adjacency query from forward edge to tri failed at " << __FILE__ << ":" << __LINE__ << std::endl;
643  return MB_FAILURE;
644  }
645  results.clear();
646  rval = mb->get_adjacencies( &tri, 1, 1, false, results );
647  if( results.size() != 1 || results.front() != forward_edge )
648  {
649  std::cerr << "Adjacency query from tri to forward edge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
650  return MB_FAILURE;
651  }
652 
653  rval = mb->delete_entities( &forward_edge, 1 );
654  if( MB_SUCCESS != rval ) return rval;
655 
656  results.clear();
657  rval = mb->get_adjacencies( &tri, 1, 1, false, results );
658  if( !results.empty() )
659  {
660  std::cerr << "Adjacency query from tri returned non-existent edge at " << __FILE__ << ":" << __LINE__
661  << std::endl;
662  return MB_FAILURE;
663  }
664 
665  rval = mb->create_element( MBEDGE, vert_arr + 1, 2, reverse_edge );
666  if( MB_SUCCESS != rval ) return rval;
667 
668  results.clear();
669  rval = mb->get_adjacencies( &reverse_edge, 1, 2, false, results );
670  if( results.size() != 1 || results.front() != tri )
671  {
672  std::cerr << "Adjacency query from reverse edge to tri failed at " << __FILE__ << ":" << __LINE__ << std::endl;
673  return MB_FAILURE;
674  }
675  results.clear();
676  rval = mb->get_adjacencies( &tri, 1, 1, false, results );
677  if( results.size() != 1 || results.front() != reverse_edge )
678  {
679  std::cerr << "Adjacency query from tri to reverse edge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
680  return MB_FAILURE;
681  }
682 
683  return MB_SUCCESS;
684 }
685 
687  EntityHandle vertices[12],
688  EntityHandle hexes[2],
689  EntityHandle hex1_faces[6],
690  EntityHandle hex2_faces[6],
691  EntityHandle hex1_edges[12],
692  EntityHandle hex2_edges[12] )
693 {
694  ErrorCode rval;
695  // create a simple mesh containing 2 hexes
696  const double coords[] = { 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 1, 0, 1, 1, 0, 2, 1, 0,
697  0, 0, 1, 1, 0, 1, 2, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1 };
698  for( int i = 0; i < 12; ++i )
699  if( MB_SUCCESS != mb->create_vertex( coords + 3 * i, vertices[i] ) ) return MB_FAILURE;
700  EntityHandle hex1_conn[] = { vertices[6], vertices[7], vertices[1], vertices[0],
701  vertices[9], vertices[10], vertices[4], vertices[3] };
702  EntityHandle hex2_conn[] = { vertices[7], vertices[8], vertices[2], vertices[1],
703  vertices[10], vertices[11], vertices[5], vertices[4] };
704  EntityHandle shared_quad_conn[] = { vertices[7], vertices[1], vertices[4], vertices[10] };
705  EntityHandle hex1_face_conn[][4] = { { vertices[6], vertices[7], vertices[10], vertices[9] },
706  { vertices[7], vertices[6], vertices[0], vertices[1] },
707  { vertices[1], vertices[0], vertices[3], vertices[4] },
708  { vertices[9], vertices[10], vertices[4], vertices[3] },
709  { vertices[3], vertices[0], vertices[6], vertices[9] } };
710  EntityHandle hex2_face_conn[][4] = { { vertices[7], vertices[8], vertices[11], vertices[10] },
711  { vertices[8], vertices[7], vertices[1], vertices[2] },
712  { vertices[2], vertices[1], vertices[4], vertices[5] },
713  { vertices[10], vertices[11], vertices[5], vertices[4] },
714  { vertices[5], vertices[2], vertices[8], vertices[11] } };
715  EntityHandle shared_edge_conn[][2] = { { vertices[1], vertices[7] },
716  { vertices[7], vertices[10] },
717  { vertices[10], vertices[4] },
718  { vertices[4], vertices[1] } };
719  EntityHandle hex1_edge_conn[][2] = { { vertices[6], vertices[7] }, { vertices[9], vertices[10] },
720  { vertices[3], vertices[4] }, { vertices[0], vertices[1] },
721  { vertices[6], vertices[9] }, { vertices[9], vertices[3] },
722  { vertices[3], vertices[0] }, { vertices[0], vertices[6] } };
723  EntityHandle hex2_edge_conn[][2] = { { vertices[7], vertices[8] }, { vertices[10], vertices[11] },
724  { vertices[4], vertices[5] }, { vertices[1], vertices[2] },
725  { vertices[8], vertices[11] }, { vertices[11], vertices[5] },
726  { vertices[5], vertices[2] }, { vertices[2], vertices[8] } };
727  rval = mb->create_element( MBHEX, hex1_conn, 8, hexes[0] );
728  if( MB_SUCCESS != rval ) return rval;
729  rval = mb->create_element( MBHEX, hex2_conn, 8, hexes[1] );
730  if( MB_SUCCESS != rval ) return rval;
731  rval = mb->create_element( MBQUAD, shared_quad_conn, 4, hex1_faces[0] );
732  if( MB_SUCCESS != rval ) return rval;
733  hex2_faces[0] = hex1_faces[0];
734  for( int i = 0; i < 5; ++i )
735  {
736  rval = mb->create_element( MBQUAD, hex1_face_conn[i], 4, hex1_faces[i + 1] );
737  if( MB_SUCCESS != rval ) return rval;
738  rval = mb->create_element( MBQUAD, hex2_face_conn[i], 4, hex2_faces[i + 1] );
739  if( MB_SUCCESS != rval ) return rval;
740  }
741  for( int i = 0; i < 4; ++i )
742  {
743  rval = mb->create_element( MBEDGE, shared_edge_conn[i], 2, hex1_edges[i] );
744  if( MB_SUCCESS != rval ) return rval;
745  hex2_edges[i] = hex1_edges[i];
746  }
747  for( int i = 0; i < 8; ++i )
748  {
749  rval = mb->create_element( MBEDGE, hex1_edge_conn[i], 2, hex1_edges[i + 4] );
750  if( MB_SUCCESS != rval ) return rval;
751  rval = mb->create_element( MBEDGE, hex2_edge_conn[i], 2, hex2_edges[i + 4] );
752  if( MB_SUCCESS != rval ) return rval;
753  }
754  return MB_SUCCESS;
755 }
756 
758 {
759  ErrorCode rval;
760  Core moab;
761  Interface* mb = &moab;
762 
763  // create a simple mesh containing 2 hexes
764  EntityHandle vertices[12], hexes[2], hex1_faces[6], hex2_faces[6], hex1_edges[12], hex2_edges[12];
765  rval = create_two_hex_full_mesh( mb, vertices, hexes, hex1_faces, hex2_faces, hex1_edges, hex2_edges );MB_CHK_ERR( rval );
766 
767  // test adjacences from dim to 3
768  for( int dim = 0; dim < 3; ++dim )
769  {
770  std::vector< EntityHandle > hex1_ent, hex2_ent, shared;
771  const EntityHandle *list1, *list2;
772  int n;
773  switch( dim )
774  {
775  case 0:
776  rval = mb->get_connectivity( hexes[0], list1, n );MB_CHK_ERR( rval );
777  rval = mb->get_connectivity( hexes[1], list2, n );MB_CHK_ERR( rval );
778  break;
779  case 1:
780  list1 = hex1_edges;
781  list2 = hex2_edges;
782  n = 12;
783  break;
784  case 2:
785  list1 = hex1_faces;
786  list2 = hex2_faces;
787  n = 6;
788  break;
789  }
790  // split entities into those uniquely in hex1, those uniquely in hex2
791  // and those shared between the two
792  for( int i = 0; i < n; ++i )
793  {
794  if( std::find( list2, list2 + n, list1[i] ) - list2 == n )
795  hex1_ent.push_back( list1[i] );
796  else
797  shared.push_back( list1[i] );
798  if( std::find( list1, list1 + n, list2[i] ) - list1 == n ) hex2_ent.push_back( list2[i] );
799  }
800  // for each shared entity check that get_adjacencies returns both hexes
801  for( size_t j = 0; j < shared.size(); ++j )
802  {
803  std::vector< EntityHandle > adj;
804  rval = mb->get_adjacencies( &shared[j], 1, 3, false, adj );MB_CHK_ERR( rval );
805  if( adj.size() != 2 )
806  {
807  std::cout << "Expected 2 hexes adjacent to " << dim << "D entity " << j << ". Got " << adj.size()
808  << " hexes." << std::endl;
809  return MB_FAILURE;
810  }
811  if( !( adj[0] == hexes[0] && adj[1] == hexes[1] ) && !( adj[0] == hexes[1] && adj[1] == hexes[0] ) )
812  {
813  std::cout << "Got incorrect hexes adjacent to " << dim << "D entity " << j << std::endl;
814  return MB_FAILURE;
815  }
816  }
817 
818  for( size_t j = 0; j < hex1_ent.size(); ++j )
819  {
820  std::vector< EntityHandle > adj;
821  rval = mb->get_adjacencies( &hex1_ent[j], 1, 3, false, adj );MB_CHK_ERR( rval );
822  CHECK( adj.size() == 1 && adj[0] == hexes[0] );
823  }
824 
825  for( size_t j = 0; j < hex2_ent.size(); ++j )
826  {
827  std::vector< EntityHandle > adj;
828  rval = mb->get_adjacencies( &hex2_ent[j], 1, 3, false, adj );MB_CHK_ERR( rval );
829  CHECK( adj.size() == 1 && adj[0] == hexes[1] );
830  }
831  }
832 
833  // For each edge, get adjacent faces, and for each face
834  // get adjacent hexes. Result should be the same as
835  // direct query from edges to hexes
836  std::vector< EntityHandle > all_edges( 24 );
837  std::copy( hex1_edges, hex1_edges + 12, all_edges.begin() );
838  std::copy( hex2_edges, hex2_edges + 12, all_edges.begin() + 12 );
839  std::sort( all_edges.begin(), all_edges.end() );
840  all_edges.erase( std::unique( all_edges.begin(), all_edges.end() ), all_edges.end() );
841  for( size_t j = 0; j < all_edges.size(); ++j )
842  {
843  std::vector< EntityHandle > edge_hexes, edge_faces, face_hexes;
844  rval = mb->get_adjacencies( &all_edges[j], 1, 3, false, edge_hexes );MB_CHK_ERR( rval );
845  rval = mb->get_adjacencies( &all_edges[j], 1, 2, false, edge_faces );MB_CHK_ERR( rval );
846  rval = mb->get_adjacencies( &edge_faces[0], edge_faces.size(), 3, false, face_hexes, Interface::UNION );MB_CHK_ERR( rval );
847  if( edge_hexes.size() != face_hexes.size() )
848  {
849  std::cout << "Inconsistent adjacency data for edge " << j << ". edge->face->hex resulted in "
850  << face_hexes.size() << "hexes while edge->hex resulted in " << edge_hexes.size() << std::endl;
851  return MB_FAILURE;
852  }
853  switch( edge_hexes.size() )
854  {
855  case 1:
856  CHECK( edge_hexes[0] == face_hexes[0] );
857  break;
858  case 2:
859  CHECK( ( edge_hexes[0] == face_hexes[0] && edge_hexes[1] == face_hexes[1] ) ||
860  ( edge_hexes[0] == face_hexes[1] && edge_hexes[1] == face_hexes[0] ) );
861  break;
862  default:
863  std::cout << "Got " << edge_hexes.size() << " hexes adjacent to edge " << j << std::endl;
864  return MB_FAILURE;
865  }
866  }
867  return MB_SUCCESS;
868 }
869 
871 {
872  Core moab;
873  Interface& mb = moab;
874  ErrorCode rval;
875 
876  // create vertices
877  const double coords[][3] = { { -0.5, -0.5, 0.5 }, { -0.5, -0.5, -0.5 }, { -0.5, 0.5, -0.5 }, { -0.5, 0.5, 0.5 },
878  { 0.5, -0.5, 0.5 }, { 0.5, -0.5, -0.5 }, { 0.5, 0.5, -0.5 }, { 0.5, 0.5, 0.5 } };
879  EntityHandle verts[8] = { 0 };
880  for( int i = 0; i < 8; ++i )
881  {
882  rval = mb.create_vertex( coords[i], verts[i] );MB_CHK_ERR( rval );
883  }
884  // create a single hex
885  const EntityHandle hconn[8] = { verts[0], verts[1], verts[2], verts[3], verts[4], verts[5], verts[6], verts[7] };
886  EntityHandle hex;
887  rval = mb.create_element( MBHEX, hconn, 8, hex );MB_CHK_ERR( rval );
888  // create hex faces
889  std::vector< EntityHandle > quads;
890  rval = mb.get_adjacencies( &hex, 1, 2, true, quads, Interface::UNION );MB_CHK_ERR( rval );
891  CHECK_EQUAL( (size_t)6, quads.size() );
892  // check that we got each of the 6 expected faces, with outwards
893  // normals assuming CCW order and correct connectivity
894  const EntityHandle faces[6][4] = {
895  { verts[0], verts[1], verts[5], verts[4] }, { verts[1], verts[2], verts[6], verts[5] },
896  { verts[2], verts[3], verts[7], verts[6] }, { verts[3], verts[0], verts[4], verts[7] },
897  { verts[3], verts[2], verts[1], verts[0] }, { verts[4], verts[5], verts[6], verts[7] } };
898  for( int i = 0; i < 6; ++i )
899  { // for each expected face
900  // get sorted list of verts first for easy comparison
901  std::vector< EntityHandle > exp_sorted( 4 );
902  std::copy( faces[i], faces[i] + 4, exp_sorted.begin() );
903  std::sort( exp_sorted.begin(), exp_sorted.end() );
904  // search for matching face in output
905  int j = 0;
906  std::vector< EntityHandle > conn;
907  for( ; j < 6; ++j )
908  {
909  conn.clear();
910  rval = mb.get_connectivity( &quads[j], 1, conn );MB_CHK_ERR( rval );
911  CHECK_EQUAL( (size_t)4, conn.size() );
912  std::vector< EntityHandle > sorted( conn );
913  std::sort( sorted.begin(), sorted.end() );
914  if( sorted == exp_sorted ) break;
915  }
916  if( j == 6 )
917  {
918  std::cerr << "No adjacent face matching hex face " << i << std::endl;
919  CHECK( j < 6 );
920  }
921  // check order
922  int k = std::find( conn.begin(), conn.end(), faces[i][0] ) - conn.begin();
923  for( j = 1; j < 4; ++j )
924  if( faces[i][j] != conn[( j + k ) % 4] ) break;
925  if( j != 4 )
926  {
927  std::cerr << "Incorrect vertex order for hex face " << i << std::endl;
928  std::cerr << "Expected: " << faces[i][0] << ", " << faces[i][1] << ", " << faces[i][2] << ", "
929  << faces[i][3] << std::endl;
930  std::cerr << "Actual: " << conn[0] << ", " << conn[1] << ", " << conn[2] << ", " << conn[3] << std::endl;
931  CHECK( false );
932  }
933  }
934  return MB_SUCCESS;
935 }
936 
937 ErrorCode nothing_but_type( Range& range, EntityType type )
938 {
939 
940  // make sure there's nothing but hexes in hex_ms
941  Range::iterator iter, end_iter;
942  iter = range.begin();
943  end_iter = range.end();
944 
945  for( ; iter != end_iter; ++iter )
946  {
947  if( TYPE_FROM_HANDLE( *iter ) != type )
948  {
949  return MB_FAILURE;
950  }
951  }
952  return MB_SUCCESS;
953 }
954 
955 ErrorCode check_esets( Interface* MB, const int num_sets )
956 {
957  int entity_sets_size;
958  ErrorCode result = MB->get_number_entities_by_type( 0, MBENTITYSET, entity_sets_size );
959  if( MB_SUCCESS != result || entity_sets_size != num_sets ) return MB_FAILURE;
960 
961  return MB_SUCCESS;
962 }
963 
965 {
966  Core moab;
967  Interface* MB = &moab;
968  ErrorCode result = create_some_mesh( MB );
969  if( MB_SUCCESS != result ) return result;
970 
971  Range temp_range;
972  std::vector< EntityHandle > temp_vector;
973  EntityType ent_type;
974 
975  EntityHandle ms_array[MBENTITYSET] = { 0 };
976  unsigned int number_array[MBENTITYSET] = { 0 };
977  unsigned int num_dim_array[4] = { 0, 0, 0, 0 };
978  int count, start_num_sets;
979 
980  result = MB->get_number_entities_by_type( 0, MBENTITYSET, start_num_sets );
981  if( MB_SUCCESS != result ) return result;
982 
983  // add entities to meshsets
984  for( ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++ )
985  {
986  result = MB->create_meshset( flags, ms_array[ent_type] );
987  if( result != MB_SUCCESS ) return result;
988 
989  temp_range.clear();
990  result = MB->get_entities_by_type( 0, ent_type, temp_range );
991  if( result != MB_SUCCESS ) return result;
992  result = MB->get_number_entities_by_type( 0, ent_type, count );
993  if( result != MB_SUCCESS ) return result;
994  if( (unsigned)count != temp_range.size() ) return MB_FAILURE;
995  result = MB->add_entities( ms_array[ent_type], temp_range );
996  if( result != MB_SUCCESS ) return result;
997 
998  number_array[ent_type] = temp_range.size(); // KGM
999  num_dim_array[CN::Dimension( ent_type )] += count;
1000 
1001  // Check to make sure mesh set really has correct number of entities in it
1002  temp_range.clear();
1003  temp_vector.clear();
1004  result = MB->get_entities_by_handle( ms_array[ent_type], temp_range );
1005  if( result != MB_SUCCESS ) return result;
1006  if( number_array[ent_type] != temp_range.size() )
1007  {
1008  cout << "Number of entities in meshset test is not correct" << endl;
1009  return MB_FAILURE;
1010  }
1011  if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
1012 
1013  result = MB->get_entities_by_handle( ms_array[ent_type], temp_vector );
1014  if( result != MB_SUCCESS ) return result;
1015  if( number_array[ent_type] != temp_vector.size() )
1016  {
1017  cout << "Number of entities in meshset test is not correct" << endl;
1018  return MB_FAILURE;
1019  }
1020 
1021  temp_range.clear();
1022  result = MB->get_entities_by_type( ms_array[ent_type], ent_type, temp_range );
1023  if( result != MB_SUCCESS ) return result;
1024  if( number_array[ent_type] != temp_range.size() )
1025  {
1026  cout << "Number of entities by type in meshset test is not correct" << endl;
1027  return MB_FAILURE;
1028  }
1029  if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
1030 
1031  temp_range.clear();
1032  result = MB->get_entities_by_type( ms_array[ent_type], MBVERTEX, temp_range );
1033  if( result != MB_SUCCESS ) return result;
1034  if( 0 != temp_range.size() ) return MB_FAILURE;
1035 
1036  temp_range.clear();
1037  result = MB->get_entities_by_dimension( ms_array[ent_type], CN::Dimension( ent_type ), temp_range );
1038  if( result != MB_SUCCESS ) return result;
1039  if( number_array[ent_type] != temp_range.size() )
1040  {
1041  cout << "Number of entities by dimension in meshset test is not correct" << endl;
1042  return MB_FAILURE;
1043  }
1044  if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
1045 
1046  temp_range.clear();
1047  result = MB->get_entities_by_dimension( ms_array[ent_type], 0, temp_range );
1048  if( result != MB_SUCCESS ) return result;
1049  if( 0 != temp_range.size() )
1050  {
1051  cout << "Number of entities by dimension in meshset test is not correct" << endl;
1052  return MB_FAILURE;
1053  }
1054 
1055  result = MB->get_number_entities_by_handle( ms_array[ent_type], count );
1056  if( result != MB_SUCCESS ) return result;
1057  if( (unsigned)count != number_array[ent_type] ) return MB_FAILURE;
1058 
1059  result = MB->get_number_entities_by_type( ms_array[ent_type], ent_type, count );
1060  if( result != MB_SUCCESS ) return result;
1061  if( (unsigned)count != number_array[ent_type] ) return MB_FAILURE;
1062 
1063  result = MB->get_number_entities_by_type( ms_array[ent_type], MBVERTEX, count );
1064  if( result != MB_SUCCESS ) return result;
1065  if( count != 0 ) return MB_FAILURE;
1066 
1067  result = MB->get_number_entities_by_dimension( ms_array[ent_type], CN::Dimension( ent_type ), count );
1068  if( result != MB_SUCCESS ) return result;
1069  if( (unsigned)count != number_array[ent_type] ) return MB_FAILURE;
1070 
1071  result = MB->get_number_entities_by_dimension( ms_array[ent_type], 0, count );
1072  if( result != MB_SUCCESS ) return result;
1073  if( count != 0 ) return MB_FAILURE;
1074  }
1075 
1076  result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE );
1077  if( MB_SUCCESS != result ) return result;
1078 
1079  for( int dim = 1; dim < 4; ++dim )
1080  {
1081  result = MB->get_number_entities_by_dimension( 0, dim, count );
1082  if( MB_SUCCESS != result ) return MB_FAILURE;
1083  if( (unsigned)count != num_dim_array[dim] ) return MB_FAILURE;
1084  }
1085 
1086  //----------TEST RECURSIVE OPERATIONS----------------//
1087  EntityHandle recursive1, recursive2;
1088  result = MB->create_meshset( MESHSET_SET, recursive1 );
1089  if( result != MB_SUCCESS ) return result;
1090  result = MB->create_meshset( 0, recursive2 );
1091  if( result != MB_SUCCESS ) return result;
1092  unsigned num_sets = MBENTITYSET - MBEDGE;
1093  result = MB->add_entities( recursive2, ms_array + MBEDGE, num_sets );
1094  if( MB_SUCCESS != result ) return result;
1095  result = MB->add_entities( recursive1, &recursive2, 1 );
1096  if( MB_SUCCESS != result ) return result;
1097 
1098  temp_range.clear();
1099  result = MB->get_entities_by_type( recursive1, MBENTITYSET, temp_range );
1100  if( MB_SUCCESS != result ) return result;
1101  if( temp_range.size() != 1 || *( temp_range.begin() ) != recursive2 ) return MB_FAILURE;
1102 
1103  temp_range.clear();
1104  result = MB->get_entities_by_type( recursive2, MBENTITYSET, temp_range );
1105  if( MB_SUCCESS != result ) return result;
1106  if( temp_range.size() != num_sets || !temp_range.all_of_type( MBENTITYSET ) ) return MB_FAILURE;
1107 
1108  temp_range.clear();
1109  result = MB->get_entities_by_handle( recursive1, temp_range );
1110  if( MB_SUCCESS != result ) return result;
1111  if( temp_range.size() != 1 || *( temp_range.begin() ) != recursive2 ) return MB_FAILURE;
1112 
1113  temp_range.clear();
1114  result = MB->get_entities_by_handle( recursive2, temp_range );
1115  if( MB_SUCCESS != result ) return result;
1116  if( temp_range.size() != num_sets || !temp_range.all_of_type( MBENTITYSET ) ) return MB_FAILURE;
1117 
1118  unsigned total = 0;
1119  for( ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++ )
1120  {
1121  total += number_array[ent_type];
1122  temp_range.clear();
1123  result = MB->get_entities_by_type( recursive1, ent_type, temp_range, true );
1124  if( result != MB_SUCCESS ) return result;
1125  if( number_array[ent_type] != temp_range.size() )
1126  {
1127  cout << "Recursive number of entities by type in meshset test is not correct" << endl;
1128  return MB_FAILURE;
1129  }
1130  if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
1131  result = MB->get_number_entities_by_type( recursive1, ent_type, count, true );
1132  if( result != MB_SUCCESS ) return result;
1133  if( number_array[ent_type] != (unsigned)count )
1134  {
1135  cout << "Recursive number of entities by type in meshset test is not correct" << endl;
1136  return MB_FAILURE;
1137  }
1138  if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
1139  }
1140  if( 0 == total )
1141  {
1142  cout << "Invalid test input. No entities!" << endl;
1143  return MB_FAILURE;
1144  }
1145 
1146  for( int dim = 1; dim < 4; ++dim )
1147  {
1148  temp_range.clear();
1149  result = MB->get_entities_by_dimension( recursive1, dim, temp_range, true );
1150  if( MB_SUCCESS != result ) return MB_FAILURE;
1151  if( temp_range.size() != num_dim_array[dim] ) return MB_FAILURE;
1152  if( !temp_range.all_of_dimension( dim ) ) return MB_FAILURE;
1153  result = MB->get_number_entities_by_dimension( recursive1, dim, count, true );
1154  if( MB_SUCCESS != result ) return MB_FAILURE;
1155  if( (unsigned)count != num_dim_array[dim] ) return MB_FAILURE;
1156  }
1157 
1158  temp_range.clear();
1159  result = MB->get_entities_by_handle( recursive1, temp_range, true );
1160  if( result != MB_SUCCESS ) return result;
1161  if( total != temp_range.size() )
1162  {
1163  cout << "Recursive number of entities in meshset test is not correct" << endl;
1164  return MB_FAILURE;
1165  }
1166 
1167  // try circular relation
1168  result = MB->add_entities( recursive2, &recursive1, 1 );
1169  if( MB_SUCCESS != result )
1170  {
1171  std::cout << "Failed to create circular set containment" << std::endl;
1172  return result;
1173  }
1174  temp_range.clear();
1175  result = MB->get_entities_by_handle( recursive1, temp_range, true );
1176  if( result != MB_SUCCESS ) return result;
1177  if( total != temp_range.size() )
1178  {
1179  cout << "Recursive number of entities in meshset test is not correct" << endl;
1180  return MB_FAILURE;
1181  }
1182 
1183  result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 2 );
1184  if( MB_SUCCESS != result ) return result;
1185 
1186  //----------TEST BOOLEAN OPERATIONS----------------//
1187 
1188  EntityHandle temp_ms1, temp_ms2;
1189  result = MB->create_meshset( flags, temp_ms1 );
1190  if( result != MB_SUCCESS ) return result;
1191  result = MB->create_meshset( flags, temp_ms2 );
1192  if( result != MB_SUCCESS ) return result;
1193 
1194  // Subtract
1195  // add all edges and hexes of ms_array[MBHEX] and ms_array[MBEDGE] to temp_ms1
1196  // get all Edge entities
1197  temp_range.clear();
1198  result = MB->get_entities_by_handle( ms_array[MBEDGE], temp_range );
1199  if( result != MB_SUCCESS ) return result;
1200 
1201  // add Edges to ms1
1202  result = MB->add_entities( temp_ms1, temp_range );
1203  if( result != MB_SUCCESS ) return result;
1204 
1205  temp_range.clear();
1206  result = MB->get_entities_by_handle( ms_array[MBHEX], temp_range );
1207  if( result != MB_SUCCESS ) return result;
1208 
1209  // add Hexes to ms1
1210  result = MB->add_entities( temp_ms1, temp_range );
1211  if( result != MB_SUCCESS ) return result;
1212 
1213  // subtract bars meshset out of hex meshset
1214  result = MB->subtract_meshset( temp_ms1, ms_array[MBEDGE] );
1215  if( result != MB_SUCCESS ) return result;
1216 
1217  // Perform the check
1218  temp_range.clear();
1219  result = MB->get_entities_by_handle( temp_ms1, temp_range );
1220  if( result != MB_SUCCESS ) return result;
1221 
1222  if( number_array[MBHEX] != temp_range.size() )
1223  {
1224  cout << "MBset subtraction is bad" << endl;
1225  return MB_FAILURE;
1226  }
1227  // make sure there's nothing but hexes in hex_ms
1228  if( nothing_but_type( temp_range, MBHEX ) != MB_SUCCESS ) return MB_FAILURE;
1229 
1230  result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 4 );
1231  if( MB_SUCCESS != result ) return result;
1232 
1233  //------------Intersect------------
1234  //
1235  // clean out the temp_ms1
1236  MB->clear_meshset( &temp_ms1, 1 );
1237 
1238  temp_range.clear();
1239  // get all quad entities
1240  temp_range.clear();
1241  result = MB->get_entities_by_handle( ms_array[MBQUAD], temp_range );
1242  if( result != MB_SUCCESS ) return result;
1243 
1244  // add tets them to ms1
1245  result = MB->add_entities( temp_ms1, temp_range );
1246  if( result != MB_SUCCESS ) return result;
1247 
1248  // get all tet entities
1249  temp_range.clear();
1250  result = MB->get_entities_by_handle( ms_array[MBTET], temp_range );
1251  if( result != MB_SUCCESS ) return result;
1252 
1253  // add tets them to ms1
1254  result = MB->add_entities( temp_ms1, temp_range );
1255  if( result != MB_SUCCESS ) return result;
1256 
1257  // intersect temp_ms1 (which contains all quads and tets) with tet meshset
1258  // temp_ms1 meshset is altered
1259  result = MB->intersect_meshset( temp_ms1, ms_array[MBTET] );
1260  if( result != MB_SUCCESS ) return result;
1261 
1262  // Perform the check, only tets should be in temp_ms1
1263  temp_range.clear();
1264  result = MB->get_entities_by_handle( temp_ms1, temp_range );
1265  if( result != MB_SUCCESS ) return result;
1266  if( number_array[MBTET] != temp_range.size() )
1267  {
1268  cout << "MBset intersection is bad" << endl;
1269  return MB_FAILURE;
1270  }
1271 
1272  // make sure there's nothing but tet in range
1273  if( nothing_but_type( temp_range, MBTET ) != MB_SUCCESS ) return MB_FAILURE;
1274 
1275  result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 4 );
1276  if( MB_SUCCESS != result ) return result;
1277 
1278  //-------------Unite--------------
1279  // fill temp_ms1 with tets and tris
1280  // get all tris
1281  temp_range.clear();
1282  result = MB->get_entities_by_handle( ms_array[MBTRI], temp_range );
1283  if( result != MB_SUCCESS ) return result;
1284 
1285  // add tets them to ms1
1286  result = MB->add_entities( temp_ms1, temp_range );
1287  if( result != MB_SUCCESS ) return result;
1288 
1289  temp_range.clear();
1290  result = MB->get_entities_by_handle( ms_array[MBTET], temp_range );
1291  if( result != MB_SUCCESS ) return result;
1292 
1293  // add tets them to ms1
1294  result = MB->add_entities( temp_ms1, temp_range );
1295  if( result != MB_SUCCESS ) return result;
1296 
1297  // fill temp_ms2 with tris and hexes
1298  temp_range.clear();
1299  result = MB->get_entities_by_handle( ms_array[MBTRI], temp_range );
1300  if( result != MB_SUCCESS ) return result;
1301 
1302  // add tets them to ms1
1303  result = MB->add_entities( temp_ms2, temp_range );
1304  if( result != MB_SUCCESS ) return result;
1305 
1306  temp_range.clear();
1307  result = MB->get_entities_by_handle( ms_array[MBQUAD], temp_range );
1308  if( result != MB_SUCCESS ) return result;
1309 
1310  // add tets them to ms1
1311  result = MB->add_entities( temp_ms2, temp_range );
1312  if( result != MB_SUCCESS ) return result;
1313 
1314  // temp_ms1 is now filled with tets and tris
1315  // temp_ms2 is now filled with quads and tris
1316  int size1 = 0, size2 = 0;
1317  result = MB->get_number_entities_by_handle( ms_array[MBTRI], size1 );
1318  if( result != MB_SUCCESS ) return result;
1319 
1320  result = MB->intersect_meshset( temp_ms1, temp_ms2 );
1321  if( result != MB_SUCCESS ) return result;
1322  result = MB->get_number_entities_by_handle( temp_ms1, size2 );
1323  if( result != MB_SUCCESS ) return result;
1324 
1325  if( size1 != size2 )
1326  {
1327  return MB_FAILURE;
1328  }
1329 
1330  temp_range.clear();
1331  result = MB->get_entities_by_handle( temp_ms1, temp_range );
1332  if( result != MB_SUCCESS ) return result;
1333 
1334  // make sure there's nothing but tris in temp_range
1335  if( nothing_but_type( temp_range, MBTRI ) != MB_SUCCESS ) return MB_FAILURE;
1336 
1337  result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 4 );
1338  if( MB_SUCCESS != result ) return result;
1339 
1340  //-------------Misc tests--------------
1341  EntityHandle temp_ms3;
1342  result = MB->create_meshset( flags, temp_ms3 );
1343  if( result != MB_SUCCESS ) return result;
1344 
1345  EntityHandle handle_array[] = { 1, 2, 3, 4, 5, 7, 8, 9, 10 };
1346  const int num_handle = sizeof( handle_array ) / sizeof( handle_array[0] );
1347  // add ents to set
1348  result = MB->add_entities( temp_ms3, handle_array, num_handle );
1349  if( result != MB_SUCCESS ) return result;
1350 
1351  // try adding again
1352  result = MB->add_entities( temp_ms3, handle_array, num_handle );
1353  if( result != MB_SUCCESS ) return result;
1354 
1355  int num_ents;
1356  result = MB->get_number_entities_by_handle( temp_ms3, num_ents );
1357  if( result != MB_SUCCESS ) return result;
1358 
1359  int num_expected = ( flags & MESHSET_SET ) ? num_handle : 2 * num_handle;
1360  if( num_ents != num_expected ) return MB_FAILURE;
1361 
1362  return MB_SUCCESS;
1363 }
1364 
1365 static bool compare_lists( std::vector< EntityHandle > vect, const EntityHandle* array, int count, bool ordered = true )
1366 {
1367  if( vect.size() != (size_t)count ) return false;
1368  for( int i = 0; i < count; ++i )
1369  {
1370  if( ordered )
1371  {
1372  if( vect[i] != array[i] ) return false;
1373  }
1374  else if( std::find( vect.begin(), vect.end(), array[i] ) == vect.end() )
1375  return false;
1376  }
1377  return true;
1378 }
1379 
1380 // Test parent/child stuff in meshsets
1382 {
1383  Core moab;
1384  Interface* MB = &moab;
1385 
1386  ErrorCode rval;
1387  std::vector< EntityHandle > list;
1388  Range range;
1389  Range::iterator iter;
1390  int count;
1391 
1392  // create a few mesh sets
1393  const int num_sets = 10;
1394  EntityHandle sets[num_sets];
1395  for( int i = 0; i < num_sets; ++i )
1396  {
1397  rval = MB->create_meshset( i % 2 ? MESHSET_SET : 0, sets[i] );
1398  if( MB_SUCCESS != rval ) return rval;
1399  }
1400 
1401  // test adding child meshsets
1402 
1403  // add first child
1404  rval = MB->add_child_meshset( sets[0], sets[1] );
1405  if( MB_SUCCESS != rval ) return rval;
1406  list.clear();
1407  rval = MB->get_child_meshsets( sets[0], list );
1408  if( MB_SUCCESS != rval ) return rval;
1409  if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
1410  // try to add child again
1411  rval = MB->add_child_meshset( sets[0], sets[1] );
1412  if( MB_SUCCESS != rval ) return rval;
1413  list.clear();
1414  rval = MB->get_child_meshsets( sets[0], list );
1415  if( MB_SUCCESS != rval ) return rval;
1416  if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
1417 
1418  // add second child
1419  rval = MB->add_child_meshset( sets[0], sets[2] );
1420  if( MB_SUCCESS != rval ) return rval;
1421  list.clear();
1422  rval = MB->get_child_meshsets( sets[0], list );
1423  if( MB_SUCCESS != rval ) return rval;
1424  if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
1425  // try adding child again
1426  rval = MB->add_child_meshset( sets[0], sets[1] );
1427  if( MB_SUCCESS != rval ) return rval;
1428  list.clear();
1429  rval = MB->get_child_meshsets( sets[0], list );
1430  if( MB_SUCCESS != rval ) return rval;
1431  if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
1432 
1433  // add third child
1434  rval = MB->add_child_meshset( sets[0], sets[3] );
1435  if( MB_SUCCESS != rval ) return rval;
1436  list.clear();
1437  rval = MB->get_child_meshsets( sets[0], list );
1438  if( MB_SUCCESS != rval ) return rval;
1439  if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
1440  // try adding child again
1441  rval = MB->add_child_meshset( sets[0], sets[1] );
1442  if( MB_SUCCESS != rval ) return rval;
1443  list.clear();
1444  rval = MB->get_child_meshsets( sets[0], list );
1445  if( MB_SUCCESS != rval ) return rval;
1446  if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
1447 
1448  // add fourth child
1449  rval = MB->add_child_meshset( sets[0], sets[4] );
1450  if( MB_SUCCESS != rval ) return rval;
1451  list.clear();
1452  rval = MB->get_child_meshsets( sets[0], list );
1453  if( MB_SUCCESS != rval ) return rval;
1454  if( !compare_lists( list, sets + 1, 4 ) ) return MB_FAILURE;
1455 
1456  // make sure range query returns same result
1457  std::sort( list.begin(), list.end() );
1458  rval = MB->get_child_meshsets( sets[0], range );
1459  iter = range.begin();
1460  for( unsigned i = 0; i < 4; ++i, ++iter )
1461  if( *iter != list[i] ) return MB_FAILURE;
1462 
1463  // remove first child
1464  rval = MB->remove_child_meshset( sets[0], sets[1] );
1465  if( MB_SUCCESS != rval ) return rval;
1466  list.clear();
1467  rval = MB->get_child_meshsets( sets[0], list );
1468  if( MB_SUCCESS != rval ) return rval;
1469  if( !compare_lists( list, sets + 2, 3 ) ) return MB_FAILURE;
1470  // try removing child again
1471  rval = MB->remove_child_meshset( sets[0], sets[1] );
1472  if( MB_SUCCESS != rval ) return rval;
1473 
1474  // remove second child
1475  rval = MB->remove_child_meshset( sets[0], sets[2] );
1476  if( MB_SUCCESS != rval ) return rval;
1477  list.clear();
1478  rval = MB->get_child_meshsets( sets[0], list );
1479  if( !compare_lists( list, sets + 3, 2 ) ) return MB_FAILURE;
1480  // try removing child again
1481  rval = MB->remove_child_meshset( sets[0], sets[2] );
1482  if( MB_SUCCESS != rval ) return rval;
1483 
1484  // remove third child
1485  rval = MB->remove_child_meshset( sets[0], sets[3] );
1486  if( MB_SUCCESS != rval ) return rval;
1487  list.clear();
1488  rval = MB->get_child_meshsets( sets[0], list );
1489  if( list.size() != 1 || list[0] != sets[4] ) return MB_FAILURE;
1490 
1491  // remove fourth child
1492  rval = MB->remove_child_meshset( sets[0], sets[4] );
1493  if( MB_SUCCESS != rval ) return rval;
1494  list.clear();
1495  rval = MB->get_child_meshsets( sets[0], list );
1496  if( !list.empty() ) return MB_FAILURE;
1497 
1498  // test adding parent meshsets
1499 
1500  // add first parent
1501  rval = MB->add_parent_meshset( sets[0], sets[1] );
1502  if( MB_SUCCESS != rval ) return rval;
1503  list.clear();
1504  rval = MB->get_parent_meshsets( sets[0], list );
1505  if( MB_SUCCESS != rval ) return rval;
1506  if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
1507  // try to add parent again
1508  rval = MB->add_parent_meshset( sets[0], sets[1] );
1509  if( MB_SUCCESS != rval ) return rval;
1510  list.clear();
1511  rval = MB->get_parent_meshsets( sets[0], list );
1512  if( MB_SUCCESS != rval ) return rval;
1513  if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
1514 
1515  // add second parent
1516  rval = MB->add_parent_meshset( sets[0], sets[2] );
1517  if( MB_SUCCESS != rval ) return rval;
1518  list.clear();
1519  rval = MB->get_parent_meshsets( sets[0], list );
1520  if( MB_SUCCESS != rval ) return rval;
1521  if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
1522  // try adding parent again
1523  rval = MB->add_parent_meshset( sets[0], sets[1] );
1524  if( MB_SUCCESS != rval ) return rval;
1525  list.clear();
1526  rval = MB->get_parent_meshsets( sets[0], list );
1527  if( MB_SUCCESS != rval ) return rval;
1528  if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
1529 
1530  // add third parent
1531  rval = MB->add_parent_meshset( sets[0], sets[3] );
1532  if( MB_SUCCESS != rval ) return rval;
1533  list.clear();
1534  rval = MB->get_parent_meshsets( sets[0], list );
1535  if( MB_SUCCESS != rval ) return rval;
1536  if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
1537  // try adding parent again
1538  rval = MB->add_parent_meshset( sets[0], sets[1] );
1539  if( MB_SUCCESS != rval ) return rval;
1540  list.clear();
1541  rval = MB->get_parent_meshsets( sets[0], list );
1542  if( MB_SUCCESS != rval ) return rval;
1543  if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
1544 
1545  // add fourth parent
1546  rval = MB->add_parent_meshset( sets[0], sets[4] );
1547  if( MB_SUCCESS != rval ) return rval;
1548  list.clear();
1549  rval = MB->get_parent_meshsets( sets[0], list );
1550  if( MB_SUCCESS != rval ) return rval;
1551  if( !compare_lists( list, sets + 1, 4 ) ) return MB_FAILURE;
1552 
1553  // make sure range query returns same result
1554  std::sort( list.begin(), list.end() );
1555  rval = MB->get_parent_meshsets( sets[0], range );
1556  iter = range.begin();
1557  for( unsigned i = 0; i < 4; ++i, ++iter )
1558  if( *iter != list[i] ) return MB_FAILURE;
1559 
1560  // remove first parent
1561  rval = MB->remove_parent_meshset( sets[0], sets[1] );
1562  if( MB_SUCCESS != rval ) return rval;
1563  list.clear();
1564  rval = MB->get_parent_meshsets( sets[0], list );
1565  if( MB_SUCCESS != rval ) return rval;
1566  if( !compare_lists( list, sets + 2, 3 ) ) return MB_FAILURE;
1567  // try removing parent again
1568  rval = MB->remove_parent_meshset( sets[0], sets[1] );
1569  if( MB_SUCCESS != rval ) return rval;
1570 
1571  // remove second parent
1572  rval = MB->remove_parent_meshset( sets[0], sets[2] );
1573  if( MB_SUCCESS != rval ) return rval;
1574  list.clear();
1575  rval = MB->get_parent_meshsets( sets[0], list );
1576  if( !compare_lists( list, sets + 3, 2 ) ) return MB_FAILURE;
1577  // try removing parent again
1578  rval = MB->remove_parent_meshset( sets[0], sets[2] );
1579  if( MB_SUCCESS != rval ) return rval;
1580 
1581  // remove third parent
1582  rval = MB->remove_parent_meshset( sets[0], sets[3] );
1583  if( MB_SUCCESS != rval ) return rval;
1584  list.clear();
1585  rval = MB->get_parent_meshsets( sets[0], list );
1586  if( list.size() != 1 || list[0] != sets[4] ) return MB_FAILURE;
1587 
1588  // remove fourth parent
1589  rval = MB->remove_parent_meshset( sets[0], sets[4] );
1590  if( MB_SUCCESS != rval ) return rval;
1591  list.clear();
1592  rval = MB->get_parent_meshsets( sets[0], list );
1593  if( !list.empty() ) return MB_FAILURE;
1594 
1595  // setup tests of recursive child query
1596  // 0
1597  // / \ .
1598  // 1 2
1599  // / \ / \ .
1600  // 3 4 5
1601  // \ / \ /
1602  // 6 7
1603  rval = MB->add_child_meshset( sets[0], sets[1] );
1604  if( MB_SUCCESS != rval ) return rval;
1605  rval = MB->add_child_meshset( sets[0], sets[2] );
1606  if( MB_SUCCESS != rval ) return rval;
1607  rval = MB->add_child_meshset( sets[1], sets[3] );
1608  if( MB_SUCCESS != rval ) return rval;
1609  rval = MB->add_child_meshset( sets[1], sets[4] );
1610  if( MB_SUCCESS != rval ) return rval;
1611  rval = MB->add_child_meshset( sets[2], sets[4] );
1612  if( MB_SUCCESS != rval ) return rval;
1613  rval = MB->add_child_meshset( sets[2], sets[5] );
1614  if( MB_SUCCESS != rval ) return rval;
1615  rval = MB->add_child_meshset( sets[3], sets[6] );
1616  if( MB_SUCCESS != rval ) return rval;
1617  rval = MB->add_child_meshset( sets[4], sets[6] );
1618  if( MB_SUCCESS != rval ) return rval;
1619  rval = MB->add_child_meshset( sets[4], sets[7] );
1620  if( MB_SUCCESS != rval ) return rval;
1621  rval = MB->add_child_meshset( sets[5], sets[7] );
1622  if( MB_SUCCESS != rval ) return rval;
1623 
1624  // test query at depth of 1
1625  list.clear();
1626  rval = MB->get_child_meshsets( sets[0], list, 1 );
1627  if( MB_SUCCESS != rval ) return rval;
1628  if( list.size() != 2 || list[0] != sets[1] || list[1] != sets[2] ) return MB_FAILURE;
1629  rval = MB->num_child_meshsets( sets[0], &count, 1 );
1630  if( MB_SUCCESS != rval ) return rval;
1631  if( count != 2 ) return MB_FAILURE;
1632 
1633  // test query at depth of 2
1634  list.clear();
1635  rval = MB->get_child_meshsets( sets[0], list, 2 );
1636  if( MB_SUCCESS != rval ) return rval;
1637  if( !compare_lists( list, sets + 1, 5, false ) ) return MB_FAILURE;
1638  rval = MB->num_child_meshsets( sets[0], &count, 2 );
1639  if( MB_SUCCESS != rval ) return rval;
1640  if( count != 5 ) return MB_FAILURE;
1641 
1642  // test query at depth of 3
1643  list.clear();
1644  rval = MB->get_child_meshsets( sets[0], list, 3 );
1645  if( MB_SUCCESS != rval ) return rval;
1646  if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
1647  rval = MB->num_child_meshsets( sets[0], &count, 3 );
1648  if( MB_SUCCESS != rval ) return rval;
1649  if( count != 7 ) return MB_FAILURE;
1650 
1651  // test query at depth of 4
1652  list.clear();
1653  rval = MB->get_child_meshsets( sets[0], list, 4 );
1654  if( MB_SUCCESS != rval ) return rval;
1655  if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
1656  rval = MB->num_child_meshsets( sets[0], &count, 4 );
1657  if( MB_SUCCESS != rval ) return rval;
1658  if( count != 7 ) return MB_FAILURE;
1659 
1660  // test query at all
1661  list.clear();
1662  rval = MB->get_child_meshsets( sets[0], list, 0 );
1663  if( MB_SUCCESS != rval ) return rval;
1664  if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
1665  rval = MB->num_child_meshsets( sets[0], &count, 0 );
1666  if( MB_SUCCESS != rval ) return rval;
1667  if( count != 7 ) return MB_FAILURE;
1668 
1669  // clean up child links
1670  rval = MB->remove_child_meshset( sets[0], sets[1] );
1671  if( MB_SUCCESS != rval ) return rval;
1672  rval = MB->remove_child_meshset( sets[0], sets[2] );
1673  if( MB_SUCCESS != rval ) return rval;
1674  rval = MB->remove_child_meshset( sets[1], sets[3] );
1675  if( MB_SUCCESS != rval ) return rval;
1676  rval = MB->remove_child_meshset( sets[1], sets[4] );
1677  if( MB_SUCCESS != rval ) return rval;
1678  rval = MB->remove_child_meshset( sets[2], sets[4] );
1679  if( MB_SUCCESS != rval ) return rval;
1680  rval = MB->remove_child_meshset( sets[2], sets[5] );
1681  if( MB_SUCCESS != rval ) return rval;
1682  rval = MB->remove_child_meshset( sets[3], sets[6] );
1683  if( MB_SUCCESS != rval ) return rval;
1684  rval = MB->remove_child_meshset( sets[4], sets[6] );
1685  if( MB_SUCCESS != rval ) return rval;
1686  rval = MB->remove_child_meshset( sets[4], sets[7] );
1687  if( MB_SUCCESS != rval ) return rval;
1688  rval = MB->remove_child_meshset( sets[5], sets[7] );
1689  if( MB_SUCCESS != rval ) return rval;
1690  for( int i = 0; i < 5; ++i )
1691  if( MB_SUCCESS != MB->num_child_meshsets( sets[i], &count ) || count ) return MB_FAILURE;
1692 
1693  // setup tests of recursive parent query
1694  // 6 7
1695  // / \ / \ .
1696  // 3 4 5
1697  // \ / \ /
1698  // 1 2
1699  // \ /
1700  // 0
1701  rval = MB->add_parent_meshset( sets[0], sets[1] );
1702  if( MB_SUCCESS != rval ) return rval;
1703  rval = MB->add_parent_meshset( sets[0], sets[2] );
1704  if( MB_SUCCESS != rval ) return rval;
1705  rval = MB->add_parent_meshset( sets[1], sets[3] );
1706  if( MB_SUCCESS != rval ) return rval;
1707  rval = MB->add_parent_meshset( sets[1], sets[4] );
1708  if( MB_SUCCESS != rval ) return rval;
1709  rval = MB->add_parent_meshset( sets[2], sets[4] );
1710  if( MB_SUCCESS != rval ) return rval;
1711  rval = MB->add_parent_meshset( sets[2], sets[5] );
1712  if( MB_SUCCESS != rval ) return rval;
1713  rval = MB->add_parent_meshset( sets[3], sets[6] );
1714  if( MB_SUCCESS != rval ) return rval;
1715  rval = MB->add_parent_meshset( sets[4], sets[6] );
1716  if( MB_SUCCESS != rval ) return rval;
1717  rval = MB->add_parent_meshset( sets[4], sets[7] );
1718  if( MB_SUCCESS != rval ) return rval;
1719  rval = MB->add_parent_meshset( sets[5], sets[7] );
1720  if( MB_SUCCESS != rval ) return rval;
1721 
1722  // test query at depth of 1
1723  list.clear();
1724  rval = MB->get_parent_meshsets( sets[0], list, 1 );
1725  if( MB_SUCCESS != rval ) return rval;
1726  if( list.size() != 2 || list[0] != sets[1] || list[1] != sets[2] ) return MB_FAILURE;
1727  rval = MB->num_parent_meshsets( sets[0], &count, 1 );
1728  if( MB_SUCCESS != rval ) return rval;
1729  if( count != 2 ) return MB_FAILURE;
1730 
1731  // test query at depth of 2
1732  list.clear();
1733  rval = MB->get_parent_meshsets( sets[0], list, 2 );
1734  if( MB_SUCCESS != rval ) return rval;
1735  if( !compare_lists( list, sets + 1, 5, false ) ) return MB_FAILURE;
1736  rval = MB->num_parent_meshsets( sets[0], &count, 2 );
1737  if( MB_SUCCESS != rval ) return rval;
1738  if( count != 5 ) return MB_FAILURE;
1739 
1740  // test query at depth of 3
1741  list.clear();
1742  rval = MB->get_parent_meshsets( sets[0], list, 3 );
1743  if( MB_SUCCESS != rval ) return rval;
1744  if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
1745  rval = MB->num_parent_meshsets( sets[0], &count, 3 );
1746  if( MB_SUCCESS != rval ) return rval;
1747  if( count != 7 ) return MB_FAILURE;
1748 
1749  // test query at depth of 4
1750  list.clear();
1751  rval = MB->get_parent_meshsets( sets[0], list, 4 );
1752  if( MB_SUCCESS != rval ) return rval;
1753  if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
1754  rval = MB->num_parent_meshsets( sets[0], &count, 4 );
1755  if( MB_SUCCESS != rval ) return rval;
1756  if( count != 7 ) return MB_FAILURE;
1757 
1758  // test query at all
1759  list.clear();
1760  rval = MB->get_parent_meshsets( sets[0], list, 0 );
1761  if( MB_SUCCESS != rval ) return rval;
1762  if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
1763  rval = MB->num_parent_meshsets( sets[0], &count, 0 );
1764  if( MB_SUCCESS != rval ) return rval;
1765  if( count != 7 ) return MB_FAILURE;
1766 
1767  // clean up parent links
1768  rval = MB->remove_parent_meshset( sets[0], sets[1] );
1769  if( MB_SUCCESS != rval ) return rval;
1770  rval = MB->remove_parent_meshset( sets[0], sets[2] );
1771  if( MB_SUCCESS != rval ) return rval;
1772  rval = MB->remove_parent_meshset( sets[1], sets[3] );
1773  if( MB_SUCCESS != rval ) return rval;
1774  rval = MB->remove_parent_meshset( sets[1], sets[4] );
1775  if( MB_SUCCESS != rval ) return rval;
1776  rval = MB->remove_parent_meshset( sets[2], sets[4] );
1777  if( MB_SUCCESS != rval ) return rval;
1778  rval = MB->remove_parent_meshset( sets[2], sets[5] );
1779  if( MB_SUCCESS != rval ) return rval;
1780  rval = MB->remove_parent_meshset( sets[3], sets[6] );
1781  if( MB_SUCCESS != rval ) return rval;
1782  rval = MB->remove_parent_meshset( sets[4], sets[6] );
1783  if( MB_SUCCESS != rval ) return rval;
1784  rval = MB->remove_parent_meshset( sets[4], sets[7] );
1785  if( MB_SUCCESS != rval ) return rval;
1786  rval = MB->remove_parent_meshset( sets[5], sets[7] );
1787  if( MB_SUCCESS != rval ) return rval;
1788  for( int i = 0; i < 5; ++i )
1789  if( MB_SUCCESS != MB->num_parent_meshsets( sets[i], &count ) || count ) return MB_FAILURE;
1790 
1791  // test combined parent/child links
1792 
1793  // test creation
1794  rval = MB->add_parent_child( sets[9], sets[8] );
1795  if( MB_SUCCESS != rval ) return rval;
1796  list.clear();
1797  rval = MB->get_child_meshsets( sets[9], list );
1798  if( MB_SUCCESS != rval ) return rval;
1799  if( list.size() != 1 || list[0] != sets[8] ) return MB_FAILURE;
1800  list.clear();
1801  rval = MB->get_parent_meshsets( sets[8], list );
1802  if( MB_SUCCESS != rval ) return rval;
1803  if( list.size() != 1 || list[0] != sets[9] ) return MB_FAILURE;
1804 
1805  // test deletion of parent/child
1806  rval = MB->add_parent_child( sets[7], sets[9] );
1807  if( MB_SUCCESS != rval ) return rval;
1808  rval = MB->delete_entities( &sets[9], 1 );
1809  if( MB_SUCCESS != rval ) return rval;
1810  list.clear();
1811  rval = MB->get_parent_meshsets( sets[8], list );
1812  if( !list.empty() ) return MB_FAILURE;
1813  list.clear();
1814  rval = MB->get_child_meshsets( sets[7], list );
1815  if( !list.empty() ) return MB_FAILURE;
1816 
1817  // clean up remaining sets
1818  return MB->delete_entities( sets, 9 );
1819 }
1820 
1822 {
1823  return mb_mesh_sets_test( MESHSET_SET );
1824 }
1825 
1827 {
1828  return mb_mesh_sets_test( MESHSET_ORDERED );
1829 }
1830 
1831 // Verify that all query functions *append* to output Range
1833 {
1834  Core moab;
1835  Interface* mb = &moab;
1836  ErrorCode rval = create_some_mesh( mb );
1837  if( MB_SUCCESS != rval ) return rval;
1838 
1839  // get all handles and subdivide into vertex and non-vertex ents
1840  Range all_ents, verts, elems, results;
1841  rval = mb->get_entities_by_handle( 0, all_ents );
1842  if( MB_SUCCESS != rval ) return rval;
1843  Range::iterator ve = all_ents.upper_bound( MBVERTEX );
1844  verts.merge( all_ents.begin(), ve );
1845  elems.merge( ve, all_ents.end() );
1846 
1847  // If we're not testing queries from the root set,
1848  // create a set containing all the vertices
1849  EntityHandle set = 0;
1850  if( flags != -1 )
1851  {
1852  rval = mb->create_meshset( flags, set );
1853  if( MB_SUCCESS != rval ) return rval;
1854  rval = mb->add_entities( set, verts );
1855  if( MB_SUCCESS != rval ) return rval;
1856  }
1857 
1858  // Test get_entities_by_handle. This one doesn't make
1859  // much sense if we're testing the root set, but it doesn't
1860  // hurt to test it anyway.
1861  results = elems;
1862  rval = mb->get_entities_by_handle( set, results );
1863  if( MB_SUCCESS != rval ) return rval;
1864  if( results != all_ents ) return MB_FAILURE;
1865 
1866  // Test get_entities_by_dimension
1867  results = elems;
1868  rval = mb->get_entities_by_dimension( set, 0, results );
1869  if( MB_SUCCESS != rval ) return rval;
1870  if( results != all_ents ) return MB_FAILURE;
1871 
1872  // Test get_entities_by_type
1873  results = elems;
1874  rval = mb->get_entities_by_type( set, MBVERTEX, results );
1875  if( MB_SUCCESS != rval ) return rval;
1876  if( results != all_ents ) return MB_FAILURE;
1877 
1878  // choose a single entity for testing tag queries
1879  EntityHandle entity = verts.front();
1880  Range expected( elems );
1881  expected.insert( entity );
1882 
1883  Tag sparse, dense;
1884  const int zero = 0, one = 1;
1885  const void* vals[] = { &one };
1886 
1887  // Test get_entities_by_type_and_tag w/ sparse tag and no value
1888  rval = mb->tag_get_handle( "mb_mesh_set_appends_sparse", 1, MB_TYPE_INTEGER, sparse, MB_TAG_SPARSE | MB_TAG_EXCL );
1889  if( MB_SUCCESS != rval ) return rval;
1890  rval = mb->tag_set_data( sparse, &entity, 1, &one );
1891  if( MB_SUCCESS != rval ) return rval;
1892  results = elems;
1893  rval =
1894  mb->get_entities_by_type_and_tag( set, TYPE_FROM_HANDLE( entity ), &sparse, 0, 1, results, Interface::UNION );
1895  if( MB_SUCCESS != rval ) return rval;
1896  if( results != expected ) return MB_FAILURE;
1897  // Test again, but specify tag value
1898  results = elems;
1899  rval = mb->get_entities_by_type_and_tag( set, TYPE_FROM_HANDLE( entity ), &sparse, vals, 1, results,
1900  Interface::UNION );
1901  if( MB_SUCCESS != rval ) return rval;
1902  if( results != expected ) return MB_FAILURE;
1903 
1904  // Test get_entities_by_type_and_tag w/ dense tag
1905  rval =
1906  mb->tag_get_handle( "mb_mesh_set_appends_dense", 1, MB_TYPE_INTEGER, dense, MB_TAG_DENSE | MB_TAG_EXCL, &zero );
1907  if( MB_SUCCESS != rval ) return rval;
1908  rval = mb->tag_set_data( dense, &entity, 1, &one );
1909  if( MB_SUCCESS != rval ) return rval;
1910  results = elems;
1911  rval =
1912  mb->get_entities_by_type_and_tag( set, TYPE_FROM_HANDLE( entity ), &dense, vals, 1, results, Interface::UNION );
1913  if( MB_SUCCESS != rval ) return rval;
1914  if( results != expected ) return MB_FAILURE;
1915 
1916  return MB_SUCCESS;
1917 }
1918 
1920 {
1921  return mb_mesh_set_appends( MESHSET_SET );
1922 }
1923 
1925 {
1926  return mb_mesh_set_appends( MESHSET_ORDERED );
1927 }
1928 
1930 {
1931  return mb_mesh_set_appends( -1 );
1932 }
1933 
1935 {
1936  Core moab;
1937  Interface* mb = &moab;
1938  ErrorCode rval;
1939  Range r;
1940  // create 10 vertices to put in set
1941  std::vector< double > coords( 30 );
1942  rval = mb->create_vertices( &coords[0], 10, r );MB_CHK_ERR( rval );
1943  std::vector< EntityHandle > verts( r.size() );
1944  std::copy( r.begin(), r.end(), verts.begin() );
1945  r.clear();
1946  // create a set
1947  EntityHandle set;
1948  rval = mb->create_meshset( MESHSET_SET, set );MB_CHK_ERR( rval );
1949  // put every other vertex in set
1950  for( size_t i = 0; i < 10; i += 2 )
1951  r.insert( verts[i] );
1952  rval = mb->add_entities( set, r );MB_CHK_ERR( rval );
1953  r.clear();
1954  // swap 3 of the vertices
1955  EntityHandle old_ents[3] = { verts[2], verts[4], verts[6] };
1956  EntityHandle new_ents[3] = { verts[1], verts[9], verts[5] };
1957  rval = mb->replace_entities( set, old_ents, new_ents, 3 );MB_CHK_ERR( rval );
1958  // check new set contents
1959  rval = mb->get_entities_by_handle( set, r );MB_CHK_ERR( rval );
1960  Range r2;
1961  r2.insert( verts[0] );
1962  r2.insert( verts[1] );
1963  r2.insert( verts[9] );
1964  r2.insert( verts[5] );
1965  r2.insert( verts[8] );
1966  if( r != r2 )
1967  {
1968  std::cerr << "Range does not contain expected values." << std::endl
1969  << " Expected: " << r2 << std::endl
1970  << " Actual : " << r << std::endl;
1971  return MB_FAILURE;
1972  }
1973 
1974  return MB_SUCCESS;
1975 }
1976 
1978 {
1979  Core moab;
1980  Interface* mb = &moab;
1981  ErrorCode rval;
1982  // create 10 vertices to put in set
1983  Range r;
1984  std::vector< double > coords( 30 );
1985  rval = mb->create_vertices( &coords[0], 10, r );MB_CHK_ERR( rval );
1986  std::vector< EntityHandle > verts( r.size() );
1987  std::copy( r.begin(), r.end(), verts.begin() );
1988  r.clear();
1989  // create a set
1990  EntityHandle set;
1991  rval = mb->create_meshset( MESHSET_ORDERED, set );MB_CHK_ERR( rval );
1992  // put all vertices in set, but add the first one a second time
1993  std::vector< EntityHandle > list( verts );
1994  list.push_back( verts.front() );
1995  rval = mb->add_entities( set, &list[0], list.size() );MB_CHK_ERR( rval );
1996  // swap 3 of the vertices
1997  EntityHandle old_ents[3] = { verts[2], verts[4], verts[6] };
1998  EntityHandle new_ents[3] = { verts[1], verts[9], verts[5] };
1999  rval = mb->replace_entities( set, old_ents, new_ents, 3 );MB_CHK_ERR( rval );
2000  // check new set contents
2001  std::vector< EntityHandle > list2;
2002  rval = mb->get_entities_by_handle( set, list2 );MB_CHK_ERR( rval );
2003  list[2] = verts[1];
2004  list[4] = verts[9];
2005  list[6] = verts[5];
2006  if( list != list2 )
2007  {
2008  std::cerr << "Range does not contain expected values." << std::endl;
2009  std::cerr << " Expected: ";
2010  std::copy( list.begin(), list.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
2011  std::cerr << std::endl << " Actual : ";
2012  std::copy( list2.begin(), list2.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
2013  std::cerr << std::endl;
2014  return MB_FAILURE;
2015  }
2016  // now try replacing a repeated value
2017  rval = mb->replace_entities( set, &verts[0], &verts[3], 1 );MB_CHK_ERR( rval );
2018  list[0] = list[10] = verts[3];
2019  list2.clear();
2020  rval = mb->get_entities_by_handle( set, list2 );MB_CHK_ERR( rval );
2021  if( list != list2 )
2022  {
2023  std::cerr << "Range does not contain expected values." << std::endl;
2024  std::cerr << " Expected: ";
2025  std::copy( list.begin(), list.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
2026  std::cerr << std::endl << " Actual : ";
2027  std::copy( list2.begin(), list2.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
2028  std::cerr << std::endl;
2029  return MB_FAILURE;
2030  }
2031 
2032  return MB_SUCCESS;
2033 }
2034 
2035 /* Test the following changes to a meshset:
2036  set MB-> tracking
2037  tracking MB-> set
2038  unordered MB-> ordered
2039  ordered MB-> unordered
2040 */
2042 {
2043  Core moab;
2044  Interface* mb = &moab;
2045 
2046  ErrorCode rval;
2047  // create 10 vertices to put in set
2048  Range verts;
2049  std::vector< double > coords( 30 );
2050  rval = mb->create_vertices( &coords[0], 10, verts );MB_CHK_ERR( rval );
2051 
2052  // CHECK SET->TRACKING
2053  // create a set and add the verts
2054  EntityHandle set;
2055  rval = mb->create_meshset( MESHSET_SET, set );MB_CHK_ERR( rval );
2056  rval = mb->add_entities( set, verts );MB_CHK_ERR( rval );
2057  // the verts should not be tracking adjacencies
2058  Range adj_sets;
2059  rval = mb->get_adjacencies( verts, 4, false, adj_sets );MB_CHK_ERR( rval );
2060  if( !adj_sets.empty() )
2061  {
2062  std::cerr << "range should be empty but contains:" << std::endl;
2063  rval = mb->list_entities( adj_sets );
2064  return MB_FAILURE;
2065  }
2066  // check to make sure the flags on MESHSET_SET
2067  unsigned int flags;
2068  rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
2069  if( !( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || ( MESHSET_ORDERED & flags ) )
2070  {
2071  std::cerr << "set should be MESHSET_SET only, flags=" << flags << std::endl;
2072  return MB_FAILURE;
2073  }
2074  // change to a tracking set and check flags
2075  rval = mb->set_meshset_options( set, MESHSET_TRACK_OWNER );MB_CHK_ERR( rval );
2076  rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
2077  if( ( MESHSET_SET & flags ) || !( MESHSET_TRACK_OWNER & flags ) || ( MESHSET_ORDERED & flags ) )
2078  {
2079  std::cerr << "set should be MESHSET_TRACK_OWNER only, flags=" << flags << std::endl;
2080  return MB_FAILURE;
2081  }
2082  // check adjacencies
2083  rval = mb->get_adjacencies( verts, 4, false, adj_sets );MB_CHK_ERR( rval );
2084  if( 1 != adj_sets.size() )
2085  {
2086  std::cerr << "range should contain a set, adj_sets.size()=" << adj_sets.size() << std::endl;
2087  rval = mb->list_entities( adj_sets );
2088  return MB_FAILURE;
2089  }
2090 
2091  // CHECK TRACKING->SET
2092  // change to a standard set and check flags
2093  rval = mb->set_meshset_options( set, MESHSET_SET );MB_CHK_ERR( rval );
2094  rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
2095  if( !( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || ( MESHSET_ORDERED & flags ) )
2096  {
2097  std::cerr << "set should be MESHSET_SET only, flags=" << flags << std::endl;
2098  return MB_FAILURE;
2099  }
2100  // the set should no longer be adjacent to the vertices
2101  adj_sets.clear();
2102  rval = mb->get_adjacencies( verts, 4, false, adj_sets );MB_CHK_ERR( rval );
2103  if( !adj_sets.empty() )
2104  {
2105  std::cerr << "range should be empty but contains:" << std::endl;
2106  rval = mb->list_entities( adj_sets );
2107  return MB_FAILURE;
2108  }
2109  // CHECK UNORDERED->ORDERED
2110  // add a duplicate vert
2111  rval = mb->add_entities( set, &verts.front(), 1 );MB_CHK_ERR( rval );
2112  // unordered sets cannot hold duplicates so size shouldn't change
2113  std::vector< EntityHandle > entities;
2114  rval = mb->get_entities_by_handle( set, entities );
2115  if( 10 != entities.size() )
2116  {
2117  std::cerr << "set should not hold duplicate entities" << std::endl;
2118  return MB_FAILURE;
2119  }
2120  // change to an ordered set and check flags
2121  rval = mb->set_meshset_options( set, MESHSET_ORDERED );MB_CHK_ERR( rval );
2122  rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
2123  if( ( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || !( MESHSET_ORDERED & flags ) )
2124  {
2125  std::cerr << "set should be MESHSET_ORDERED only, flags=" << flags << std::endl;
2126  return MB_FAILURE;
2127  }
2128  // swap the order with some entities to that the handles aren't ordered
2129  rval = mb->clear_meshset( &set, 1 );MB_CHK_ERR( rval );
2130  entities.clear();
2131  entities.resize( 2 );
2132  entities[0] = verts[1];
2133  entities[1] = verts[0];
2134  rval = mb->add_entities( set, &entities[0], 2 );MB_CHK_ERR( rval );
2135  // check to ensure the entities keep their order
2136  entities.clear();
2137  rval = mb->get_entities_by_handle( set, entities );
2138  if( verts[0] != entities[1] || verts[1] != entities[0] )
2139  {
2140  std::cerr << "ordered set did not keep its order" << std::endl;
2141  return MB_FAILURE;
2142  }
2143 
2144  // CHECK ORDERED->UNORDERED
2145  // change to an unordered set and check flags
2146  rval = mb->set_meshset_options( set, MESHSET_SET );MB_CHK_ERR( rval );
2147  rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
2148  if( !( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || MESHSET_ORDERED & flags )
2149  {
2150  std::cerr << "set should be MESHSET_SET only, flags=" << flags << std::endl;
2151  return MB_FAILURE;
2152  }
2153  // the entities in the set should now be ordered by handle
2154  entities.clear();
2155  rval = mb->get_entities_by_handle( set, entities );
2156  if( verts[0] != entities[0] || verts[1] != entities[1] )
2157  {
2158  std::cerr << "unordered set is still ordered" << std::endl;
2159  return MB_FAILURE;
2160  }
2161  return MB_SUCCESS;
2162 }
2163 
2164 #ifdef MOAB_HAVE_NETCDF
2165 // number of entities of type MBVERTEX, MBEDGE, MBDTri, MBQUAD, MBTET, and MBHEX
2166 // in mbtest1.g (all other values are 0.
2167 static const EntityType types[] = { MBVERTEX, MBEDGE, MBTRI, MBQUAD, MBTET, MBHEX };
2168 const int num_types = sizeof( types ) / sizeof( types[0] );
2169 static const unsigned int num_entities[num_types + 1] = { 47, 12, 18, 8, 22, 8, 0 };
2170 
2171 ErrorCode mb_delete_mesh_test()
2172 {
2173  Core moab;
2174  Interface* gMB = &moab;
2176  if( MB_SUCCESS != error ) return error;
2177 
2178  // Lets also test the global MB pointer (gMB) here.
2179  error = gMB->delete_mesh();
2180  if( error != MB_SUCCESS ) return error;
2181 
2182  // load the mesh again
2183  error = load_file_one( gMB );
2184  if( error != MB_SUCCESS ) return error;
2185 
2186  // step through each element type
2187  for( EntityType type = MBVERTEX; type != MBENTITYSET; type++ )
2188  {
2189  // There should be entities
2190  Range entities;
2191  error = gMB->get_entities_by_type( 0, type, entities );
2192  if( error != MB_SUCCESS ) return error;
2193 
2194  size_t idx = std::find( types, types + num_types, type ) - types;
2195  if( entities.size() != num_entities[idx] ) return MB_FAILURE;
2196  }
2197 
2198  return MB_SUCCESS;
2199 }
2200 
2201 ErrorCode mb_mesh_set_tracking_test()
2202 {
2203  Core moab;
2204  Interface* MB = &moab;
2205 
2206  // read in a file so you have some data in the database
2207 
2208  ErrorCode error = load_file_one( MB );
2209  if( error != MB_SUCCESS ) return error;
2210 
2211  EntityHandle ms1, ms2, ms3;
2212 
2213  // create meshsets
2214  ErrorCode result = MB->create_meshset( MESHSET_TRACK_OWNER | MESHSET_ORDERED, ms1 );
2215  if( result != MB_SUCCESS ) return result;
2216  result = MB->create_meshset( MESHSET_SET | MESHSET_TRACK_OWNER, ms2 );
2217  if( result != MB_SUCCESS ) return result;
2218  result = MB->create_meshset( MESHSET_SET | MESHSET_TRACK_OWNER, ms3 );
2219  if( result != MB_SUCCESS ) return result;
2220 
2221  // get all hexes
2222  Range hexes;
2223  result = MB->get_entities_by_type( 0, MBHEX, hexes );
2224  if( result != MB_SUCCESS ) return result;
2225 
2226  // get all tris
2227  Range tris;
2228  result = MB->get_entities_by_type( 0, MBTRI, tris );
2229  if( result != MB_SUCCESS ) return result;
2230 
2231  // get all tets
2232  Range temp_range;
2233  result = MB->get_entities_by_type( 0, MBTET, temp_range );
2234  if( result != MB_SUCCESS ) return result;
2235 
2236  // copy all the tets from the range into a vector 'tets'
2237  std::vector< EntityHandle > tets( temp_range.size() );
2238  std::copy( temp_range.begin(), temp_range.end(), tets.begin() );
2239 
2240  // Quick check on 'get_entities_by_dimension()'
2241  Range dim_3_range;
2242  result = MB->get_entities_by_dimension( 0, 3, dim_3_range );
2243  if( result != MB_SUCCESS ) return result;
2244 
2245  // hexes and tets should be only dimension 3 entities
2246  if( hexes.size() + tets.size() != dim_3_range.size() ) return MB_FAILURE;
2247 
2248  // put all hexes in ms1, ms2, ms3
2249  result = MB->add_entities( ms1, hexes ); // add ents in a range
2250  if( result != MB_SUCCESS ) return result;
2251  // to ordered meshset
2252 
2253  result = MB->add_entities( ms2, hexes ); // add ents in a range
2254  if( result != MB_SUCCESS ) return result;
2255  // to unordered meshset
2256 
2257  result = MB->add_entities( ms3, hexes );
2258  if( result != MB_SUCCESS ) return result;
2259 
2260  // put all tets in ms1, ms2
2261  if( MB->add_entities( ms1, &tets[0], tets.size() ) != MB_SUCCESS ) // add ents in a vector
2262  return MB_FAILURE; // to ordered meshset
2263 
2264  if( MB->add_entities( ms2, &tets[0], tets.size() ) != MB_SUCCESS ) // add ents in a vector
2265  return MB_FAILURE; // to unordered meshset
2266 
2267  // put all tris in ms1
2268  result = MB->add_entities( ms1, tris );
2269  if( result != MB_SUCCESS ) return result;
2270 
2271  Range::iterator iter;
2272  iter = tris.begin();
2273 
2274  std::vector< EntityHandle > temp_vec;
2275 
2276  // ask a tri which meshsets it is in
2277  result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
2278  if( result != MB_SUCCESS ) return result;
2279 
2280  // cout<<"tris temp_vec.size() = "<<temp_vec.size()<<endl;
2281  if( temp_vec.size() != 2 ) return MB_FAILURE;
2282 
2283  // ask a tet which meshsets it is in
2284  temp_vec.clear();
2285  std::vector< EntityHandle >::iterator vec_iter = tets.begin();
2286  result = MB->get_adjacencies( &( *vec_iter ), 1, 4, false, temp_vec );
2287  if( result != MB_SUCCESS ) return result;
2288 
2289  // cout<<"tet temp_vec.size() = "<<temp_vec.size()<<endl;
2290  if( temp_vec.size() != 3 ) return MB_FAILURE;
2291 
2292  // ask a hex which meshsets it is in
2293  temp_vec.clear();
2294  iter = hexes.begin();
2295  result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
2296  if( result != MB_SUCCESS ) return result;
2297 
2298  // should be in 4 temp_vec
2299  if( temp_vec.size() != 4 ) return MB_FAILURE;
2300 
2301  // take this hex out of the ms1, ms2, ms3
2302  if( MB->remove_entities( ms1, &( *iter ), 1 ) != MB_SUCCESS ) // remove ents in a vector
2303  return MB_FAILURE; // from ordered meshset
2304 
2305  if( MB->remove_entities( ms2, &( *iter ), 1 ) != MB_SUCCESS ) // remove ents in a vector
2306  return MB_FAILURE; // from unordered meshset
2307 
2308  temp_range.clear();
2309  temp_range.insert( *iter );
2310  if( MB->remove_entities( ms3, temp_range ) != MB_SUCCESS ) // remove ents in a range
2311  return MB_FAILURE; // from unordered meshset
2312 
2313  // ask the hex how many meshsets it is in
2314  temp_vec.clear();
2315  result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
2316  if( result != MB_SUCCESS ) return result;
2317  if( temp_vec.size() != 1 ) return MB_FAILURE;
2318 
2319  // add the hex back into ms1
2320  result = MB->add_entities( ms1, temp_range );
2321  if( result != MB_SUCCESS ) return result;
2322 
2323  // ask the hex how many meshsets it is in
2324  temp_vec.clear();
2325  result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
2326  if( result != MB_SUCCESS ) return result;
2327  if( temp_vec.size() != 2 ) return MB_FAILURE;
2328 
2329  temp_range.clear();
2330  temp_range.insert( *iter );
2331  if( MB->remove_entities( ms1, temp_range ) != MB_SUCCESS ) // remove ents in a range
2332  return MB_FAILURE; // from an ordered meshset
2333 
2334  // ask the hex how many meshsets it is in
2335  temp_vec.clear();
2336  result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
2337  if( result != MB_SUCCESS ) return result;
2338  if( temp_vec.size() != 1 ) return MB_FAILURE;
2339 
2340  // Deleting a meshset
2341 
2342  iter = tris.begin();
2343  temp_vec.clear();
2344  // ask a tri which meshsets it is in
2345  result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
2346  if( result != MB_SUCCESS ) return result;
2347 
2348  if( temp_vec.size() != 2 ) return MB_FAILURE;
2349 
2350  // Try deleting a meshset
2351  result = MB->delete_entities( &ms1, 1 );
2352  if( result != MB_SUCCESS ) return result;
2353 
2354  temp_vec.clear();
2355  // Query tri again for meshsets it's in
2356  result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
2357  if( result != MB_SUCCESS ) return result;
2358 
2359  if( temp_vec.size() != 1 ) return MB_FAILURE;
2360 
2361  // Delete an entitiy from ms2....make sure it's removed out of ms2
2362  int num_before = 0;
2363  MB->get_number_entities_by_handle( ms2, num_before );
2364  vec_iter = tets.begin();
2365  result = MB->delete_entities( &( *vec_iter ), 1 );
2366  if( result != MB_SUCCESS ) return result;
2367 
2368  int num_after = 0;
2369  MB->get_number_entities_by_handle( ms2, num_after );
2370  if( num_before != num_after + 1 ) return MB_FAILURE;
2371 
2372  return MB_SUCCESS;
2373 }
2374 #endif
2375 
2376 // Compare internal representation of contents for a list (MESHSET_ORDERED)
2377 // set to expected contents. Assumes expected contents are correctly
2378 // ordered.
2380  int num_expected,
2381  const EntityHandle* contents,
2382  int length )
2383 {
2384  bool okay = true;
2385  for( int i = 0; i < std::min( num_expected, length ); ++i )
2386  {
2387  if( expected[i] != contents[i] )
2388  {
2389  std::cerr << "List set contents differ at index " << i << ": expected " << expected[i] << " but got "
2390  << contents[i] << std::endl;
2391  okay = false;
2392  }
2393  }
2394  if( num_expected > length )
2395  {
2396  std::cerr << "List set is missing " << num_expected - length << "handles" << std::endl;
2397  okay = false;
2398  }
2399  else if( length > num_expected )
2400  {
2401  std::cerr << "List set has " << num_expected - length << " extra handles" << std::endl;
2402  okay = false;
2403  }
2404 
2405  if( okay ) return MB_SUCCESS;
2406 
2407  std::cerr << "Expected contents: ";
2408  if( !num_expected )
2409  std::cerr << "(empty)";
2410  else
2411  std::cerr << expected[0];
2412  for( int i = 1; i < num_expected; ++i )
2413  std::cerr << ", " << expected[i];
2414  std::cerr << std::endl;
2415 
2416  std::cerr << "Actual contents: ";
2417  if( !length )
2418  std::cerr << "(empty)";
2419  else
2420  std::cerr << contents[0];
2421  for( int i = 1; i < length; ++i )
2422  std::cerr << ", " << contents[i];
2423  std::cerr << std::endl;
2424 
2425  return MB_FAILURE;
2426 }
2427 
2428 // Compare internal representation of contents for a ranged (MESHSET_SET)
2429 // set to expected contents. Assumes expected contents are correctly
2430 // ordered.
2432  int num_expected,
2433  const EntityHandle* contents,
2434  int length )
2435 {
2436  if( length % 2 )
2437  {
2438  std::cerr << "Range set is corrupt. Odd number of handles in content list" << std::endl;
2439  std::cerr << "Actual contents: " << contents[0];
2440  for( int i = 1; i < length; ++i )
2441  std::cerr << ", " << contents[i];
2442  std::cerr << std::endl;
2443  return MB_FAILURE;
2444  }
2445  bool okay = true;
2446  // check that all range pairs are valid (first handle less than or
2447  // equal to second)
2448  for( int i = 0; i < length; i += 2 )
2449  {
2450  if( contents[i] > contents[i + 1] )
2451  {
2452  std::cerr << "Range set has invalid range pair at index " << i << ": [" << contents[i] << ','
2453  << contents[i + 1] << ']' << std::endl;
2454  okay = false;
2455  }
2456  }
2457  // check that all range pairs are sorted and non-overlapping
2458  // (start of a range must be greater than end of previous range)
2459  for( int i = 2; i < length; i += 2 )
2460  {
2461  if( contents[i] < contents[i - 1] )
2462  {
2463  std::cerr << "Range set has incorrectly ordered ranges at index " << i << ": [...," << contents[i - 1]
2464  << "], [" << contents[i] << ",...]" << std::endl;
2465  okay = false;
2466  }
2467  if( contents[i] == contents[i - 1] + 1 )
2468  {
2469  std::cerr << "Range set has pairs that should have been merged at index " << i << ": [...,"
2470  << contents[i - 1] << "], [" << contents[i] << ",...]" << std::endl;
2471  okay = false;
2472  }
2473  }
2474  if( !okay )
2475  {
2476  std::cerr << "Actual contents: ";
2477  if( !length )
2478  std::cerr << "(empty)";
2479  else
2480  std::cerr << '[' << contents[0] << ',' << contents[1] << ']';
2481  for( int i = 2; i < length; i += 2 )
2482  std::cerr << ", [" << contents[i] << ',' << contents[i + 1] << ']';
2483  std::cerr << std::endl;
2484  return MB_FAILURE;
2485  }
2486 
2487  int j = 0;
2488  for( int i = 0; i < length; i += 2 )
2489  {
2490  for( ; j < num_expected && expected[j] < contents[i]; ++j )
2491  {
2492  std::cerr << "Range set missing expected handle: " << expected[j] << std::endl;
2493  okay = false;
2494  }
2495  int k = j;
2496  while( k < num_expected && expected[k] <= contents[i + 1] )
2497  ++k;
2498  if( (EntityHandle)( k - j ) <= ( contents[i + 1] - contents[i] ) )
2499  {
2500  std::cerr << "Handle range [" << contents[i] << ',' << contents[i + 1]
2501  << "] contains unexpected handles. Expected handles: ";
2502  if( k == j )
2503  std::cerr << "(none)" << std::endl;
2504  else
2505  {
2506  std::cerr << expected[j];
2507  for( ++j; j < k; ++j )
2508  std::cerr << ", " << expected[j];
2509  std::cerr << std::endl;
2510  }
2511  okay = false;
2512  }
2513  j = k;
2514  }
2515 
2516  if( okay ) return MB_SUCCESS;
2517 
2518  std::cerr << "Expected contents: ";
2519  if( !num_expected )
2520  std::cerr << "(empty)";
2521  else
2522  std::cerr << expected[0];
2523  for( int i = 1; i < num_expected; ++i )
2524  std::cerr << ", " << expected[i];
2525  std::cerr << std::endl;
2526 
2527  std::cerr << "Actual contents: ";
2528  if( !length )
2529  std::cerr << "(empty)";
2530  else
2531  std::cerr << '[' << contents[0] << ',' << contents[1] << ']';
2532  for( int i = 2; i < length; i += 2 )
2533  std::cerr << ", [" << contents[i] << ',' << contents[i + 1] << ']';
2534  std::cerr << std::endl;
2535 
2536  return MB_FAILURE;
2537 }
2538 
2539 // Check the internal representation of a meshset
2540 // to verify that it is correct.
2542  EntityHandle set,
2543  const EntityHandle* expected,
2544  int num_expected )
2545 {
2546  ErrorCode rval;
2547  WriteUtilIface* tool = 0;
2548  rval = mb.query_interface( tool );MB_CHK_ERR( rval );
2549 
2550  const EntityHandle* contents;
2551  int length;
2552  unsigned char flags;
2553  rval = tool->get_entity_list_pointers( &set, 1, &contents, WriteUtilIface::CONTENTS, &length, &flags );MB_CHK_ERR( rval );
2554  ErrorCode rval1 = mb.release_interface( tool );MB_CHK_ERR( rval1 );
2555 
2556  if( flags & MESHSET_ORDERED )
2557  rval = check_list_meshset_internal( expected, num_expected, contents, length );
2558  else
2559  rval = check_ranged_meshset_internal( expected, num_expected, contents, length );MB_CHK_ERR( rval );
2560  return MB_SUCCESS;
2561 }
2562 
2564 {
2565  Core core;
2566  Interface& mb = core;
2567  EntityHandle set;
2568  ErrorCode rval = mb.create_meshset( MESHSET_SET, set );MB_CHK_ERR( rval );
2569 
2570  EntityHandle list1[] = { 10, 16, 18, 20, 24, 27 };
2571  size_t len1 = sizeof( list1 ) / sizeof( list1[0] );
2572  EntityHandle list2[] = { 10, 16, 17, 18, 19, 20, 24, 27 };
2573  size_t len2 = sizeof( list2 ) / sizeof( list2[0] );
2574  rval = mb.add_entities( set, list1, len1 );MB_CHK_ERR( rval );
2575  rval = check_meshset_internal( mb, set, list1, len1 );MB_CHK_ERR( rval );
2576  rval = mb.add_entities( set, list2, len2 );MB_CHK_ERR( rval );
2577  EntityHandle exp12[] = { 10, 16, 17, 18, 19, 20, 24, 27 };
2578  size_t len12 = sizeof( exp12 ) / sizeof( exp12[0] );
2579  rval = check_meshset_internal( mb, set, exp12, len12 );MB_CHK_ERR( rval );
2580 
2581  EntityHandle list3[] = { 15, 16, 18, 20, 21, 24, 28 };
2582  size_t len3 = sizeof( list3 ) / sizeof( list3[0] );
2583  rval = mb.remove_entities( set, list3, len3 );MB_CHK_ERR( rval );
2584  EntityHandle exp123[] = { 10, 17, 19, 27 };
2585  size_t len123 = sizeof( exp123 ) / sizeof( exp123[0] );
2586  rval = check_meshset_internal( mb, set, exp123, len123 );MB_CHK_ERR( rval );
2587 
2588  EntityHandle list4[] = { 18, 10, 11, 12, 13, 14, 15, 16 };
2589  size_t len4 = sizeof( list4 ) / sizeof( list4[0] );
2590  rval = mb.add_entities( set, list4, len4 );MB_CHK_ERR( rval );
2591  EntityHandle exp14[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 27 };
2592  size_t len14 = sizeof( exp14 ) / sizeof( exp14[0] );
2593  rval = check_meshset_internal( mb, set, exp14, len14 );MB_CHK_ERR( rval );
2594 
2595  EntityHandle list5[] = { 9, 10, 12, 13, 14, 15, 19, 20 };
2596  rval = mb.remove_entities( set, list5, sizeof( list5 ) / sizeof( list5[0] ) );MB_CHK_ERR( rval );
2597  EntityHandle exp5[] = { 11, 16, 17, 18, 27 };
2598  rval = check_meshset_internal( mb, set, exp5, sizeof( exp5 ) / sizeof( exp5[0] ) );MB_CHK_ERR( rval );
2599 
2600  EntityHandle list6[] = { 9, 10, 15, 16, 18, 19, 28 };
2601  rval = mb.add_entities( set, list6, sizeof( list6 ) / sizeof( list6[0] ) );MB_CHK_ERR( rval );
2602  EntityHandle exp6[] = { 9, 10, 11, 15, 16, 17, 18, 19, 27, 28 };
2603  rval = check_meshset_internal( mb, set, exp6, sizeof( exp6 ) / sizeof( exp6[0] ) );MB_CHK_ERR( rval );
2604 
2605  EntityHandle list7[] = { 13, 19, 27, 28 };
2606  rval = mb.add_entities( set, list7, sizeof( list7 ) / sizeof( list7[0] ) );MB_CHK_ERR( rval );
2607  EntityHandle exp7[] = { 9, 10, 11, 13, 15, 16, 17, 18, 19, 27, 28 };
2608  rval = check_meshset_internal( mb, set, exp7, sizeof( exp7 ) / sizeof( exp7[0] ) );MB_CHK_ERR( rval );
2609 
2610  EntityHandle list8[] = { 12, 14, 33 };
2611  rval = mb.add_entities( set, list8, sizeof( list8 ) / sizeof( list8[0] ) );MB_CHK_ERR( rval );
2612  EntityHandle exp8[] = { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 27, 28, 33 };
2613  rval = check_meshset_internal( mb, set, exp8, sizeof( exp8 ) / sizeof( exp8[0] ) );MB_CHK_ERR( rval );
2614 
2615  EntityHandle list9[] = { 29, 30, 31, 32, 34 };
2616  rval = mb.remove_entities( set, list9, sizeof( list9 ) / sizeof( list9[0] ) );MB_CHK_ERR( rval );
2617  rval = check_meshset_internal( mb, set, exp8, sizeof( exp8 ) / sizeof( exp8[0] ) );MB_CHK_ERR( rval );
2618 
2619  EntityHandle list10[] = { 9, 11, 13, 17, 18, 19, 28, 33, 100 };
2620  rval = mb.remove_entities( set, list10, sizeof( list10 ) / sizeof( list10[0] ) );MB_CHK_ERR( rval );
2621  EntityHandle exp10[] = { 10, 12, 14, 15, 16, 27 };
2622  rval = check_meshset_internal( mb, set, exp10, sizeof( exp10 ) / sizeof( exp10[0] ) );MB_CHK_ERR( rval );
2623 
2624  EntityHandle list11[] = { 11, 12, 13, 14, 27, 28 };
2625  rval = mb.remove_entities( set, list11, sizeof( list11 ) / sizeof( list11[0] ) );MB_CHK_ERR( rval );
2626  EntityHandle exp11[] = { 10, 15, 16 };
2627  rval = check_meshset_internal( mb, set, exp11, sizeof( exp11 ) / sizeof( exp11[0] ) );MB_CHK_ERR( rval );
2628 
2629  EntityHandle list12[] = { 1, 10, 15, 16 };
2630  rval = mb.remove_entities( set, list12, sizeof( list12 ) / sizeof( list12[0] ) );MB_CHK_ERR( rval );
2631  rval = check_meshset_internal( mb, set, 0, 0 );MB_CHK_ERR( rval );
2632 
2633  return MB_SUCCESS;
2634 }
2635 
2637 {
2638  Core moab;
2639  Interface* MB = &moab;
2640 
2641  double nodes_array[7][3];
2642 
2643  nodes_array[0][0] = 0;
2644  nodes_array[0][1] = 0;
2645  nodes_array[0][2] = 0;
2646  nodes_array[1][0] = 2;
2647  nodes_array[1][1] = 0;
2648  nodes_array[1][2] = 0;
2649  nodes_array[2][0] = 1;
2650  nodes_array[2][1] = 2;
2651  nodes_array[2][2] = 1;
2652  nodes_array[3][0] = 1;
2653  nodes_array[3][1] = 0;
2654  nodes_array[3][2] = 0;
2655  nodes_array[4][0] = 1.5;
2656  nodes_array[4][1] = 0.5;
2657  nodes_array[4][2] = 0.5;
2658  nodes_array[5][0] = 0.5;
2659  nodes_array[5][1] = 0.5;
2660  nodes_array[5][2] = 0.5;
2661  nodes_array[6][0] = 1;
2662  nodes_array[6][1] = 1;
2663  nodes_array[6][2] = 0.5;
2664 
2665  // create the nodes
2666  std::vector< EntityHandle > connectivity( 8 );
2667  EntityHandle node_handle;
2668  int i;
2669  for( i = 0; i < 7; i++ )
2670  {
2671  if( MB->create_vertex( nodes_array[i], node_handle ) != MB_SUCCESS ) return MB_FAILURE;
2672  connectivity[i] = node_handle;
2673  }
2674 
2675  // create the higher order tri
2676  EntityHandle tri_handle;
2677  ErrorCode result = MB->create_element( MBTRI, &connectivity[0], 6, tri_handle );
2678  if( result != MB_SUCCESS ) return result;
2679 
2680  // create the higher order tri
2681  std::vector< EntityHandle > other_conn( 3 );
2682 
2683  double other_nodes[3][3];
2684  other_nodes[0][0] = 1.999;
2685  other_nodes[0][1] = 1.999;
2686  other_nodes[0][2] = 1.999;
2687  other_nodes[1][0] = 2.999;
2688  other_nodes[1][1] = 2.999;
2689  other_nodes[1][2] = 2.999;
2690  other_nodes[2][0] = 3.999;
2691  other_nodes[2][1] = 3.999;
2692  other_nodes[2][2] = 3.999;
2693 
2694  for( i = 0; i < 3; i++ )
2695  {
2696  if( MB->create_vertex( other_nodes[i], node_handle ) != MB_SUCCESS ) return MB_FAILURE;
2697  other_conn[i] = node_handle;
2698  }
2699 
2700  EntityHandle other_tri_handle;
2701  result = MB->create_element( MBTRI, &other_conn[0], 3, other_tri_handle );
2702  if( result != MB_SUCCESS ) return result;
2703 
2704  // get the connectivity now
2705  std::vector< EntityHandle > retrieved_conn;
2706 
2707  result = MB->get_connectivity( &tri_handle, 1, retrieved_conn );
2708  if( result != MB_SUCCESS ) return result;
2709 
2710  unsigned int k;
2711  for( k = 0; k < retrieved_conn.size(); k++ )
2712  if( connectivity[k] != retrieved_conn[k] ) return MB_FAILURE;
2713 
2714  result = MB->get_connectivity( &other_tri_handle, 1, retrieved_conn );
2715  if( result != MB_SUCCESS ) return result;
2716 
2717  for( k = 0; k < other_conn.size(); k++ )
2718  if( other_conn[k] != retrieved_conn[k] ) return MB_FAILURE;
2719 
2720  // now let's just try getting the topological connectivity (the 3 corner vertices)
2721  std::vector< EntityHandle > topo_conn;
2722  result = MB->get_connectivity( &other_tri_handle, 1, topo_conn, true );
2723  if( result != MB_SUCCESS ) return result;
2724 
2725  if( topo_conn.size() != 3 ) return MB_FAILURE;
2726 
2727  for( k = 0; k < 3; k++ )
2728  if( topo_conn[k] != retrieved_conn[k] ) return MB_FAILURE;
2729 
2730  // short check to make sure that Core::handle_from_id() works
2731  unsigned long handle_id = MB->id_from_handle( node_handle );
2732 
2733  EntityHandle test_handle;
2734  result = MB->handle_from_id( MBVERTEX, handle_id, test_handle );
2735  if( result != MB_SUCCESS ) return result;
2736 
2737  if( test_handle != node_handle ) return MB_FAILURE;
2738 
2739  handle_id = MB->id_from_handle( tri_handle );
2740 
2741  result = MB->handle_from_id( MBTRI, handle_id, test_handle );
2742  if( result != MB_SUCCESS ) return result;
2743 
2744  if( test_handle != tri_handle ) return MB_FAILURE;
2745 
2746  // make up some bogus id
2747  handle_id = 2140824;
2748 
2749  result = MB->handle_from_id( MBTRI, handle_id, test_handle );
2750  if( result != MB_ENTITY_NOT_FOUND ) return MB_FAILURE;
2751 
2752  result = MB->handle_from_id( MBVERTEX, handle_id, test_handle );
2753  if( result != MB_ENTITY_NOT_FOUND ) return MB_FAILURE;
2754 
2755  return MB_SUCCESS;
2756 }
2757 
2759 {
2760  Core moab;
2761  Interface* MB = &moab;
2762  ErrorCode success = create_some_mesh( MB );
2763  if( MB_SUCCESS != success ) return success;
2764 
2765  Tag bit_tag;
2766  Range entities;
2768 
2769  if( MB->tag_get_handle( "bit on vertex", 3, MB_TYPE_BIT, bit_tag, MB_TAG_CREAT ) != MB_SUCCESS )
2770  {
2771  cout << "couldn't create bit tag" << endl;
2772  return MB_FAILURE;
2773  }
2774 
2775  Range::iterator iter;
2776  unsigned char bits;
2777  for( iter = entities.begin(); iter != entities.end(); ++iter )
2778  {
2779  // tag each vertex with the low 3 bits of the entity handle
2780  bits = ( ( *iter ) & 0x7 );
2781  success = MB->tag_set_data( bit_tag, &( *iter ), 1, &bits );
2782  if( success != MB_SUCCESS ) return MB_FAILURE;
2783  }
2784 
2785  bits = 0;
2786  for( iter = entities.begin(); iter != entities.end(); ++iter )
2787  {
2788  // tag each vertex with the low 3 bits of the entity handle
2789  success = MB->tag_get_data( bit_tag, &( *iter ), 1, &bits );
2790  if( success != MB_SUCCESS ) return MB_FAILURE;
2791 
2792  if( bits != ( ( *iter ) & 0x7 ) ) return MB_FAILURE;
2793  }
2794 
2795  // test range-based query for all vertices
2796  std::vector< unsigned char > data( entities.size() );
2797  success = MB->tag_get_data( bit_tag, entities, &data[0] );
2798  if( MB_SUCCESS != success ) return success;
2799  std::vector< unsigned char >::iterator i = data.begin();
2800  for( iter = entities.begin(); iter != entities.end(); ++iter, ++i )
2801  if( *i != ( ( *iter ) & 0x7 ) ) return MB_FAILURE;
2802 
2803  // test vector-based query for all vertices
2804  std::vector< EntityHandle > verts( entities.begin(), entities.end() );
2805  success = MB->tag_get_data( bit_tag, &verts[0], verts.size(), &data[0] );
2806  if( MB_SUCCESS != success ) return success;
2807  i = data.begin();
2808  for( iter = entities.begin(); iter != entities.end(); ++iter, ++i )
2809  if( *i != ( ( *iter ) & 0x7 ) ) return MB_FAILURE;
2810 
2811  // test default value
2812  const unsigned char default_bits = '\005'; // 0000 0101
2813  Tag tag2;
2814  success = MB->tag_get_handle( "bit with default", 4, MB_TYPE_BIT, tag2, MB_TAG_CREAT, &default_bits );
2815  if( MB_SUCCESS != success )
2816  {
2817  cout << "Failed to create bit tag with default value" << std::endl;
2818  return success;
2819  }
2820 
2821  // set value to zero on a single vertex
2822  bits = 0;
2823  EntityHandle zh = verts[verts.size() / 2];
2824  success = MB->tag_set_data( tag2, &zh, 1, &bits );
2825  if( MB_SUCCESS != success ) return success;
2826 
2827  // get tag values for all entities
2828  data.clear();
2829  data.resize( verts.size(), 0x7A ); // initialize with 0111 1010
2830  success = MB->tag_get_data( tag2, entities, &data[0] );
2831  if( MB_SUCCESS != success ) return success;
2832 
2833  // check values
2834  i = data.begin();
2835  for( iter = entities.begin(); iter != entities.end(); ++iter, ++i )
2836  if( *iter == zh && *i ) // the one we set to zero
2837  return MB_FAILURE;
2838  else if( *iter != zh && *i != default_bits )
2839  return MB_FAILURE;
2840 
2841  return MB_SUCCESS;
2842 }
2843 
2844 #ifdef MOAB_HAVE_NETCDF
2845 ErrorCode mb_tags_test()
2846 {
2847  Core moab;
2848  Interface* MB = &moab;
2849  ErrorCode result = load_file_one( MB );
2850  if( MB_SUCCESS != result ) return result;
2851 
2852  Tag stale_bits, stale_dense, stale_sparse;
2853  result = MB->tag_get_handle( "stale data", 5, MB_TYPE_BIT, stale_bits, MB_TAG_CREAT );
2854  if( MB_SUCCESS != result ) return result;
2855 
2856  int def_data = 9;
2857  result = MB->tag_get_handle( "dense stale_data", 1, MB_TYPE_INTEGER, stale_dense, MB_TAG_DENSE | MB_TAG_EXCL,
2858  &def_data );
2859  if( MB_SUCCESS != result ) return result;
2860  result = MB->tag_get_handle( "sparse stale data", 1, MB_TYPE_INTEGER, stale_sparse, MB_TAG_SPARSE | MB_TAG_EXCL );
2861  if( MB_SUCCESS != result ) return result;
2862 
2863  double coords[3] = { 0, 0, 0 };
2864  EntityHandle stale_handle1, stale_handle2;
2865  result = MB->create_vertex( coords, stale_handle1 );
2866  if( MB_SUCCESS != result ) return result;
2867 
2868  unsigned char bits = 0x5;
2869  result = MB->tag_set_data( stale_bits, &stale_handle1, 1, &bits );
2870  if( MB_SUCCESS != result ) return result;
2871  bits = 0;
2872  result = MB->tag_get_data( stale_bits, &stale_handle1, 1, &bits );
2873  if( MB_SUCCESS != result ) return result;
2874  if( bits != 0x5 ) return MB_FAILURE;
2875 
2876  def_data = 1;
2877  result = MB->tag_set_data( stale_dense, &stale_handle1, 1, &def_data );
2878  if( MB_SUCCESS != result ) return result;
2879  def_data = 0;
2880  result = MB->tag_get_data( stale_dense, &stale_handle1, 1, &def_data );
2881  if( MB_SUCCESS != result ) return result;
2882  if( def_data != 1 ) return MB_FAILURE;
2883 
2884  def_data = 100;
2885  result = MB->tag_set_data( stale_sparse, &stale_handle1, 1, &def_data );
2886  if( MB_SUCCESS != result ) return result;
2887  def_data = 0;
2888  result = MB->tag_get_data( stale_sparse, &stale_handle1, 1, &def_data );
2889  if( MB_SUCCESS != result ) return result;
2890  if( def_data != 100 ) return MB_FAILURE;
2891 
2892  result = MB->delete_entities( &stale_handle1, 1 );
2893  if( MB_SUCCESS != result ) return result;
2894  result = MB->create_vertex( coords, stale_handle2 );
2895  if( MB_SUCCESS != result ) return result;
2896 
2897  if( stale_handle1 != stale_handle2 )
2898  cout << "Tag test could test stale data" << endl;
2899  else
2900  {
2901  bits = 0;
2902  result = MB->tag_get_data( stale_bits, &stale_handle2, 1, &bits );
2903  if( MB_SUCCESS != result ) return result;
2904  if( bits != 0 ) return MB_FAILURE;
2905 
2906  def_data = 3;
2907  result = MB->tag_get_data( stale_dense, &stale_handle2, 1, &def_data );
2908  if( MB_SUCCESS != result ) return result;
2909  if( def_data != 9 ) return MB_FAILURE;
2910 
2911  def_data = 3;
2912  ErrorCode stale_result = MB->tag_get_data( stale_sparse, &stale_handle2, 1, &def_data );
2913  // we are supposed to fail here
2914  if( stale_result != MB_TAG_NOT_FOUND ) return MB_FAILURE;
2915  }
2916 
2917  result = MB->tag_delete( stale_dense );
2918  if( MB_SUCCESS != result ) return result;
2919 
2920  result = MB->delete_entities( &stale_handle2, 1 );
2921  if( MB_SUCCESS != result ) return result;
2922 
2923  // get all blocks with material tag and with tag_value of 1 (should only be 1)
2924  Range entities;
2925  int value = 1;
2926  const void* dum_ptr = &value;
2927  Tag material_tag;
2928  result = MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, material_tag );
2929  if( MB_SUCCESS != result ) return result;
2930  if( MB->get_entities_by_type_and_tag( 0, MBENTITYSET, &material_tag, &dum_ptr, 1, entities ) != MB_SUCCESS )
2931  return MB_FAILURE;
2932 
2933  if( entities.size() != 1 ) return MB_FAILURE;
2934 
2935  // add a dense tag to hexes
2936  Tag junk_tag;
2937  if( MB->tag_get_handle( "junk_tag", 1, MB_TYPE_INTEGER, junk_tag, MB_TAG_DENSE | MB_TAG_EXCL ) != MB_SUCCESS )
2938  return MB_FAILURE;
2939 
2940  // Set the dense tag on 5 hexes to 3489
2941  Range test_range;
2942  result = MB->get_entities_by_type( 0, MBHEX, test_range );
2943  if( result != MB_SUCCESS ) return result;
2944 
2945  Range::iterator iter, end_iter;
2946  iter = test_range.begin();
2947  end_iter = test_range.end();
2948 
2949  int data = 3489;
2950  const void* ptr_data = &data;
2951 
2952  // mark approxiamtely the first 20% of the hex entities; also put a bit tag on them
2953  unsigned int times = test_range.size() / 5;
2954  bits = 0x5;
2955  const void* ptr_bits = &bits;
2956 
2957  for( unsigned int i = 0; i < times; i++ )
2958  {
2959  if( MB->tag_set_data( junk_tag, &( *iter ), 1, &data ) != MB_SUCCESS ) return MB_FAILURE;
2960  if( MB->tag_set_data( stale_bits, &( *iter ), 1, &bits ) != MB_SUCCESS ) return MB_FAILURE;
2961  ++iter;
2962  }
2963 
2964  entities.clear();
2965  // fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
2966  if( MB->get_entities_by_type_and_tag( 0, MBHEX, &junk_tag, &ptr_data, 1, entities ) != MB_SUCCESS )
2967  return MB_FAILURE;
2968 
2969  if( entities.size() != times ) // should get as many hexes as you perviously marked
2970  return MB_FAILURE;
2971 
2972  // fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
2973  entities.clear();
2974  if( MB->get_entities_by_type_and_tag( 0, MBHEX, &stale_bits, &ptr_bits, 1, entities ) != MB_SUCCESS )
2975  return MB_FAILURE;
2976 
2977  if( entities.size() != times ) // should get as many hexes as you perviously marked
2978  return MB_FAILURE;
2979 
2980  // test fetch by tag value again, this time limiting the results
2981  // to the contents of an entity set
2982  EntityHandle meshset;
2983  result = MB->create_meshset( MESHSET_SET, meshset );
2984  if( MB_SUCCESS != result ) return result;
2985  result = MB->add_entities( meshset, test_range );
2986  if( MB_SUCCESS != result ) return result;
2987 
2988  // fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
2989  entities.clear();
2990  result = MB->get_entities_by_type_and_tag( meshset, MBHEX, &junk_tag, &ptr_data, 1, entities );
2991  if( MB_SUCCESS != result ) return result;
2992 
2993  if( entities.size() != times ) // should get as many hexes as you perviously marked
2994  return MB_FAILURE;
2995 
2996  // fetch the hex entities of type--MBHEX, tag-"stale_bits", and tag value -- 0x5
2997  entities.clear();
2998  result = MB->get_entities_by_type_and_tag( meshset, MBHEX, &stale_bits, &ptr_bits, 1, entities );
2999  if( MB_SUCCESS != result ) return result;
3000 
3001  if( entities.size() != times ) // should get as many hexes as you perviously marked
3002  return MB_FAILURE;
3003 
3004  // now try the query with an empty meshset, expecting to get back
3005  // an empty Range
3006 
3007  result = MB->create_meshset( MESHSET_SET, meshset );
3008  if( MB_SUCCESS != result ) return result;
3009 
3010  entities.clear();
3011  result = MB->get_entities_by_type_and_tag( meshset, MBHEX, &junk_tag, &ptr_data, 1, entities );
3012  if( MB_SUCCESS != result ) return result;
3013 
3014  if( !entities.empty() ) return MB_FAILURE;
3015 
3016  result = MB->tag_delete( stale_bits );
3017  if( MB_SUCCESS != result ) return result;
3018 
3019  return MB_SUCCESS;
3020 }
3021 #endif
3023 {
3024  Core moab;
3025  Interface* mb = &moab;
3026  ErrorCode result = create_some_mesh( mb );
3027  if( MB_SUCCESS != result ) return result;
3028 
3029  char tagname[64];
3030  sprintf( tagname, "t%d", rand() );
3031 
3032  Tag tag;
3033  const EntityHandle def_val = ~(EntityHandle)0;
3034  ErrorCode rval = mb->tag_get_handle( tagname, 1, MB_TYPE_HANDLE, tag, storage | MB_TAG_EXCL, &def_val );
3035  if( MB_SUCCESS != rval ) return rval;
3036 
3037  Range entities;
3039  if( entities.empty() ) return MB_FAILURE;
3040 
3041  // set tag on every other entity to be the entities handle
3043  bool odd = true;
3044  for( i = entities.begin(); i != entities.end(); ++i, odd = !odd )
3045  {
3046  if( odd )
3047  {
3048  const EntityHandle h = *i;
3049  rval = mb->tag_set_data( tag, &h, 1, &h );
3050  if( MB_SUCCESS != rval ) return rval;
3051  }
3052  }
3053 
3054  // check values on every entity -- expect default for every other entity
3055  odd = true;
3056  for( i = entities.begin(); i != entities.end(); ++i, odd = !odd )
3057  {
3058  EntityHandle val = 0;
3059  rval = mb->tag_get_data( tag, &*i, 1, &val );
3060  if( MB_SUCCESS != rval ) return rval;
3061 
3062  if( odd )
3063  {
3064  if( val != *i ) return MB_FAILURE;
3065  }
3066  else
3067  {
3068  if( val != def_val ) return MB_FAILURE;
3069  }
3070  }
3071 
3072  // set tag values on all entities
3073  std::vector< EntityHandle > values( entities.size() );
3074  std::copy( entities.begin(), entities.end(), values.begin() );
3075  rval = mb->tag_set_data( tag, entities, &values[0] );
3076  if( MB_SUCCESS != rval ) return rval;
3077 
3078  // check values on every entity -- expect default for every other entity
3079  for( i = entities.begin(); i != entities.end(); ++i )
3080  {
3081  EntityHandle val = 0;
3082  rval = mb->tag_get_data( tag, &*i, 1, &val );
3083  if( MB_SUCCESS != rval ) return rval;
3084  if( val != *i ) return MB_FAILURE;
3085  }
3086 
3087  // find each entity by tag value
3088  for( i = entities.begin(); i != entities.end(); ++i )
3089  {
3090  const EntityHandle h = *i;
3091  const EntityType type = mb->type_from_handle( h );
3092  const void* const tag_vals[] = { &h };
3093  Range range;
3094  rval = mb->get_entities_by_type_and_tag( 0, type, &tag, tag_vals, 1, range );
3095  if( MB_SUCCESS != rval ) return rval;
3096  if( range.size() != 1 ) return MB_FAILURE;
3097  if( range.front() != h ) return MB_FAILURE;
3098  }
3099 
3100  return MB_SUCCESS;
3101 }
3102 
3104 {
3105  return mb_common_tag_test( MB_TAG_DENSE );
3106 }
3107 
3109 {
3111 }
3112 
3113 // class to offset hex center nodes
3115 {
3116  public:
3117  OffsetHexCenterNodes( Interface* mb, double x, double y, double z ) : gMB( mb )
3118  {
3119  mCoords[0] = 0.0;
3120  mCoords[1] = 0.0;
3121  mCoords[2] = 0.0;
3122  mOffset[0] = x;
3123  mOffset[1] = y;
3124  mOffset[2] = z;
3125  }
3126 
3128 
3130  {
3131  gMB->get_coords( &node, 1, mCoords );
3132  mCoords[0] += mOffset[0];
3133  mCoords[1] += mOffset[1];
3134  mCoords[2] += mOffset[2];
3135  gMB->set_coords( &node, 1, mCoords );
3136  }
3137 
3138  // do nothing
3139  void node_removed( EntityHandle /*node*/ ) {}
3140 
3141  private:
3143  double mCoords[3];
3144  double mOffset[3];
3145 };
3146 #ifdef MOAB_HAVE_NETCDF
3147 ErrorCode mb_entity_conversion_test()
3148 {
3149  ErrorCode error;
3150  Core moab;
3151  Interface* MB = &moab;
3152 
3153  // read in a file so you have some data in the database
3154  std::string file_name = TestDir + "unittest/mbtest3.g";
3155  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3156  if( error != MB_SUCCESS ) return error;
3157 
3158  Range entities;
3159  EntityHandle meshset;
3160  MB->create_meshset( MESHSET_SET, meshset );
3161 
3162  MB->get_entities_by_type( 0, MBHEX, entities );
3163  MB->add_entities( meshset, entities );
3164 
3165  OffsetHexCenterNodes function_object( MB, 0.07, 0.15, 0 );
3166 
3167  MB->convert_entities( meshset, false, false, true, &function_object );
3168  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3169 
3170  file_name = "hex_mid_volume_nodes.g";
3171  error = MB->write_mesh( file_name.c_str() );
3172  if( error != MB_SUCCESS ) return error;
3173 
3174  error = MB->delete_mesh();
3175  if( error != MB_SUCCESS ) return error;
3176 
3177  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3178  if( error != MB_SUCCESS ) return error;
3179 
3180  error = MB->delete_mesh();
3181  if( error != MB_SUCCESS ) return error;
3182 
3183  file_name = TestDir + "unittest/mbtest3.g";
3184  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3185  if( error != MB_SUCCESS ) return error;
3186 
3187  entities.clear();
3188  MB->get_entities_by_type( 0, MBHEX, entities );
3189 
3190  MB->create_meshset( MESHSET_SET, meshset );
3191  MB->add_entities( meshset, entities );
3192  MB->convert_entities( meshset, true, true, true );
3193  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3194 
3195  file_name = "hex_mid_edge_face_vol_nodes.g";
3196  error = MB->write_mesh( file_name.c_str() );
3197  if( error != MB_SUCCESS ) return error;
3198 
3199  error = MB->delete_mesh();
3200  if( error != MB_SUCCESS ) return error;
3201 
3202  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3203  if( error != MB_SUCCESS ) return error;
3204 
3205  error = MB->delete_mesh();
3206  if( error != MB_SUCCESS ) return error;
3207 
3208  file_name = TestDir + "unittest/mbtest3.g";
3209  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3210  if( error != MB_SUCCESS ) return error;
3211 
3212  entities.clear();
3214  unsigned int original_num_nodes = entities.size();
3215  entities.clear();
3216  MB->get_entities_by_type( 0, MBHEX, entities );
3217 
3218  MB->create_meshset( MESHSET_SET, meshset );
3219  MB->add_entities( meshset, entities );
3220  MB->convert_entities( meshset, true, false, false );
3221  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3222 
3223  file_name = "hex_mid_edge_nodes.g";
3224  error = MB->write_mesh( file_name.c_str() );
3225  if( error != MB_SUCCESS ) return error;
3226 
3227  // convert them back to hex8's
3228  MB->convert_entities( meshset, false, false, false );
3229  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3230 
3231  entities.clear();
3233  // make sure the higher order nodes really were deleted
3234  if( entities.size() != original_num_nodes ) return MB_FAILURE;
3235 
3236  error = MB->delete_mesh();
3237  if( error != MB_SUCCESS ) return error;
3238 
3239  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3240  if( error != MB_SUCCESS ) return error;
3241 
3242  error = MB->delete_mesh();
3243  if( error != MB_SUCCESS ) return error;
3244 
3245  file_name = TestDir + "unittest/mbtest1.g";
3246  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3247  if( error != MB_SUCCESS ) return error;
3248 
3249  entities.clear();
3250  MB->get_entities_by_type( 0, MBTET, entities );
3251 
3252  MB->create_meshset( MESHSET_SET, meshset );
3253  MB->add_entities( meshset, entities );
3254  MB->convert_entities( meshset, true, false, false );
3255  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3256 
3257  file_name = "tet_mid_edge_nodes.g";
3258  error = MB->write_mesh( file_name.c_str() );
3259  if( error != MB_SUCCESS ) return error;
3260 
3261  error = MB->delete_mesh();
3262  if( error != MB_SUCCESS ) return error;
3263 
3264  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3265  if( error != MB_SUCCESS ) return error;
3266 
3267  error = MB->delete_mesh();
3268  if( error != MB_SUCCESS ) return error;
3269 
3270  file_name = TestDir + "unittest/mbtest1.g";
3271  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3272  if( error != MB_SUCCESS ) return error;
3273 
3274  entities.clear();
3275  MB->get_entities_by_type( 0, MBTET, entities );
3276 
3277  MB->create_meshset( MESHSET_SET, meshset );
3278  MB->add_entities( meshset, entities );
3279  MB->convert_entities( meshset, false, true, false );
3280  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3281 
3282  file_name = "tet_mid_face_nodes.g";
3283  error = MB->write_mesh( file_name.c_str() );
3284  if( error != MB_SUCCESS ) return error;
3285 
3286  error = MB->delete_mesh();
3287  if( error != MB_SUCCESS ) return error;
3288 
3289  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3290  if( error != MB_SUCCESS ) return error;
3291 
3292  error = MB->delete_mesh();
3293  if( error != MB_SUCCESS ) return error;
3294 
3295  file_name = TestDir + "unittest/mbtest1.g";
3296  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3297  if( error != MB_SUCCESS ) return error;
3298 
3299  entities.clear();
3300  MB->get_entities_by_type( 0, MBTET, entities );
3301 
3302  MB->create_meshset( MESHSET_SET, meshset );
3303  MB->add_entities( meshset, entities );
3304  MB->convert_entities( meshset, true, true, false );
3305  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3306 
3307  file_name = "tet_mid_edge_face_nodes.g";
3308  error = MB->write_mesh( file_name.c_str() );
3309  if( error != MB_SUCCESS ) return error;
3310 
3311  error = MB->delete_mesh();
3312  if( error != MB_SUCCESS ) return error;
3313 
3314  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3315  if( error != MB_SUCCESS ) return error;
3316 
3317  error = MB->delete_mesh();
3318  if( error != MB_SUCCESS ) return error;
3319 
3320  file_name = TestDir + "unittest/mbtest1.g";
3321  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3322  if( error != MB_SUCCESS ) return error;
3323 
3324  // delete all MBTRI's
3325  entities.clear();
3327  if( MB_SUCCESS != error ) return error;
3328  error = MB->delete_entities( entities );
3329  if( MB_SUCCESS != error ) return error;
3330 
3331  entities.clear();
3333  if( MB_SUCCESS != error ) return error;
3334 
3335  // skin the model
3336  for( Range::iterator tet_iter = entities.begin(); tet_iter != entities.end(); ++tet_iter )
3337  {
3338  std::vector< EntityHandle > adj;
3339  error = MB->get_adjacencies( &( *tet_iter ), 1, 2, true, adj );
3340  if( MB_SUCCESS != error ) return error;
3341  for( std::vector< EntityHandle >::iterator tri_iter = adj.begin(); tri_iter != adj.end(); ++tri_iter )
3342  {
3343  std::vector< EntityHandle > up_adj;
3344  MB->get_adjacencies( &( *tri_iter ), 1, 3, false, up_adj );
3345  if( up_adj.size() > 1 )
3346  {
3347  error = MB->delete_entities( &( *tri_iter ), 1 );
3348  if( MB_SUCCESS != error ) return error;
3349  }
3350  }
3351  }
3352 
3353  // create a meshset of the skin
3354  EntityHandle export_meshset;
3355  MB->create_meshset( MESHSET_SET, export_meshset );
3356  Tag material_tag;
3357  MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, material_tag );
3358  int block_id = 100;
3359  MB->tag_set_data( material_tag, &export_meshset, 1, &block_id );
3360  entities.clear();
3361  MB->get_entities_by_type( 0, MBTRI, entities );
3362  // remove the first few tri's for fun
3363  Range tmp_ents;
3364  tmp_ents.insert( *entities.begin() );
3365  entities.erase( entities.begin() );
3366  tmp_ents.insert( *entities.begin() );
3367  entities.erase( entities.begin() );
3368  tmp_ents.insert( *entities.begin() );
3369  entities.erase( entities.begin() );
3370  tmp_ents.insert( *entities.begin() );
3371  entities.erase( entities.begin() );
3372 
3373  MB->add_entities( export_meshset, entities );
3374 
3375  // convert the skin
3376  MB->convert_entities( export_meshset, true, true, false );
3377  if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
3378 
3379  // make sure our first few tri's were untouched
3380  std::vector< EntityHandle > conn( 3 );
3381  for( Range::iterator kter = tmp_ents.begin(); kter != tmp_ents.end(); ++kter )
3382  {
3383  MB->get_connectivity( &( *kter ), 1, conn );
3384  if( conn.size() != 3 ) return MB_FAILURE;
3385  }
3386 
3387  // output the skin
3388  file_name = "tri_mid_edge_face_nodes.g";
3389  error = MB->write_mesh( file_name.c_str(), &export_meshset, 1 );
3390  if( error != MB_SUCCESS ) return error;
3391 
3392  MB->delete_entities( &export_meshset, 1 );
3393 
3394  error = MB->delete_mesh();
3395  if( error != MB_SUCCESS ) return error;
3396 
3397  // read the skin back in
3398  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
3399  if( error != MB_SUCCESS ) return error;
3400 
3401  entities.clear();
3403  // must have 101 nodes
3404  if( entities.size() != 101 ) return MB_FAILURE;
3405 
3406  error = MB->delete_mesh();
3407  if( error != MB_SUCCESS ) return error;
3408 
3409  return MB_SUCCESS;
3410 }
3411 #endif
3412 //! Build two Quads with two edges shared between them. The
3413 //! edges share the same nodes. We should be able to get
3414 //! adjacencies on the edges and get one (correct) quad. We
3415 //! should be able to get the edge adjacencies of the quads
3416 //! and only get 4 (not 5) edges.
3417 //!
3418 
3420 {
3421  //! first clean up any existing mesh.
3422  ErrorCode error;
3423  Core moab;
3424  Interface* MB = &moab;
3425 
3426  //! create 6 nodes, 2 quads and 8 edges. Edge 4 is adjacent
3427  //! to quad 1 and edge 5 is adjacent to quad 2.
3428  //!
3429  //! 4 5 6
3430  //! o--e7---o--e8---o
3431  //! | | |
3432  //! e3 q1 e4 e5 q2 e6
3433  //! | | |
3434  //! o--e1---o--e2---o
3435  //! 1 2 3
3436  //!
3437  double node_coord1[3] = { 0., 0., 0. };
3438  double node_coord2[3] = { 1., 0., 0. };
3439  double node_coord3[3] = { 2., 0., 0. };
3440  double node_coord4[3] = { 0., 1., 0. };
3441  double node_coord5[3] = { 1., 1., 0. };
3442  double node_coord6[3] = { 2., 1., 0. };
3443 
3444  EntityHandle node1, node2, node3, node4, node5, node6;
3445  error = MB->create_vertex( node_coord1, node1 );
3446  if( error != MB_SUCCESS ) return error;
3447 
3448  error = MB->create_vertex( node_coord2, node2 );
3449  if( error != MB_SUCCESS ) return error;
3450 
3451  error = MB->create_vertex( node_coord3, node3 );
3452  if( error != MB_SUCCESS ) return error;
3453 
3454  error = MB->create_vertex( node_coord4, node4 );
3455  if( error != MB_SUCCESS ) return error;
3456 
3457  error = MB->create_vertex( node_coord5, node5 );
3458  if( error != MB_SUCCESS ) return error;
3459 
3460  error = MB->create_vertex( node_coord6, node6 );
3461  if( error != MB_SUCCESS ) return error;
3462 
3463  std::vector< EntityHandle > conn( 4 );
3464  //! create the first quad
3465  EntityHandle quad1;
3466  conn[0] = node1;
3467  conn[1] = node2;
3468  conn[2] = node5;
3469  conn[3] = node4;
3470  error = MB->create_element( MBQUAD, &conn[0], 4, quad1 );
3471  if( error != MB_SUCCESS ) return error;
3472 
3473  //! create the second quad
3474  EntityHandle quad2;
3475  conn[0] = node2;
3476  conn[1] = node3;
3477  conn[2] = node6;
3478  conn[3] = node5;
3479  error = MB->create_element( MBQUAD, &conn[0], 4, quad2 );
3480  if( error != MB_SUCCESS ) return error;
3481 
3482  //! create the edges
3483  EntityHandle edge1;
3484  conn.resize( 2 );
3485  conn[0] = node1;
3486  conn[1] = node2;
3487  error = MB->create_element( MBEDGE, &conn[0], 2, edge1 );
3488  if( error != MB_SUCCESS ) return error;
3489 
3490  EntityHandle edge2;
3491  conn[0] = node2;
3492  conn[1] = node3;
3493  error = MB->create_element( MBEDGE, &conn[0], 2, edge2 );
3494  if( error != MB_SUCCESS ) return error;
3495 
3496  EntityHandle edge3;
3497  conn[0] = node1;
3498  conn[1] = node4;
3499  error = MB->create_element( MBEDGE, &conn[0], 2, edge3 );
3500  if( error != MB_SUCCESS ) return error;
3501 
3502  EntityHandle edge4;
3503  conn[0] = node2;
3504  conn[1] = node5;
3505  error = MB->create_element( MBEDGE, &conn[0], 2, edge4 );
3506  if( error != MB_SUCCESS ) return error;
3507 
3508  EntityHandle edge5;
3509  conn[0] = node2;
3510  conn[1] = node5;
3511  error = MB->create_element( MBEDGE, &conn[0], 2, edge5 );
3512  if( error != MB_SUCCESS ) return error;
3513 
3514  EntityHandle edge6;
3515  conn[0] = node3;
3516  conn[1] = node6;
3517  error = MB->create_element( MBEDGE, &conn[0], 2, edge6 );
3518  if( error != MB_SUCCESS ) return error;
3519 
3520  EntityHandle edge7;
3521  conn[0] = node4;
3522  conn[1] = node5;
3523  error = MB->create_element( MBEDGE, &conn[0], 2, edge7 );
3524  if( error != MB_SUCCESS ) return error;
3525 
3526  EntityHandle edge8;
3527  conn[0] = node5;
3528  conn[1] = node6;
3529  error = MB->create_element( MBEDGE, &conn[0], 2, edge8 );
3530  if( error != MB_SUCCESS ) return error;
3531 
3532  //! Edge 4 and 5 share the same nodes, but should be different entities
3533  if( edge4 == edge5 ) return MB_FAILURE;
3534 
3535  //! Now that the geometry is created start adding the adjacency information
3536  std::vector< EntityHandle > edge_adjacencies1( 4 );
3537  edge_adjacencies1[0] = edge1;
3538  edge_adjacencies1[1] = edge4;
3539  edge_adjacencies1[2] = edge7;
3540  edge_adjacencies1[3] = edge3;
3541 
3542  //! does this (should this) say anything about order of the edges around the
3543  //! quad? Also, does this also build the edge->quad adjacency, or is that
3544  //! does with a separate call?
3545  error = MB->add_adjacencies( quad1, &edge_adjacencies1[0], edge_adjacencies1.size(), true );
3546  if( error != MB_SUCCESS ) return error;
3547 
3548  std::vector< EntityHandle > edge_adjacencies2( 4 );
3549  edge_adjacencies2[0] = edge2;
3550  edge_adjacencies2[1] = edge6;
3551  edge_adjacencies2[2] = edge8;
3552  edge_adjacencies2[3] = edge5;
3553  error = MB->add_adjacencies( quad2, &edge_adjacencies2[0], edge_adjacencies2.size(), true );
3554  if( error != MB_SUCCESS ) return error;
3555 
3556  //! now get the adjacencies of each quad.
3557  std::vector< EntityHandle > quad1_adjacencies;
3558  error = MB->get_adjacencies( &( quad1 ), 1, 1, false, quad1_adjacencies );
3559  if( error != MB_SUCCESS ) return error;
3560 
3561  std::sort( quad1_adjacencies.begin(), quad1_adjacencies.end() );
3562  std::sort( edge_adjacencies1.begin(), edge_adjacencies1.end() );
3563 
3564  if( quad1_adjacencies != edge_adjacencies1 ) return MB_FAILURE;
3565 
3566  std::vector< EntityHandle > quad2_adjacencies;
3567  error = MB->get_adjacencies( &( quad2 ), 1, 1, false, quad2_adjacencies );
3568  if( error != MB_SUCCESS ) return error;
3569 
3570  std::sort( quad2_adjacencies.begin(), quad2_adjacencies.end() );
3571  std::sort( edge_adjacencies2.begin(), edge_adjacencies2.end() );
3572 
3573  if( quad2_adjacencies != edge_adjacencies2 ) return MB_FAILURE;
3574 
3575  //! try getting the adjacency of edge1 (should be quad1)
3576  std::vector< EntityHandle > edge1_adjacencies;
3577  error = MB->get_adjacencies( &( edge1 ), 1, 2, false, edge1_adjacencies );
3578  if( error != MB_SUCCESS ) return error;
3579 
3580  //! there should be only 1 entity adjacent to edge1
3581  if( edge1_adjacencies.size() != 1 ) return MB_FAILURE;
3582 
3583  //! and that entity should be quad1
3584  if( edge1_adjacencies[0] != quad1 ) return MB_FAILURE;
3585 
3586  //! try getting the adjacency of edge6 (should be one)
3587  std::vector< EntityHandle > edge6_adjacencies;
3588  error = MB->get_adjacencies( &( edge6 ), 1, 2, false, edge6_adjacencies );
3589  if( error != MB_SUCCESS ) return error;
3590 
3591  //! there should be only 1 entity adjacent to edge6
3592  if( edge6_adjacencies.size() != 1 ) return MB_FAILURE;
3593 
3594  //! Now seal up the "gap" caused by edges 4 and 5. Remove edge5
3595  //! from the adjacencies of quad2 and add edge 4 to quad2.
3596 
3597  std::vector< EntityHandle > edge5_adjacencies( 1, edge5 );
3598  error = MB->remove_adjacencies( quad2, &edge5_adjacencies[0], edge5_adjacencies.size() );
3599  if( error != MB_SUCCESS ) return error;
3600 
3601  std::vector< EntityHandle > edge4_adjacencies( 1, edge4 );
3602  error = MB->add_adjacencies( quad2, &edge4_adjacencies[0], edge4_adjacencies.size(), true );
3603  if( error != MB_SUCCESS ) return error;
3604 
3605  //! get the adjacencies of edge4 and it should return both quads.
3606  std::vector< EntityHandle > quad_adjacencies;
3607  error = MB->get_adjacencies( &( edge4 ), 1, 2, false, quad_adjacencies );
3608  if( error != MB_SUCCESS ) return error;
3609 
3610  //! there should be 2 entities adjacent to edge4
3611  if( quad_adjacencies.size() != 2 ) return MB_FAILURE;
3612 
3613  //! and they should be quad1 and quad2. Note that we are not saying anything
3614  //! about order in the array.
3615  if( ( quad_adjacencies[0] != quad1 || quad_adjacencies[1] != quad2 ) &&
3616  ( quad_adjacencies[0] != quad2 || quad_adjacencies[1] != quad1 ) )
3617  return MB_FAILURE;
3618 
3619  //! clean up on exit
3620  error = MB->delete_mesh();
3621  if( error != MB_SUCCESS ) return error;
3622 
3623  return MB_SUCCESS;
3624 }
3625 
3626 /*bool lessnodesZ(const EntityHandle entity_handle1, const EntityHandle entity_handle2)
3627  {
3628  double coords1[3], coords2[3];
3629  gMB->get_coords(entity_handle1, coords1);
3630  gMB->get_coords(entity_handle2, coords2);
3631 
3632  return coords2[2] < coords1[2];
3633  }*/
3634 
3635 /*void sort_verts(Range vertices)
3636  {
3637  std::vector<EntityHandle> vert_vec(vertices.size());
3638  Range::const_iterator iter;
3639  for (iter = vertices.begin(); iter != vertices.end(); ++iter)
3640  vert_vec.push_back(*iter);
3641  vert_vec.sort(lessnodesZ);
3642  }*/
3643 bool points_are_coincident( const double* first, const double* second )
3644 {
3645  double diff[3];
3646  diff[2] = first[2] - second[2];
3647  // if (diff[2] > 0.001) return false;
3648 
3649  diff[0] = first[0] - second[0];
3650  diff[1] = first[1] - second[1];
3651 
3652  double length = diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2];
3653  if( fabs( length ) < .001 ) return true;
3654 
3655  return false;
3656 }
3658  const Range& vertices,
3659  std::vector< std::pair< EntityHandle, EntityHandle > >& coin_nodes )
3660 {
3661  double first_coords[3], second_coords[3];
3662  Range::const_iterator iter, jter;
3663  std::pair< EntityHandle, EntityHandle > coincident_pair;
3664  ErrorCode result;
3665 
3666  for( iter = vertices.begin(); iter != vertices.end(); ++iter )
3667  {
3668  result = gMB->get_coords( &( *iter ), 1, first_coords );
3669  if( result != MB_SUCCESS ) return result;
3670 
3671  for( jter = iter; jter != vertices.end(); ++jter )
3672  {
3673  if( *iter != *jter )
3674  {
3675  result = gMB->get_coords( &( *jter ), 1, second_coords );
3676  if( result != MB_SUCCESS ) return result;
3677 
3678  if( points_are_coincident( first_coords, second_coords ) )
3679  {
3680  coincident_pair.first = *iter;
3681  coincident_pair.second = *jter;
3682  coin_nodes.push_back( coincident_pair );
3683  }
3684  }
3685  }
3686  }
3687  return MB_SUCCESS;
3688 }
3689 
3691  const Range& entities,
3692  int num_nodes,
3693  std::vector< std::pair< EntityHandle, EntityHandle > >& coin )
3694 {
3695  double coords1[8][3], coords2[8][3];
3696  Range::iterator iter, jter;
3697  std::vector< EntityHandle > conn( 8 );
3698  std::pair< EntityHandle, EntityHandle > coincident_pair;
3699  int i = 0, /* j = 0,*/ ii = 0;
3700 
3701  for( iter = entities.begin(); iter != entities.end(); ++iter )
3702  {
3703  // Get the coordinates for the element corners.
3704  if( gMB->get_connectivity( &( *iter ), 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
3705  for( ii = 0; ii < num_nodes; ii++ )
3706  {
3707  if( gMB->get_coords( &( conn[ii] ), 1, coords1[ii] ) != MB_SUCCESS ) return MB_FAILURE;
3708  }
3709 
3710  for( jter = iter; jter != entities.end(); ++jter )
3711  {
3712  if( *iter != *jter )
3713  {
3714  // Elements should be the same sense to merge.
3715  if( gMB->get_connectivity( &( *jter ), 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
3716 
3717  for( int tq = 0; tq < num_nodes; tq++ )
3718  if( gMB->get_coords( &( conn[tq] ), 1, coords2[tq] ) != MB_SUCCESS ) return MB_FAILURE;
3719  // if(gMB->get_coords(&(conn[0]), 1, coords2[0]) != MB_SUCCESS)
3720  // return MB_FAILURE;
3721 
3722  // Find if first node is coincident before testing the rest.
3723  bool first = false;
3724  for( i = 0; i < num_nodes; i++ )
3725  {
3726  if( points_are_coincident( coords1[i], coords2[0] ) )
3727  {
3728  /* cout <<"first("<<i<<",0) - ";
3729  cout <<" coords1["<<i<<"] = ("
3730  <<coords1[i][0]<<","
3731  <<coords1[i][1]<<","
3732  <<coords1[i][2]<<") ";
3733  cout <<" coords2["<<0<<"] = ("
3734  <<coords2[0][0]<<","
3735  <<coords2[0][1]<<","
3736  <<coords2[0][2]<<")\n";*/
3737  first = true;
3738  break;
3739  }
3740  }
3741  // TEST -- Find if second node is coincident before testing the rest.
3742  bool second = false;
3743  for( int t2 = 0; t2 < num_nodes; t2++ )
3744  {
3745  if( points_are_coincident( coords1[t2], coords2[1] ) )
3746  {
3747  /* cout <<"second("<<t2<<",1) - ";
3748  cout <<" coords1["<<t2<<"] = ("
3749  <<coords1[t2][0]<<","
3750  <<coords1[t2][1]<<","
3751  <<coords1[t2][2]<<") ";
3752  cout <<" coords2["<<1<<"] = ("
3753  <<coords2[1][0]<<","
3754  <<coords2[1][1]<<","
3755  <<coords2[1][2]<<")\n";*/
3756  second = true;
3757  break;
3758  }
3759  }
3760  // TEST -- Find if second node is coincident before testing the rest.
3761  bool third = false;
3762  for( int ti = 0; ti < num_nodes; ti++ )
3763  {
3764  if( points_are_coincident( coords1[ti], coords2[2] ) )
3765  {
3766  /* cout <<"third("<<ti<<",2) - ";
3767  cout <<" coords1["<<ti<<"] = ("
3768  <<coords1[ti][0]<<","
3769  <<coords1[ti][1]<<","
3770  <<coords1[ti][2]<<") ";
3771  cout <<" coords2["<<1<<"] = ("
3772  <<coords2[2][0]<<","
3773  <<coords2[2][1]<<","
3774  <<coords2[2][2]<<")\n";*/
3775  third = true;
3776  break;
3777  }
3778  }
3779  if( ( first ) && ( second ) && ( third ) )
3780  {
3781  cout << "i = " << i << "\n";
3782  for( int tii = 0; tii < num_nodes; tii++ )
3783  {
3784  cout << " coords1[" << tii << "] = (" << coords1[tii][0] << "," << coords1[tii][1] << ","
3785  << coords1[tii][2] << ") ";
3786  cout << " coords2[" << tii << "] = (" << coords2[tii][0] << "," << coords2[tii][1] << ","
3787  << coords2[tii][2] << ")\n";
3788  }
3789  }
3790 
3791  if( i < num_nodes )
3792  {
3793  for( ii = 1; ii < num_nodes; ii++ )
3794  {
3795  if( gMB->get_coords( &( conn[ii] ), 1, coords2[ii] ) != MB_SUCCESS ) return MB_FAILURE;
3796  }
3797  /*
3798  for(j=1; j<num_nodes; j++)
3799  {
3800 
3801  if(!points_are_coincident(coords1[j], coords2[(j+i)%num_nodes]))
3802  break;
3803  }
3804  if(j == num_nodes)*/
3805  if( ( first ) && ( second ) && ( third ) )
3806  {
3807  coincident_pair.first = *iter;
3808  coincident_pair.second = *jter;
3809  coin.push_back( coincident_pair );
3810  }
3811  }
3812  }
3813  }
3814  }
3815 
3816  return MB_SUCCESS;
3817 }
3818 
3819 #ifdef MOAB_HAVE_NETCDF
3820 ErrorCode mb_merge_test()
3821 {
3822  Core moab;
3823  Interface* MB = &moab;
3824 
3825  time_t begin_time = clock();
3826  unsigned int i;
3827  ErrorCode result;
3828  Skinner Skinner_Obj( MB );
3829 
3830  std::string test_files[] = { std::string( "cell1.gen" ), std::string( "cell2.gen" ) };
3831  /* std::string("cell3.gen"),
3832  std::string("cell4.gen"),
3833  std::string("cell5.gen"),
3834  std::string("cell6.gen"),
3835  std::string("cell7.gen"),
3836  std::string("cell8.gen"),
3837  std::string("cell9.gen"),
3838  std::string("cell10.gen"),
3839  std::string("cell11.gen"),
3840  std::string("cell12.gen"),
3841  std::string("cell13.gen"),
3842  std::string("cell14.gen"),
3843  std::string("cell15.gen"),
3844  std::string("cell16.gen"),
3845  std::string("cell17.gen"),
3846  std::string("cell18.gen"),
3847  std::string("cell19.gen"),
3848  std::string("cell20.gen"),
3849  std::string("cell21.gen"),
3850  std::string("cell22.gen"),
3851  std::string("cell23.gen"),
3852  std::string("cell24.gen")};*/
3853 
3854  /*std::vector<Range> entities(sizeof(test_files));
3855  std::vector<Range> forward_lower(sizeof(test_files));
3856  std::vector<Range> reverse_lower(sizeof(test_files));
3857  std::vector<Range> nodes(sizeof(test_files));*/
3858  Range entities;
3859  Range forward_lower;
3860  Range reverse_lower;
3861  Range faces;
3862  Range nodes;
3863 
3864  cout << "---Starting Merge Tests---" << endl << endl;
3865  for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
3866  {
3867 
3868  cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
3869  result = MB->load_mesh( test_files[i].c_str(), NULL, 0 );
3870  if( result == MB_SUCCESS ) cout << "Loaded " << test_files[i] << "\n";
3871  // get Hexes from model
3872  }
3873  result = MB->get_entities_by_type( 0, MBHEX, entities );
3874  if( MB_SUCCESS != result ) return result;
3875  Skinner_Obj.find_skin( 0, entities, false, forward_lower, &reverse_lower );
3876  // cout <<"num hexes = "<<entities.size()<<"\n";
3877  // cout <<"fl = "<<forward_lower.size()<<" rl = "<<reverse_lower.size()<<"\n";
3878 
3879  // Range::const_iterator iter;
3880  int dim = 0;
3881  // int num_ents = 1;
3882  result = MB->get_adjacencies( forward_lower, dim, true, nodes, Interface::UNION );
3883  // cout <<"nodes.size() = "<<nodes.size() <<"\n";
3884 
3885  // result = MB->get_entities_by_type(0, MBQUAD, faces);
3886  // cout <<"num faces = "<<faces.size() <<"\n";
3887 
3888  std::vector< std::pair< EntityHandle, EntityHandle > > coin_nodes;
3889  // cout <<"Begining sort...\n";
3890  // std::sort(nodes.begin(),nodes.end(),lessnodesZ);
3891  // cout <<"Ending sort...\n";
3892  result = find_coincident_nodes( MB, nodes, coin_nodes );
3893  cout << "coin_nodes.size() = " << coin_nodes.size() << "\n";
3894  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator n_iter;
3895  for( n_iter = coin_nodes.begin(); n_iter != coin_nodes.end(); ++n_iter )
3896  {
3897  result = MB->merge_entities( ( *n_iter ).first, ( *n_iter ).second, false, true );
3898  if( MB_SUCCESS != result ) return result;
3899  }
3900  /* std::vector<std::pair<EntityHandle, EntityHandle> > coin_faces;
3901  int nodes_per_elt = 4;
3902  result = find_coincident_elements(forward_lower, nodes_per_elt, coin_faces);
3903  if (result != MB_SUCCESS) cout <<"find_coincident_elements fail!\n";
3904  cout <<"coin_faces.size() = "<<coin_faces.size() <<"\n";
3905  std::vector< std::pair<EntityHandle, EntityHandle> >::iterator f_iter;
3906  for (f_iter=coin_faces.begin(); f_iter != coin_faces.end(); ++f_iter)
3907  MB->merge_entities((*f_iter).first, (*f_iter).second, true, true);*/
3908  /*
3909  std::vector<std::pair<EntityHandle, EntityHandle> > coin_fl;
3910  nodes_per_elt = 4;
3911  result = find_coincident_elements(entities, nodes_per_elt, coin_fl);
3912  cout <<"coin_fl.size() = "<<coin_fl.size() <<"\n";
3913  */
3914  int num_ents;
3915  if( ( MB_SUCCESS == MB->get_number_entities_by_dimension( 0, 3, num_ents ) && 0 != num_ents ) ||
3916  ( MB_SUCCESS == MB->get_number_entities_by_dimension( 0, 2, num_ents ) && 0 != num_ents ) )
3917  result = MB->write_mesh( "merge_test.g" );
3918  ;
3919 
3920  double clocks_per_sec = (double)CLOCKS_PER_SEC;
3921  double real_time = difftime( time( NULL ), begin_time );
3922  cout << "TIME: " << ( real_time / clocks_per_sec ) << " seconds.\n";
3923  return result;
3924 }
3925 #endif
3926 
3928 {
3929  Core moab;
3930  Interface* mb = &moab;
3931  ErrorCode rval;
3932 
3933  // create two quads with a coincident edge pair
3934  double coords[] = { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 2, 0, 0, 2, 1, 0 };
3935  EntityHandle verts[8];
3936  for( int i = 0; i < 8; ++i )
3937  mb->create_vertex( coords + 3 * i, verts[i] );
3938  EntityHandle quad1, quad2, edge1, edge2;
3939  mb->create_element( MBQUAD, verts, 4, quad1 );
3940  mb->create_element( MBQUAD, verts + 4, 4, quad2 );
3941  mb->create_element( MBEDGE, verts + 1, 2, edge1 );
3942  mb->create_element( MBEDGE, verts + 4, 2, edge2 );
3943 
3944  // create two tracking sets containing the vertices
3945  // and edge of each quad
3946  EntityHandle set1, set2;
3948  mb->create_meshset( MESHSET_TRACK_OWNER | MESHSET_ORDERED, set2 );
3949  mb->add_entities( set1, verts, 4 );
3950  mb->add_entities( set2, verts + 4, 4 );
3951  mb->add_entities( set1, &edge1, 1 );
3952  mb->add_entities( set2, &edge2, 1 );
3953 
3954  // now merge the coincident edges
3955  rval = mb->merge_entities( verts[1], verts[5], false, true );
3956  if( MB_SUCCESS != rval )
3957  {
3958  std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
3959  return rval;
3960  }
3961  rval = mb->merge_entities( verts[2], verts[4], false, true );
3962  if( MB_SUCCESS != rval )
3963  {
3964  std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
3965  return rval;
3966  }
3967  rval = mb->merge_entities( edge1, edge2, false, true );
3968  if( MB_SUCCESS != rval )
3969  {
3970  std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
3971  return rval;
3972  }
3973 
3974  // check that there is only one edge and that it has the correct connectivity
3975  Range r;
3976  mb->get_entities_by_type( 0, MBEDGE, r );
3977  if( r.size() != 1 || r.front() != edge1 )
3978  {
3979  std::cerr << "Edge merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
3980  return MB_FAILURE;
3981  }
3982  std::vector< EntityHandle > exp( verts + 1, verts + 3 ), act;
3983  mb->get_connectivity( &edge1, 1, act );
3984  if( exp != act )
3985  {
3986  std::cerr << "Incorrect conn for edge at " << __FILE__ << ":" << __LINE__ << std::endl;
3987  return MB_FAILURE;
3988  }
3989 
3990  // check that quad connectivity is as expected
3991  exp = std::vector< EntityHandle >( verts, verts + 4 );
3992  act.clear();
3993  mb->get_connectivity( &quad1, 1, act );
3994  if( exp != act )
3995  {
3996  std::cerr << "Incorrect conn for quad at " << __FILE__ << ":" << __LINE__ << std::endl;
3997  return MB_FAILURE;
3998  }
3999  exp.resize( 4 );
4000  exp[0] = verts[2];
4001  exp[1] = verts[1];
4002  exp[2] = verts[6];
4003  exp[3] = verts[7];
4004  act.clear();
4005  mb->get_connectivity( &quad2, 1, act );
4006  if( exp != act )
4007  {
4008  std::cerr << "Incorrect conn for quad at " << __FILE__ << ":" << __LINE__ << std::endl;
4009  return MB_FAILURE;
4010  }
4011 
4012  // check that set contents are correctly updated
4013  exp = std::vector< EntityHandle >( verts, verts + 4 );
4014  exp.push_back( edge1 );
4015  act.clear();
4016  mb->get_entities_by_handle( set1, act );
4017  std::sort( exp.begin(), exp.end() );
4018  std::sort( act.begin(), act.end() );
4019  if( exp != act )
4020  {
4021  std::cerr << "Incorrect set contents at " << __FILE__ << ":" << __LINE__ << std::endl;
4022  std::cerr << " Expected: ";
4023  std::copy( exp.begin(), exp.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
4024  std::cerr << std::endl << " Actual : ";
4025  std::copy( act.begin(), act.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
4026  std::cerr << std::endl;
4027  return MB_FAILURE;
4028  }
4029 
4030  exp.resize( 5 );
4031  exp[0] = verts[2];
4032  exp[1] = verts[1];
4033  exp[2] = verts[6];
4034  exp[3] = verts[7];
4035  exp[4] = edge1;
4036  act.clear();
4037  mb->get_entities_by_handle( set2, act );
4038  if( exp != act )
4039  {
4040  std::cerr << "Incorrect set contents at " << __FILE__ << ":" << __LINE__ << std::endl;
4041  std::cerr << " Expected: ";
4042  std::copy( exp.begin(), exp.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
4043  std::cerr << std::endl << " Actual : ";
4044  std::copy( act.begin(), act.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
4045  std::cerr << std::endl;
4046  return MB_FAILURE;
4047  }
4048 
4049  return MB_SUCCESS;
4050 }
4051 #ifdef MOAB_HAVE_NETCDF
4052 ErrorCode mb_stress_test()
4053 {
4054  ErrorCode error;
4055  Core moab;
4056  Interface* MB = &moab;
4057 
4058  cout << " Beginning Stress Test . . ." << endl;
4059  cout << "\n Reading elements" << endl;
4060  clock_t start = clock();
4061  clock_t total_start = clock();
4062 
4063  // read in a file so you have some data in the database
4064  std::string file_name = "mb_big_test.g";
4065  error = MB->load_mesh( file_name.c_str(), NULL, 0 );
4066  if( error != MB_SUCCESS ) return error;
4067 
4068  clock_t stop = clock();
4069 
4070  int num_entities_local;
4071  error = MB->get_number_entities_by_type( 0, MBHEX, num_entities_local );
4072  if( error != MB_SUCCESS ) return error;
4073 
4074  if( num_entities_local != 256000 ) return error;
4075 
4076  float time = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
4077  float speed = num_entities_local / time;
4078  cout << " Read " << num_entities_local << " entities"
4079  << " in " << time << " seconds" << endl;
4080  cout << " at " << speed << " elements per second." << endl;
4081 
4082  cout << "\n Transforming and copying elements" << endl;
4083  start = clock();
4084 
4085  Range hexes;
4086  error = MB->get_entities_by_type( 0, MBHEX, hexes );
4087  if( error != MB_SUCCESS ) return error;
4088 
4089  std::vector< EntityHandle > conn;
4090  Range::iterator iter;
4091  for( iter = hexes.begin(); iter != hexes.end(); ++iter )
4092  {
4093  error = MB->get_connectivity( &( *iter ), 1, conn );
4094  if( error != MB_SUCCESS ) return error;
4095 
4096  double coords[3];
4097  int i = 0;
4098  std::vector< EntityHandle > vertex_handle( 8 );
4099  EntityHandle element_handle;
4100  std::vector< EntityHandle >::iterator jter;
4101 
4102  for( jter = conn.begin(); jter != conn.end(); ++jter )
4103  {
4104  error = MB->get_coords( &( *jter ), 1, coords );
4105  if( error != MB_SUCCESS ) return error;
4106  coords[2] += 20.0;
4107  error = MB->create_vertex( coords, vertex_handle[i++] );
4108  if( error != MB_SUCCESS ) return error;
4109  }
4110  error = MB->create_element( MBHEX, &vertex_handle[0], 8, element_handle );
4111  if( error != MB_SUCCESS ) return error;
4112  }
4113 
4114  stop = clock();
4115  time = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
4116 
4117  cout << " Transformed and created " << num_entities_local << " entities"
4118  << " in " << time << " seconds" << endl;
4119 
4120  // Create mesh set
4121  cout << "\n Creating meshset" << endl;
4122  start = clock();
4123  error = MB->get_entities_by_type( 0, MBHEX, hexes );
4124  if( error != MB_SUCCESS ) return error;
4125 
4126  if( hexes.size() != 512000 ) return MB_FAILURE;
4127 
4130  if( error != MB_SUCCESS ) return error;
4131 
4132  error = MB->add_entities( mesh_set, hexes );
4133  if( error != MB_SUCCESS ) return error;
4134 
4135  stop = clock();
4136  time = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
4137 
4138  cout << " Created meshset with " << hexes.size() << " entities"
4139  << " in " << time << " seconds" << endl;
4140 
4141  cout << "\n Writing 512K element file . . ." << endl;
4142  start = clock();
4143 
4144  // set the block tag
4145  Tag tag_handle;
4146  ErrorCode result = MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handle );
4147  if( result != MB_SUCCESS ) return result;
4148 
4149  int id = 1;
4150  result = MB->tag_set_data( tag_handle, &mesh_set, 1, &id );
4151  if( result != MB_SUCCESS ) return result;
4152 
4153  std::vector< EntityHandle > output_list;
4154  output_list.push_back( mesh_set );
4155 
4156  file_name = "mb_stress_out.g";
4157  error = MB->write_mesh( file_name.c_str(), &output_list[0], output_list.size() );
4158  if( error != MB_SUCCESS ) return error;
4159 
4160  stop = clock();
4161  time = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
4162 
4163  cout << " Wrote file with " << hexes.size() << " entities"
4164  << " in " << time << " seconds" << endl;
4165 
4166  clock_t total_stop = clock();
4167  time = static_cast< float >( total_stop - total_start ) / CLOCKS_PER_SEC;
4168 
4169  cout << " Total time: " << time << " seconds." << endl;
4170 
4171  MB->delete_mesh();
4172 
4173  return MB_SUCCESS;
4174 }
4175 #endif
4176 
4178 {
4179  Core moab;
4180  Interface* MB = &moab;
4181 
4182  // various tests for canonical ordering
4183 
4184  // CN::AdjacentSubEntities
4185  std::vector< int > vec1, vec2;
4186  ErrorCode result;
4187 
4188  EntityType this_type;
4189 
4190  for( this_type = MBEDGE; this_type != MBKNIFE; this_type++ )
4191  {
4192 
4193  for( int i = 0; i < CN::VerticesPerEntity( this_type ); i++ )
4194  {
4195  // test for edges and faces
4196  for( int dim = 1; dim <= CN::Dimension( this_type ); dim++ )
4197  {
4198  // get the sides adjacent to this vertex
4199  vec1.clear();
4200  int temp_result = CN::AdjacentSubEntities( this_type, &i, 1, 0, dim, vec1 );
4201 
4202  if( 0 != temp_result || vec1.size() > (unsigned int)CN::NumSubEntities( this_type, dim ) )
4203  {
4204  cout << "failed getting sides for type " << CN::EntityTypeName( this_type ) << " dimension" << dim
4205  << endl;
4206  return MB_FAILURE;
4207  }
4208 
4209  // now get the vertices shared by these sides
4210  vec2.clear();
4211  temp_result = CN::AdjacentSubEntities( this_type, &vec1[0], vec1.size(), dim, 0, vec2 );
4212 
4213  // vertex side recovered should be i
4214  if( 0 != temp_result ||
4215  // if dimension is same as DIMENSION(this_type), will get back all the
4216  // vertices in the entity
4217  ( dim == CN::Dimension( this_type ) &&
4218  vec2.size() != (unsigned int)CN::VerticesPerEntity( this_type ) ) ||
4219  // otherwise, we should get back only one vertex, and it should be the one
4220  // we started with
4221  ( dim != CN::Dimension( this_type ) && ( vec2.size() != 1 || vec2[0] != i ) ) )
4222  {
4223  cout << "traversal from verts to sides to verts failed for " << endl
4224  << "vertex " << i << " type " << CN::EntityTypeName( this_type ) << " dimension " << dim
4225  << endl;
4226  return MB_FAILURE;
4227  }
4228  }
4229  }
4230  }
4231 
4232  // CN::side_number
4233 
4234  // create vertices to use later
4235  double xyz[3] = { 0.0, 0.0, 0.0 };
4236  EntityHandle vertex_handles[8];
4237  for( int i = 0; i < 8; i++ )
4238  {
4239  result = MB->create_vertex( xyz, vertex_handles[i] );
4240  assert( result == MB_SUCCESS );
4241  }
4242  int side, sense, offset;
4243 
4244  EntityHandle this_entity;
4245 
4246  for( this_type = MBEDGE; this_type != MBKNIFE; this_type++ )
4247  {
4248 
4249  // skip remainder of the loop for MBPOLYGONS and POLYHEDRA, which don't follow
4250  // the standard canonical ordering
4251  if( this_type == MBPOLYGON || this_type == MBPOLYHEDRON ) continue;
4252 
4253  // make an entity of this type
4254  result = MB->create_element( this_type, vertex_handles, CN::VerticesPerEntity( this_type ), this_entity );
4255  if( MB_SUCCESS != result || 0 == this_entity )
4256  {
4257  cout << "failed to create entity of type " << CN::EntityTypeName( this_type ) << endl;
4258  return MB_FAILURE;
4259  }
4260 
4261  // now get the connectivity vector *
4262  const EntityHandle* entity_vertices;
4263  int num_verts;
4264  result = MB->get_connectivity( this_entity, entity_vertices, num_verts );
4265  if( MB_SUCCESS != result || num_verts != CN::VerticesPerEntity( this_type ) )
4266  {
4267  cout << "failed to get connectivity for entity type " << CN::EntityTypeName( this_type ) << endl;
4268  return MB_FAILURE;
4269  }
4270 
4271  // for each dimension
4272  for( int dim = 1; dim <= CN::Dimension( this_type ); dim++ )
4273  {
4274  // for each side of this dimension
4275  const CN::ConnMap& cm = CN::mConnectivityMap[this_type][dim - 1];
4276  int tmp_conn[moab::MAX_SUB_ENTITY_VERTICES];
4277 
4278  for( int side_no = 0; side_no < CN::NumSubEntities( this_type, dim ); side_no++ )
4279  {
4280 
4281  for( int j = 0; j < moab::MAX_SUB_ENTITY_VERTICES; j++ )
4282  tmp_conn[j] = cm.conn[side_no][j];
4283  int temp_result = CN::SideNumber( this_type, tmp_conn,
4284  CN::VerticesPerEntity( CN::SubEntityType( this_type, dim, side_no ) ),
4285  dim, side, sense, offset );
4286  if( 0 != temp_result )
4287  {
4288  cout << "call to CN::side_number failed with non-success result"
4289  << " for type " << CN::EntityTypeName( this_type ) << " dimension " << dim << " side no "
4290  << side_no << endl;
4291  return MB_FAILURE;
4292  }
4293 
4294  // side number should be the same as side_no, sense should be forward, offset should
4295  // be zero
4296  if( side != side_no || sense != 1 || offset != 0 )
4297  {
4298  cout << "call to CN::side_number failed for type " << CN::EntityTypeName( this_type )
4299  << " dimension " << dim << " side no " << side_no << endl
4300  << "side, sense, offset = " << side << " " << sense << " " << offset << endl;
4301  return MB_FAILURE;
4302  }
4303  }
4304  }
4305 
4306  // destroy the entity of this_type
4307  result = MB->delete_entities( &this_entity, 1 );
4308  if( MB_SUCCESS != result ) return result;
4309  }
4310 
4311  return MB_SUCCESS;
4312 }
4314 {
4315  ErrorCode rval;
4316  Core moab;
4317  Interface* mb = &moab;
4318 
4319  /* Create faces of a wedge: */
4320  /*
4321  4
4322  /|\
4323  / | \
4324  / | \
4325  / 2 \
4326  3.../.\...5
4327  | / \ |
4328  | / \ |
4329  |/ \| 6 // off vertex
4330  0_________1
4331  */
4332 
4333  const double coords[][3] = {
4334  { 0, 0, 0 }, { 2, 0, 0 }, { 1, 0, 1 }, { 0, 2, 0 }, { 2, 2, 0 }, { 1, 2, 1 }, { 3, 1, 0 },
4335  };
4336  EntityHandle verts[7];
4337  for( unsigned i = 0; i < 7; ++i )
4338  mb->create_vertex( coords[i], verts[i] );
4339 
4340  EntityHandle faces[6];
4341  EntityHandle tri[] = { verts[0], verts[1], verts[2] };
4342  EntityHandle tri2[] = { verts[3], verts[4], verts[5] };
4343  EntityHandle quad1[] = { verts[0], verts[1], verts[5], verts[3] };
4344  EntityHandle quad2[] = { verts[1], verts[5], verts[4], verts[2] };
4345  EntityHandle quad3[] = { verts[2], verts[4], verts[3], verts[0] };
4346  rval = mb->create_element( MBTRI, tri, 3, faces[0] );MB_CHK_ERR( rval );
4347  rval = mb->create_element( MBQUAD, quad1, 4, faces[1] );MB_CHK_ERR( rval );
4348  rval = mb->create_element( MBQUAD, quad2, 4, faces[2] );MB_CHK_ERR( rval );
4349  rval = mb->create_element( MBQUAD, quad3, 4, faces[3] );MB_CHK_ERR( rval );
4350  rval = mb->create_element( MBTRI, tri2, 3, faces[4] );MB_CHK_ERR( rval );
4351 
4352  EntityHandle prism;
4353  rval = mb->create_element( MBPRISM, verts, 6, prism );MB_CHK_ERR( rval );
4354 
4355  /*
4356  * side_number(const EntityHandle parent,
4357  const EntityHandle child,
4358  int &side_number,
4359  int &sense,
4360  int &offset)
4361  */
4362  int side_n, sen, ofs;
4363  rval = mb->side_number( prism, faces[0], side_n, sen, ofs );MB_CHK_ERR( rval );
4364  CHECK_EQUAL( side_n, 3 );
4365  CHECK_EQUAL( sen, -1 );
4366  CHECK_EQUAL( ofs, 0 );
4367 
4368  // this diagonal should not be on the prism (not an edge of the prism)
4369  EntityHandle diagonal1;
4370  EntityHandle diag[] = { verts[2], verts[3] };
4371  rval = mb->create_element( MBEDGE, diag, 2, diagonal1 );MB_CHK_ERR( rval );
4372  rval = mb->side_number( prism, diagonal1, side_n, sen, ofs );
4373  // expected fail
4374  if( rval != MB_FAILURE ) return MB_FAILURE;
4375 
4376  // create another triangle, connected to the prism, but not on the side
4377  EntityHandle tri3[] = { verts[3], verts[4], verts[6] };
4378  rval = mb->create_element( MBTRI, tri3, 3, faces[5] );MB_CHK_ERR( rval );
4379  rval = mb->side_number( prism, faces[5], side_n, sen, ofs );
4380  // expected fail
4381  if( rval != MB_FAILURE ) return MB_FAILURE;
4382 
4383  return MB_SUCCESS;
4384 }
4385 
4387 {
4388  Core moab;
4389  Interface* mb = &moab;
4390 
4391  // test polygon and polyhedron representation
4392  // create a couple of polygons; vertices first
4393  const double vert_pos[48] = { -1, 0, 0, 1, 0, 0, 2, 0, 0, 2, 1, 0, 1, 1, 0, 0,
4394  2, 0, -1, 1, 0, -2, 1, 0, -2, 0, 0, -2, -1, 0, -1, -1,
4395  0, -1, -2, 0, 1, -2, 0, 1, -1, 0, 2, -1, 0, 1.5, .5, 1 };
4396 
4397  EntityHandle verts[16];
4398  ErrorCode result;
4399  int i;
4400  for( i = 0; i < 16; i++ )
4401  {
4402  result = mb->create_vertex( &vert_pos[3 * i], verts[i] );
4403  if( MB_SUCCESS != result )
4404  {
4405  std::cout << "Failed to create vertex " << i << " in mb_poly_test." << std::endl;
4406  return result;
4407  }
4408  }
4409 
4410  // then polygons
4411  const int connect_idx[] = { 1, 2, 5, 6, 7, 2, 3, 4, 5, 5, 4, 6, 7, 6, 8, 0, 1, 7, 8, 0, 1, 2, 3, 14,
4412  13, 12, 11, 10, 9, 0, 9, 10, 11, 12, 13, 14, 3, 4, 6, 8, 2, 3, 15, 5, 3, 4, 5, 15 };
4413 
4414  int num_connect_idx[] = { 5, 4, 3, 3, 4, 10, 11, 4, 4 };
4415 
4416  EntityHandle polygons[9], temp_connect[12];
4417  int idx = 0, nump = 0;
4418  ErrorCode tmp_result;
4419  while( nump < 9 )
4420  {
4421  for( i = 0; i < num_connect_idx[nump]; i++ )
4422  temp_connect[i] = verts[connect_idx[idx + i]];
4423 
4424  tmp_result = mb->create_element( MBPOLYGON, temp_connect, num_connect_idx[nump], polygons[nump] );
4425  if( MB_SUCCESS != tmp_result )
4426  {
4427  std::cout << "mb_poly_test: create_element failed for polygon " << i << "." << std::endl;
4428  result = tmp_result;
4429  nump++;
4430  continue;
4431  }
4432 
4433  idx += num_connect_idx[nump];
4434  nump++;
4435  }
4436 
4437  if( MB_SUCCESS != result ) return result;
4438 
4439  // ok, made 'em; now get all the vertices and make sure they're the same
4440  const EntityHandle* connect;
4441  int num_connect;
4442  idx = 0;
4443  int j;
4444  for( i = 0; i < 9; i++ )
4445  {
4446  tmp_result = mb->get_connectivity( polygons[i], connect, num_connect );
4447  if( MB_SUCCESS != tmp_result || num_connect != num_connect_idx[i] )
4448  {
4449  std::cout << "mb_poly_test: get_connectivity test failed for polygon " << i << "." << std::endl;
4450  result = ( tmp_result != MB_SUCCESS ? tmp_result : MB_FAILURE );
4451  continue;
4452  }
4453 
4454  for( j = 0; j < num_connect; j++ )
4455  {
4456  if( connect[j] != verts[connect_idx[idx + j]] )
4457  {
4458  std::cout << "mb_poly_test: get_connectivity test returned wrong vertices for polygon " << i << "."
4459  << std::endl;
4460  result = MB_FAILURE;
4461  continue;
4462  }
4463  }
4464 
4465  idx += num_connect;
4466  }
4467 
4468  if( MB_SUCCESS != result ) return result;
4469 
4470  // check a different way, with ranges
4471  Range vert_range, poly_range;
4472  for( i = 0; i < 9; i++ )
4473  poly_range.insert( polygons[i] );
4474  result = mb->get_adjacencies( poly_range, 0, false, vert_range, Interface::UNION );
4475  if( MB_SUCCESS != result )
4476  {
4477  std::cout << "mb_poly_test: get_adjacencies failed for polygon " << i << "." << std::endl;
4478  return result;
4479  }
4480 
4481  else if( vert_range.size() != 16 )
4482  {
4483  std::cout << "mb_poly_test: get_adjacencies returned wrong # of vertices for polygon " << i << "." << std::endl;
4484  return MB_FAILURE;
4485  }
4486 
4487  // make a couple polyhedra
4488  EntityHandle polyhedra[2];
4489  result = mb->create_element( MBPOLYHEDRON, polygons, 7, polyhedra[0] );
4490  if( MB_SUCCESS != result )
4491  {
4492  std::cout << "mb_poly_test: create_element failed for polyhedron 1." << std::endl;
4493  return result;
4494  }
4495 
4496  temp_connect[0] = polygons[1];
4497  temp_connect[1] = polygons[7];
4498  temp_connect[2] = polygons[8];
4499  result = mb->create_element( MBPOLYHEDRON, temp_connect, 3, polyhedra[1] );
4500  if( MB_SUCCESS != result )
4501  {
4502  std::cout << "mb_poly_test: create_element failed for polyhedron 2." << std::endl;
4503  return result;
4504  }
4505 
4506  // now look for vertices common to both
4507  std::vector< EntityHandle > temp_verts;
4508  result = mb->get_adjacencies( polyhedra, 2, 0, false, temp_verts );
4509  if( MB_SUCCESS != result )
4510  {
4511  std::cout << "mb_poly_test: get_adjacencies failed for polyhedra." << std::endl;
4512  return result;
4513  }
4514 
4515  if( 4 != temp_verts.size() )
4516  {
4517  std::cout << "mb_poly_test: get_adjacencies for polyhedra returned " << temp_verts.size()
4518  << " vertices, should be 4." << std::endl;
4519  return MB_FAILURE;
4520  }
4521 
4522  // ok, we're probably fine
4523  return MB_SUCCESS;
4524 }
4525 
4527 {
4528  Core moab;
4529  Interface* gMB = &moab;
4530  MeshTopoUtil mtu( gMB );
4531 
4532  // construct a four-hex mesh for testing purposes
4533  double grid_vert_pos[] = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 2.0, 1.0, 0.0,
4534  0.0, 2.0, 0.0, 1.0, 2.0, 0.0, 2.0, 2.0, 0.0,
4535  //
4536  0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 2.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0,
4537  0.0, 2.0, 1.0, 1.0, 2.0, 1.0, 2.0, 2.0, 1.0 };
4538 
4539  EntityHandle grid_verts[18], grid_elems[4];
4540  ErrorCode result;
4541 #define RR \
4542  if( result != MB_SUCCESS ) return result
4543  int init_edges, init_faces;
4544  result = gMB->get_number_entities_by_dimension( 0, 1, init_edges );RR;
4545  result = gMB->get_number_entities_by_dimension( 0, 2, init_faces );RR;
4546 
4547  // make vertices
4548  for( int i = 0; i < 18; i++ )
4549  {
4550  result = gMB->create_vertex( &grid_vert_pos[3 * i], grid_verts[i] );RR;
4551  }
4552 
4553  // make hexes
4554  int numv = 3, numv_sq = 9;
4555 #define VINDEX( i, j, k ) ( ( i ) + ( (j)*numv ) + ( (k)*numv_sq ) )
4556  EntityHandle connect[8];
4557  for( int j = 0; j < 2; j++ )
4558  {
4559  for( int i = 0; i < 2; i++ )
4560  {
4561  int vijk = VINDEX( i, j, 0 );
4562  connect[0] = grid_verts[vijk];
4563  connect[1] = grid_verts[vijk + 1];
4564  connect[2] = grid_verts[vijk + 1 + numv];
4565  connect[3] = grid_verts[vijk + numv];
4566  connect[4] = grid_verts[vijk + numv * numv];
4567  connect[5] = grid_verts[vijk + 1 + numv * numv];
4568  connect[6] = grid_verts[vijk + 1 + numv + numv * numv];
4569  connect[7] = grid_verts[vijk + numv + numv * numv];
4570  result = gMB->create_element( MBHEX, connect, 8, grid_elems[2 * j + i] );RR;
4571  }
4572  }
4573 
4574  Range vert_range;
4575  std::copy( grid_verts, grid_verts + 18, range_inserter( vert_range ) );
4576 
4577  // generate aentities
4578  result = mtu.construct_aentities( vert_range );RR;
4579 
4580  int this_edges, this_faces;
4581  result = gMB->get_number_entities_by_dimension( 0, 1, this_edges );RR;
4582  result = gMB->get_number_entities_by_dimension( 0, 2, this_faces );RR;
4583 
4584  if( this_edges != init_edges + 33 || this_faces != init_faces + 20 )
4585  {
4586  std::cout << "Wrong number of edges or faces in mb_topo_util test." << std::endl;
4587  // return MB_FAILURE;
4588  }
4589 
4590  // get average position
4591  double pos[3];
4592  for( int j = 0; j < 2; j++ )
4593  {
4594  for( int i = 0; i < 2; i++ )
4595  {
4596  result = mtu.get_average_position( grid_elems[2 * j + i], pos );RR;
4597  if( pos[0] != .5 + i || pos[1] != .5 + j || pos[2] != .5 )
4598  {
4599  std::cout << "Wrong position at i = " << i << ", j = " << j << std::endl;
4600  result = MB_FAILURE;
4601  }
4602  }
4603  }
4604  RR;
4605 
4606  // get star faces
4607  Range all_hexes, middle_edge;
4608  std::copy( grid_elems, grid_elems + 4, range_inserter( all_hexes ) );
4609  // get the shared edge
4610  result = gMB->get_adjacencies( all_hexes, 1, false, middle_edge );
4611  if( MB_SUCCESS != result || 1 != middle_edge.size() )
4612  {
4613  std::cout << "Bad result getting single shared edge." << std::endl;
4614  return MB_FAILURE;
4615  }
4616 
4617  std::vector< EntityHandle > star_faces, star_hexes;
4618  bool bdy_edge;
4619  result = mtu.star_entities( *middle_edge.begin(), star_faces, bdy_edge, 0, &star_hexes );
4620  if( MB_SUCCESS != result || bdy_edge || star_faces.size() != 4 || star_hexes.size() != 4 )
4621  {
4622  std::cout << "Bad result from star_faces for non-bdy edge." << std::endl;
4623  return MB_FAILURE;
4624  }
4625 
4626  // now try for a different edge, which has to be on the bdy
4627  Range other_edges;
4628  all_hexes.clear();
4629  all_hexes.insert( grid_elems[0] );
4630  result = gMB->get_adjacencies( all_hexes, 1, false, other_edges );RR;
4631  other_edges.erase( *middle_edge.begin() );
4632  if( 11 != other_edges.size() )
4633  {
4634  std::cout << "Wrong number of edges in hex." << std::endl;
4635  return MB_FAILURE;
4636  }
4637  star_faces.clear();
4638  star_hexes.clear();
4639  result = mtu.star_entities( *other_edges.begin(), star_faces, bdy_edge, 0, &star_hexes );
4640  if( MB_SUCCESS != result || !bdy_edge || ( star_faces.size() != 2 && star_faces.size() != 3 ) ||
4641  ( star_hexes.size() != 1 && star_hexes.size() != 2 ) )
4642  {
4643  std::cout << "Bad result from star_faces for bdy edge." << std::endl;
4644  return MB_FAILURE;
4645  }
4646 
4647  return MB_SUCCESS;
4648 }
4649 
4651 {
4652  Core moab;
4653  Interface* gMB = &moab;
4654  MeshTopoUtil mtu( gMB );
4655 
4656  // construct a four-hex mesh for testing purposes
4657  double grid_vert_pos[] = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 2.0, 1.0, 0.0,
4658  0.0, 2.0, 0.0, 1.0, 2.0, 0.0, 2.0, 2.0, 0.0,
4659  //
4660  0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 2.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0,
4661  0.0, 2.0, 1.0, 1.0, 2.0, 1.0, 2.0, 2.0, 1.0,
4662  //
4663  0.0, 0.0, 2.0, 1.0, 0.0, 2.0, 2.0, 0.0, 2.0, 0.0, 1.0, 2.0, 1.0, 1.0, 2.0, 2.0, 1.0, 2.0,
4664  0.0, 2.0, 2.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0 };
4665 
4666  EntityHandle grid_verts[27], grid_elems[8];
4667  ErrorCode result;
4668 #define RR \
4669  if( result != MB_SUCCESS ) return result
4670  int init_edges, init_faces, init_regions;
4671  result = gMB->get_number_entities_by_dimension( 0, 1, init_edges );RR;
4672  result = gMB->get_number_entities_by_dimension( 0, 2, init_faces );RR;
4673  result = gMB->get_number_entities_by_dimension( 0, 3, init_regions );RR;
4674 
4675  // make vertices
4676  for( int i = 0; i < 27; i++ )
4677  {
4678  result = gMB->create_vertex( &grid_vert_pos[3 * i], grid_verts[i] );RR;
4679  }
4680 
4681  // make hexes
4682  int numv = 3, numv_sq = 9;
4683 #define VINDEX( i, j, k ) ( ( i ) + ( (j)*numv ) + ( (k)*numv_sq ) )
4684  EntityHandle connect[8];
4685  for( int k = 0; k < 2; k++ )
4686  {
4687  for( int j = 0; j < 2; j++ )
4688  {
4689  for( int i = 0; i < 2; i++ )
4690  {
4691  int vijk = VINDEX( i, j, k );
4692  connect[0] = grid_verts[vijk];
4693  connect[1] = grid_verts[vijk + 1];
4694  connect[2] = grid_verts[vijk + 1 + numv];
4695  connect[3] = grid_verts[vijk + numv];
4696  connect[4] = grid_verts[vijk + numv * numv];
4697  connect[5] = grid_verts[vijk + 1 + numv * numv];
4698  connect[6] = grid_verts[vijk + 1 + numv + numv * numv];
4699  connect[7] = grid_verts[vijk + numv + numv * numv];
4700  result = gMB->create_element( MBHEX, connect, 8, grid_elems[4 * k + 2 * j + i] );RR;
4701  }
4702  }
4703  }
4704 
4705  Range vert_range;
4706  std::copy( grid_verts, grid_verts + 27, range_inserter( vert_range ) );
4707 
4708  // generate aentities
4709  result = mtu.construct_aentities( vert_range );RR;
4710 
4711  int this_edges, this_faces;
4712  result = gMB->get_number_entities_by_dimension( 0, 1, this_edges );RR;
4713  result = gMB->get_number_entities_by_dimension( 0, 2, this_faces );RR;
4714 
4715  if( this_edges != init_edges + 54 || this_faces != init_faces + 36 )
4716  {
4717  std::cout << "Wrong number of edges or faces in mb_topo_util test." << std::endl;
4718  return MB_FAILURE;
4719  }
4720 
4721  // split the faces between the 2 layers
4722  // first get the faces
4723  Range split_faces, tmp_ents, tmp_faces;
4724  for( int i = 0; i < 4; i++ )
4725  {
4726  tmp_ents.clear();
4727  tmp_ents.insert( grid_elems[i] );
4728  tmp_ents.insert( grid_elems[i + 4] );
4729  tmp_faces.clear();
4730  result = gMB->get_adjacencies( tmp_ents, 2, false, tmp_faces );
4731  if( MB_SUCCESS != result || tmp_faces.size() != 1 )
4732  {
4733  std::cout << "mb_split_test failed to get shared quad." << std::endl;
4734  return MB_FAILURE;
4735  }
4736  split_faces.insert( *tmp_faces.begin() );
4737  }
4738 
4739  Range new_faces, new_regions;
4740 
4741  // NOTE: passing in non-NULL pointer for new_regions requests that region between the
4742  // split entities be filled with an element; in this case, since we're splitting faces,
4743  // the new entities are polyhedra
4744  result = mtu.split_entities_manifold( split_faces, new_faces, &new_regions );
4745  if( MB_SUCCESS != result || new_faces.size() != 4 || new_regions.size() != 4 )
4746  {
4747  std::cout << "mb_split_test failed to split quads." << std::endl;
4748  return MB_FAILURE;
4749  }
4750 
4751  int this_regions;
4752  result = gMB->get_number_entities_by_dimension( 0, 1, this_edges );RR;
4753  result = gMB->get_number_entities_by_dimension( 0, 2, this_faces );RR;
4754  result = gMB->get_number_entities_by_dimension( 0, 3, this_regions );RR;
4755 
4756  if( this_edges != init_edges + 54 || this_faces != init_faces + 40 || this_regions != init_regions + 12 )
4757  {
4758  std::cout << "Wrong number of edges or faces or regions after splitting in mb_topo_util test." << std::endl;
4759  return MB_FAILURE;
4760  }
4761 
4762  return MB_SUCCESS;
4763 }
4764 
4766 {
4767  ErrorCode rval;
4768  SequenceManager sequences;
4769  RangeSeqIntersectIter iter( &sequences );
4770  Range range;
4771 
4772  // create some entity sequences
4773  EntitySequence *ts1, *ts2, *ts3, *qs1;
4774  EntityHandle th1, th2, th3, qh1;
4775  const int nt1 = 100, nt2 = 10, nt3 = 1, nq1 = 20;
4776  rval = sequences.create_entity_sequence( MBTRI, nt1, 3, 5, th1, ts1, -1 );
4777  if( MB_SUCCESS != rval ) return rval;
4778  rval = sequences.create_entity_sequence( MBTRI, nt2, 6, 0, th2, ts2, -1 );
4779  if( MB_SUCCESS != rval ) return rval;
4780  rval = sequences.create_entity_sequence( MBTRI, nt3, 3, MB_END_ID, th3, ts3, -1 );
4781  if( MB_SUCCESS != rval ) return rval;
4782  rval = sequences.create_entity_sequence( MBQUAD, nq1, 4, 0, qh1, qs1, -1 );
4783  if( MB_SUCCESS != rval ) return rval;
4784 
4785  // we're going to assume this below, so verify it now
4786  if( th1 > th2 || th2 > th3 || th3 > qh1 ) return MB_FAILURE;
4787 
4788  // construct an Range containing all valid handles;
4789  range.clear();
4790  range.insert( ts1->start_handle(), ts1->end_handle() );
4791  range.insert( ts2->start_handle(), ts2->end_handle() );
4792  range.insert( ts3->start_handle(), ts3->end_handle() );
4793  range.insert( qs1->start_handle(), qs1->end_handle() );
4794 
4795  // iterate over all and check results
4796 
4797  rval = iter.init( range.begin(), range.end() );
4798  if( MB_SUCCESS != rval ) return rval;
4799  if( ts1 != iter.get_sequence() ) return MB_FAILURE;
4800  if( iter.get_start_handle() != ts1->start_handle() ) return MB_FAILURE;
4801  if( iter.get_end_handle() != ts1->end_handle() ) return MB_FAILURE;
4802 
4803  rval = iter.step();
4804  if( MB_SUCCESS != rval ) return rval;
4805  if( ts2 != iter.get_sequence() ) return MB_FAILURE;
4806  if( iter.get_start_handle() != ts2->start_handle() ) return MB_FAILURE;
4807  if( iter.get_end_handle() != ts2->end_handle() ) return MB_FAILURE;
4808 
4809  rval = iter.step();
4810  if( MB_SUCCESS != rval ) return rval;
4811  if( ts3 != iter.get_sequence() ) return MB_FAILURE;
4812  if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
4813  if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
4814 
4815  rval = iter.step();
4816  if( MB_SUCCESS != rval ) return rval;
4817  if( qs1 != iter.get_sequence() ) return MB_FAILURE;
4818  if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
4819  if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
4820 
4821  if( !iter.is_at_end() ) return MB_FAILURE;
4822  rval = iter.step();
4823  if( MB_FAILURE != rval ) return MB_FAILURE;
4824 
4825  // iterate over just the quads
4826 
4827  rval = iter.init( range.lower_bound( MBQUAD ), range.end() );
4828  if( MB_SUCCESS != rval ) return rval;
4829  if( qs1 != iter.get_sequence() ) return MB_FAILURE;
4830  if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
4831  if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
4832 
4833  if( !iter.is_at_end() ) return MB_FAILURE;
4834  rval = iter.step();
4835  if( MB_FAILURE != rval ) return MB_FAILURE;
4836 
4837  // iterate starting one past the beginning of the
4838  // triangles and stopping one before the end. The last
4839  // sequence contains only one tri, so should stop and end
4840  // of second-to-last sequence
4841 
4842  rval = iter.init( ++( range.begin() ), --( range.lower_bound( MBQUAD ) ) );
4843  if( MB_SUCCESS != rval ) return rval;
4844  if( ts1 != iter.get_sequence() ) return MB_FAILURE;
4845  if( iter.get_start_handle() != ts1->start_handle() + 1 ) return MB_FAILURE;
4846  if( iter.get_end_handle() != ts1->end_handle() ) return MB_FAILURE;
4847 
4848  rval = iter.step();
4849  if( MB_SUCCESS != rval ) return rval;
4850  if( ts2 != iter.get_sequence() ) return MB_FAILURE;
4851  if( iter.get_start_handle() != ts2->start_handle() ) return MB_FAILURE;
4852  if( iter.get_end_handle() != ts2->end_handle() ) return MB_FAILURE;
4853 
4854  if( !iter.is_at_end() ) return MB_FAILURE;
4855  rval = iter.step();
4856  if( MB_FAILURE != rval ) return MB_FAILURE;
4857 
4858  // Iterate over the quad sequence, starting two past the
4859  // beginning and stopping one before the end
4860 
4861  rval = iter.init( ++( range.lower_bound( MBQUAD ) ), --( range.end() ) );
4862  if( MB_SUCCESS != rval ) return rval;
4863  if( qs1 != iter.get_sequence() ) return MB_FAILURE;
4864  if( iter.get_start_handle() != qs1->start_handle() + 1 ) return MB_FAILURE;
4865  if( iter.get_end_handle() != qs1->end_handle() - 1 ) return MB_FAILURE;
4866 
4867  if( !iter.is_at_end() ) return MB_FAILURE;
4868  rval = iter.step();
4869  if( MB_FAILURE != rval ) return MB_FAILURE;
4870 
4871  // Iterate over two subsets of the quad sequence
4872 
4873  Range quads = range.subset_by_type( MBQUAD );
4874  EntityHandle removed = qs1->start_handle() + nq1 / 2;
4875  if( quads.erase( removed ) == quads.end() ) return MB_FAILURE;
4876 
4877  rval = iter.init( quads.begin(), quads.end() );
4878  if( MB_SUCCESS != rval ) return rval;
4879  if( qs1 != iter.get_sequence() ) return MB_FAILURE;
4880  if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
4881  if( iter.get_end_handle() != removed - 1 ) return MB_FAILURE;
4882 
4883  rval = iter.step();
4884  if( MB_SUCCESS != rval ) return rval;
4885  if( qs1 != iter.get_sequence() ) return MB_FAILURE;
4886  if( iter.get_start_handle() != removed + 1 ) return MB_FAILURE;
4887  if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
4888 
4889  if( !iter.is_at_end() ) return MB_FAILURE;
4890  rval = iter.step();
4891  if( MB_FAILURE != rval ) return MB_FAILURE;
4892 
4893  // Iterate over everything, including a bunch of
4894  // invalid handles
4895 
4896  Range big;
4897  int junk;
4898  EntityHandle last = CREATE_HANDLE( MBQUAD + 1, 0, junk );
4899  big.insert( ts1->start_handle() - 1, last );
4900 
4901  // first some invalid handles in the beginning of the range
4902  rval = iter.init( big.begin(), big.end() );
4903  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
4904  if( NULL != iter.get_sequence() ) return MB_FAILURE;
4905  if( iter.get_start_handle() != *big.begin() ) return MB_FAILURE;
4906  if( iter.get_end_handle() != ts1->start_handle() - 1 ) return MB_FAILURE;
4907 
4908  // next the first triangle sequence
4909  rval = iter.step();
4910  if( MB_SUCCESS != rval ) return rval;
4911  if( ts1 != iter.get_sequence() ) return MB_FAILURE;
4912  if( iter.get_start_handle() != ts1->start_handle() ) return MB_FAILURE;
4913  if( iter.get_end_handle() != ts1->end_handle() ) return MB_FAILURE;
4914 
4915  // next the the invalid handles between the first two tri sequences
4916  if( ts1->end_handle() + 1 != ts2->start_handle() )
4917  {
4918  rval = iter.step();
4919  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
4920  if( NULL != iter.get_sequence() ) return MB_FAILURE;
4921  if( iter.get_start_handle() != ts1->end_handle() + 1 ) return MB_FAILURE;
4922  if( iter.get_end_handle() != ts2->start_handle() - 1 ) return MB_FAILURE;
4923  }
4924 
4925  // next the second triangle sequence
4926  rval = iter.step();
4927  if( MB_SUCCESS != rval ) return rval;
4928  if( ts2 != iter.get_sequence() ) return MB_FAILURE;
4929  if( iter.get_start_handle() != ts2->start_handle() ) return MB_FAILURE;
4930  if( iter.get_end_handle() != ts2->end_handle() ) return MB_FAILURE;
4931 
4932  // next the the invalid handles between the 2nd and 3rd tri sequences
4933  if( ts2->end_handle() + 1 != ts3->start_handle() )
4934  {
4935  rval = iter.step();
4936  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
4937  if( NULL != iter.get_sequence() ) return MB_FAILURE;
4938  if( iter.get_start_handle() != ts2->end_handle() + 1 ) return MB_FAILURE;
4939  if( iter.get_end_handle() != ts3->start_handle() - 1 ) return MB_FAILURE;
4940  }
4941 
4942  // next the third triangle sequence
4943  rval = iter.step();
4944  if( MB_SUCCESS != rval ) return rval;
4945  if( ts3 != iter.get_sequence() ) return MB_FAILURE;
4946  if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
4947  if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
4948 
4949  // third tri sequence contains the MAX tri handle, so no more
4950  // invalid triangles.
4951  // next 1 invalid quad at the before MB_START_ID
4952  if( ts3->end_handle() + 1 != qs1->start_handle() )
4953  {
4954  rval = iter.step();
4955  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
4956  if( NULL != iter.get_sequence() ) return MB_FAILURE;
4957  if( iter.get_start_handle() != ts3->end_handle() + 1 ) return MB_FAILURE;
4958  if( iter.get_end_handle() != qs1->start_handle() - 1 ) return MB_FAILURE;
4959  }
4960 
4961  // next the quad sequence
4962  rval = iter.step();
4963  if( MB_SUCCESS != rval ) return rval;
4964  if( qs1 != iter.get_sequence() ) return MB_FAILURE;
4965  if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
4966  if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
4967 
4968  // next remaining invalid quad handles in the range
4969  rval = iter.step();
4970  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
4971  if( 0 != iter.get_sequence() ) return MB_FAILURE;
4972  if( iter.get_start_handle() != qs1->end_handle() + 1 ) return MB_FAILURE;
4973  if( iter.get_end_handle() != last - 1 ) return MB_FAILURE;
4974 
4975  // next invalid entity after the last quad in the range
4976  rval = iter.step();
4977  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
4978  if( 0 != iter.get_sequence() ) return MB_FAILURE;
4979  if( iter.get_start_handle() != last ) return MB_FAILURE;
4980  if( iter.get_end_handle() != last ) return MB_FAILURE;
4981 
4982  // now at the end
4983  if( !iter.is_at_end() ) return MB_FAILURE;
4984  rval = iter.step();
4985  if( MB_FAILURE != rval ) return MB_FAILURE;
4986 
4987  // Create some holes
4988  Error eh;
4989  EntityHandle ts1s = ts1->start_handle();
4990  EntityHandle dead1 = ts1->start_handle() + 1;
4991  EntityHandle dead2 = ts1->start_handle() + 2;
4992  EntityHandle ts1e = ts1->end_handle();
4993  EntityHandle dead3 = ts2->start_handle();
4994  EntityHandle dead4 = ts2->end_handle();
4995  EntityHandle qs1s = qs1->start_handle();
4996  EntityHandle qs1e = qs1->end_handle();
4997  EntityHandle dead5 = qs1->start_handle() + nq1 / 2;
4998  EntityHandle dead6 = dead5 + 1;
4999  rval = sequences.delete_entity( &eh, dead1 );
5000  if( MB_SUCCESS != rval ) return rval;
5001  rval = sequences.delete_entity( &eh, dead2 );
5002  if( MB_SUCCESS != rval ) return rval;
5003  rval = sequences.delete_entity( &eh, dead3 );
5004  if( MB_SUCCESS != rval ) return rval;
5005  rval = sequences.delete_entity( &eh, dead4 );
5006  if( MB_SUCCESS != rval ) return rval;
5007  rval = sequences.delete_entity( &eh, dead5 );
5008  if( MB_SUCCESS != rval ) return rval;
5009  rval = sequences.delete_entity( &eh, dead6 );
5010  if( MB_SUCCESS != rval ) return rval;
5011 
5012  // Iterate over sequences w/out removing deleted entities
5013  // from range.
5014 
5015  // first sequence should have one valid handle at beginning
5016  rval = iter.init( range.begin(), range.end() );
5017  if( MB_SUCCESS != rval ) return rval;
5018  if( 0 == iter.get_sequence() || ts1s != iter.get_sequence()->start_handle() ||
5019  dead1 - 1 != iter.get_sequence()->end_handle() )
5020  return MB_FAILURE;
5021  if( iter.get_start_handle() != ts1->start_handle() ) return MB_FAILURE;
5022  if( iter.get_end_handle() != dead1 - 1 ) return MB_FAILURE;
5023 
5024  // next two invalid handles in sequence in first sequence
5025  rval = iter.step();
5026  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
5027  if( 0 != iter.get_sequence() ) return MB_FAILURE;
5028  if( iter.get_start_handle() != dead1 ) return MB_FAILURE;
5029  if( iter.get_end_handle() != dead2 ) return MB_FAILURE;
5030 
5031  // next the remainder of the fist sequence
5032  rval = iter.step();
5033  if( MB_SUCCESS != rval ) return rval;
5034  if( 0 == iter.get_sequence() || dead2 + 1 != iter.get_sequence()->start_handle() ||
5035  ts1e != iter.get_sequence()->end_handle() )
5036  return MB_FAILURE;
5037  if( iter.get_start_handle() != dead2 + 1 ) return MB_FAILURE;
5038  if( iter.get_end_handle() != ts1e ) return MB_FAILURE;
5039 
5040  // next an invalid handle at the start of the second sequence
5041  rval = iter.step();
5042  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
5043  if( 0 != iter.get_sequence() ) return MB_FAILURE;
5044  if( iter.get_start_handle() != dead3 ) return MB_FAILURE;
5045  if( iter.get_end_handle() != dead3 ) return MB_FAILURE;
5046 
5047  // next the second sequence up to the invalid handle at the end
5048  rval = iter.step();
5049  if( MB_SUCCESS != rval ) return rval;
5050  if( 0 == iter.get_sequence() || dead3 + 1 != iter.get_sequence()->start_handle() ||
5051  dead4 - 1 != iter.get_sequence()->end_handle() )
5052  return MB_FAILURE;
5053  if( ts2 != iter.get_sequence() ) return MB_FAILURE;
5054  if( iter.get_start_handle() != dead3 + 1 ) return MB_FAILURE;
5055  if( iter.get_end_handle() != dead4 - 1 ) return MB_FAILURE;
5056 
5057  // next invaild handle at the end of the second sequence
5058  rval = iter.step();
5059  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
5060  if( 0 != iter.get_sequence() ) return MB_FAILURE;
5061  if( iter.get_start_handle() != dead4 ) return MB_FAILURE;
5062  if( iter.get_end_handle() != dead4 ) return MB_FAILURE;
5063 
5064  // next the third sequence
5065  rval = iter.step();
5066  if( MB_SUCCESS != rval ) return rval;
5067  if( ts3 != iter.get_sequence() ) return MB_FAILURE;
5068  if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
5069  if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
5070 
5071  // next the quad sequence up to the invalid handle in the middle
5072  rval = iter.step();
5073  if( MB_SUCCESS != rval ) return rval;
5074  if( 0 == iter.get_sequence() || qs1s != iter.get_sequence()->start_handle() ||
5075  dead5 - 1 != iter.get_sequence()->end_handle() )
5076  return MB_FAILURE;
5077  if( qs1 != iter.get_sequence() ) return MB_FAILURE;
5078  if( iter.get_start_handle() != qs1s ) return MB_FAILURE;
5079  if( iter.get_end_handle() != dead5 - 1 ) return MB_FAILURE;
5080 
5081  // next the two invalid handles in the middle
5082  rval = iter.step();
5083  if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
5084  if( 0 != iter.get_sequence() ) return MB_FAILURE;
5085  if( iter.get_start_handle() != dead5 ) return MB_FAILURE;
5086  if( iter.get_end_handle() != dead6 ) return MB_FAILURE;
5087 
5088  // next the remainder of the quad sequence
5089  rval = iter.step();
5090  if( MB_SUCCESS != rval ) return rval;
5091  if( 0 == iter.get_sequence() || dead6 + 1 != iter.get_sequence()->start_handle() ||
5092  qs1e != iter.get_sequence()->end_handle() )
5093  return MB_FAILURE;
5094  if( iter.get_start_handle() != dead6 + 1 ) return MB_FAILURE;
5095  if( iter.get_end_handle() != qs1e ) return MB_FAILURE;
5096 
5097  // now at the end
5098  if( !iter.is_at_end() ) return MB_FAILURE;
5099  rval = iter.step();
5100  if( MB_FAILURE != rval ) return MB_FAILURE;
5101 
5102  // now remove the dead entities from the range and iterate again
5103 
5104  if( range.erase( dead1 ) == quads.end() ) return MB_FAILURE;
5105  if( range.erase( dead2 ) == quads.end() ) return MB_FAILURE;
5106  if( range.erase( dead3 ) == quads.end() ) return MB_FAILURE;
5107  if( range.erase( dead4 ) == quads.end() ) return MB_FAILURE;
5108  if( range.erase( dead5 ) == quads.end() ) return MB_FAILURE;
5109  if( range.erase( dead6 ) == quads.end() ) return MB_FAILURE;
5110 
5111  // first sequence should have one valid handle at beginning
5112  rval = iter.init( range.begin(), range.end() );
5113  if( MB_SUCCESS != rval ) return rval;
5114  if( 0 == iter.get_sequence() || ts1s != iter.get_sequence()->start_handle() ||
5115  dead1 - 1 != iter.get_sequence()->end_handle() )
5116  return MB_FAILURE;
5117  if( iter.get_start_handle() != ts1s ) return MB_FAILURE;
5118  if( iter.get_end_handle() != dead1 - 1 ) return MB_FAILURE;
5119 
5120  // next the remainder of the fist sequence after the hole
5121  rval = iter.step();
5122  if( MB_SUCCESS != rval ) return rval;
5123  if( 0 == iter.get_sequence() || dead2 + 1 != iter.get_sequence()->start_handle() ||
5124  ts1e != iter.get_sequence()->end_handle() )
5125  return MB_FAILURE;
5126  if( iter.get_start_handle() != dead2 + 1 ) return MB_FAILURE;
5127  if( iter.get_end_handle() != ts1e ) return MB_FAILURE;
5128 
5129  // next the second sequence between deleted start and end handles
5130  rval = iter.step();
5131  if( MB_SUCCESS != rval ) return rval;
5132  if( 0 == iter.get_sequence() || dead3 + 1 != iter.get_sequence()->start_handle() ||
5133  dead4 - 1 != iter.get_sequence()->end_handle() )
5134  return MB_FAILURE;
5135  if( iter.get_start_handle() != dead3 + 1 ) return MB_FAILURE;
5136  if( iter.get_end_handle() != dead4 - 1 ) return MB_FAILURE;
5137 
5138  // next the third sequence
5139  rval = iter.step();
5140  if( MB_SUCCESS != rval ) return rval;
5141  if( ts3 != iter.get_sequence() ) return MB_FAILURE;
5142  if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
5143  if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
5144 
5145  // next the quad sequence up to the hole in the middle
5146  rval = iter.step();
5147  if( MB_SUCCESS != rval ) return rval;
5148  if( 0 == iter.get_sequence() || qs1s != iter.get_sequence()->start_handle() ||
5149  dead5 - 1 != iter.get_sequence()->end_handle() )
5150  return MB_FAILURE;
5151  if( iter.get_start_handle() != qs1s ) return MB_FAILURE;
5152  if( iter.get_end_handle() != dead5 - 1 ) return MB_FAILURE;
5153 
5154  // next the remainder of the quad sequence after the hole
5155  rval = iter.step();
5156  if( MB_SUCCESS != rval ) return rval;
5157  if( 0 == iter.get_sequence() || dead6 + 1 != iter.get_sequence()->start_handle() ||
5158  qs1e != iter.get_sequence()->end_handle() )
5159  return MB_FAILURE;
5160  if( iter.get_start_handle() != dead6 + 1 ) return MB_FAILURE;
5161  if( iter.get_end_handle() != qs1e ) return MB_FAILURE;
5162 
5163  // now at the end
5164  if( !iter.is_at_end() ) return MB_FAILURE;
5165  rval = iter.step();
5166  if( MB_FAILURE != rval ) return MB_FAILURE;
5167 
5168  return MB_SUCCESS;
5169 }
5170 
5171 #define ASSERT_EQUAL( A, B ) \
5172  do \
5173  { \
5174  if( !_assert_equal( ( A ), ( B ), #A, #B, __LINE__ ) ) return MB_FAILURE; \
5175  } while( false )
5176 
5177 #define ASSERT_NOT_EQUAL( A, B ) \
5178  do \
5179  { \
5180  if( !_assert_not_equal( ( A ), ( B ), #A, #B, __LINE__ ) ) return MB_FAILURE; \
5181  } while( false )
5182 
5183 template < typename T1, typename T2 >
5184 bool _assert_equal( T1 a, T2 b, const char* as, const char* bs, int line )
5185 {
5186  if( a == b ) return true;
5187 
5188  std::cout << "Assertion failed at line " << line << std::endl
5189  << "\t" << as << " == " << bs << std::endl
5190  << "\t" << as << " = " << a << std::endl
5191  << "\t" << bs << " = " << b << std::endl;
5192  return false;
5193 }
5194 
5195 template < typename T1, typename T2 >
5196 bool _assert_not_equal( T1 a, T2 b, const char* as, const char* bs, int line )
5197 {
5198  if( a != b ) return true;
5199 
5200  std::cout << "Assertion failed at line " << line << std::endl
5201  << "\t" << as << " != " << bs << std::endl
5202  << "\t" << as << " = " << a << std::endl
5203  << "\t" << bs << " = " << b << std::endl;
5204  return false;
5205 }
5206 
5207 std::ostream& operator<<( std::ostream& s, Range::const_iterator i )
5208 {
5209  return s << *i;
5210 }
5211 
5213 {
5214  ErrorCode rval;
5215  Core moab;
5216  Interface* mbImpl = &moab;
5217 
5218  // make a couple polygons and a polyhedron
5219  double coords[3] = { 0, 1, 2 };
5220  EntityHandle verts[10], polygons[2], polyhedron;
5221 
5222  for( int i = 0; i < 10; i++ )
5223  {
5224  rval = mbImpl->create_vertex( coords, verts[i] );
5225  if( MB_SUCCESS != rval ) return rval;
5226  }
5227 
5228  for( int i = 0; i < 2; i++ )
5229  {
5230  rval = mbImpl->create_element( MBPOLYGON, verts, 5, polygons[i] );
5231  if( MB_SUCCESS != rval ) return rval;
5232  }
5233  rval = mbImpl->create_element( MBPOLYHEDRON, polygons, 2, polyhedron );
5234  if( MB_SUCCESS != rval ) return rval;
5235 
5236  // create the aentities
5237  Range dum_range;
5238  for( int dim = 0; dim < 3; dim++ )
5239  {
5240  dum_range.clear();
5241  rval = mbImpl->get_adjacencies( &polyhedron, 1, dim, true, dum_range );
5242  if( MB_SUCCESS != rval ) return rval;
5243  }
5244 
5245  // delete the polyhedron
5246  rval = mbImpl->delete_entities( &polyhedron, 1 );
5247  if( MB_SUCCESS != rval ) return rval;
5248 
5249  // check adjacencies
5250  return moab.check_adjacencies();
5251 }
5252 
5254 {
5255  ErrorCode rval;
5256  Core moab;
5257  Interface* mbImpl = &moab;
5258 
5259  // make a polyhedra in shape of a cube with a corner cut
5260 
5261  /*
5262  *
5263  * 7 ------------- 8
5264  * . | . |
5265  * . . | initial cube had 8 vertices; box [000 - 222]
5266  * 5 ------------- 6 | cut a triangle 123 on lower corner
5267  * | | | |
5268  * | | | faces of the polyhedra (pointing outward)
5269  * | | | | (123) (24653) (4 10 8 6)
5270  * 3 | | (9 10 4 2 1) (7 8 10 9) (5687)
5271  * \ | | | (1 3 5 7 9)
5272  * 9 - - -| - 10
5273  * \ . | .
5274  * 1, | .
5275  * (000) '2 ---- 4
5276  *
5277  */
5278  double coords[] = {
5279  0, 1, 0, // vertex 1
5280  1, 0, 0, // vertex 2
5281  0, 0, 1, // vertex 3
5282  2, 0, 0, 0, 0, 2, 2, 0, 2, // vertex 6
5283  0, 2, 2, 2, 2, 2, // vertex 8
5284  0, 2, 0, // vertex 9
5285  2, 2, 0 // vertex 9
5286 
5287  };
5288  EntityHandle verts[10], polygons[7], polyhedron;
5289 
5290  for( int i = 0; i < 10; i++ )
5291  {
5292  rval = mbImpl->create_vertex( &coords[3 * i], verts[i] );
5293  if( MB_SUCCESS != rval ) return rval;
5294  }
5295 
5296  EntityHandle connect[] = {
5297  1, 2, 3, // poly 1
5298  2, 4, 6, 5, 3, // poly 2
5299  4, 10, 8, 6, // polygon 3...
5300  9, 10, 4, 2, 1, 7, 8, 10, 9, 5, 6, 8, 7, 1, 3, 5, 7, 9 // polygon 7
5301  }; // we know the handles directly
5302 
5303  int num_verts[7] = { 3, 5, 4, 5, 4, 4, 5 };
5304  int start_indx[7];
5305  start_indx[0] = 0;
5306  for( int i = 0; i < 6; i++ )
5307  start_indx[i + 1] = start_indx[i] + num_verts[i];
5308  for( int j = 0; j < 7; j++ )
5309  {
5310  rval = mbImpl->create_element( MBPOLYGON, &connect[start_indx[j]], num_verts[j], polygons[j] );
5311  if( MB_SUCCESS != rval ) return rval;
5312  }
5313  rval = mbImpl->create_element( MBPOLYHEDRON, polygons, 7, polyhedron );
5314  if( MB_SUCCESS != rval ) return rval;
5315 
5316  // create the aentities
5317  Range dum_range;
5318  for( int dim = 0; dim < 3; dim++ )
5319  {
5320  dum_range.clear();
5321  rval = mbImpl->get_adjacencies( &polyhedron, 1, dim, true, dum_range, Interface::UNION );
5322  if( MB_SUCCESS != rval ) return rval;
5323  // std::cout << "\n dimension:" << dim << " " << dum_range.size() << " entities";
5324  }
5325  // std::cout << "\n";
5326  /*rval=mbImpl->write_mesh("polyhedra.vtk");
5327  if (MB_SUCCESS != rval)
5328  return rval;*/
5329  // delete the polyhedron
5330  rval = mbImpl->delete_entities( &polyhedron, 1 );
5331  if( MB_SUCCESS != rval ) return rval;
5332 
5333  // check adjacencies
5334  return moab.check_adjacencies();
5335 }
5336 
5338 {
5339  Core mb;
5340  unsigned long long init_total, total_with_elem, total_with_tag, total_with_tag_data;
5341  mb.estimated_memory_use( 0, 0, 0, &init_total );
5342 
5343  double coords[12] = { 1, 2, 0, 3, 4, 0, 5, 6, 0, 7, 8, 0 };
5344  EntityHandle verts[4];
5345  for( int i = 0; i < 4; ++i )
5346  if( MB_SUCCESS != mb.create_vertex( coords + 3 * i, verts[i] ) ) return MB_FAILURE;
5347 
5348  EntityHandle elem;
5349  mb.create_element( MBQUAD, verts, 4, elem );
5350 
5351  mb.estimated_memory_use( 0, 0, 0, &total_with_elem );
5352  if( total_with_elem <= init_total ) return MB_FAILURE;
5353 
5354  unsigned long long min, am;
5355  Range r;
5356  r.insert( elem );
5357  mb.estimated_memory_use( r, &min, &am );
5358  if( min != 4 * sizeof( EntityHandle ) ) return MB_FAILURE;
5359 
5360  r.clear();
5361  r.insert( verts[0] );
5362  r.insert( verts[1] );
5363  mb.estimated_memory_use( r, &min, &am );
5364  if( min != 6 * sizeof( double ) ) return MB_FAILURE;
5365 
5366  Tag tag;
5367  if( MB_SUCCESS != mb.tag_get_handle( "TMP_TAG", 1, MB_TYPE_INTEGER, tag, MB_TAG_SPARSE | MB_TAG_EXCL ) )
5368  return MB_FAILURE;
5369  mb.estimated_memory_use( r, &min, &am );
5370  if( min != 6 * sizeof( double ) ) return MB_FAILURE;
5371 
5372  mb.estimated_memory_use( 0, 0, 0, &total_with_tag );
5373  if( total_with_tag <= total_with_elem ) return MB_FAILURE;
5374 
5375  int tag_data[] = { 0xA, 0xB };
5376  if( MB_SUCCESS != mb.tag_set_data( tag, r, &tag_data ) ) return MB_FAILURE;
5377  mb.estimated_memory_use( r, &min, &am );
5378  if( min <= 6 * sizeof( double ) ) return MB_FAILURE;
5379 
5380  mb.estimated_memory_use( 0, 0, 0, &total_with_tag_data );
5381  if( total_with_tag_data <= total_with_tag ) return MB_FAILURE;
5382 
5383  return MB_SUCCESS;
5384 }
5385 
5386 ErrorCode mb_skin_curve_test_common( bool use_adj );
5387 
5389 {
5390  return mb_skin_curve_test_common( false );
5391 }
5392 
5394 {
5395  return mb_skin_curve_test_common( true );
5396 }
5397 
5398 ErrorCode mb_skin_surface_test_common( bool use_adj );
5399 
5401 {
5402  return mb_skin_surface_test_common( false );
5403 }
5404 
5406 {
5407  return mb_skin_surface_test_common( true );
5408 }
5409 
5410 ErrorCode mb_skin_volume_test_common( bool use_adj );
5411 
5413 {
5414  return mb_skin_volume_test_common( false );
5415 }
5416 
5418 {
5419  return mb_skin_volume_test_common( true );
5420 }
5421 
5423 {
5424  ErrorCode rval;
5425  Core moab;
5426  Interface* mb = &moab;
5427 
5428  std::vector< EntityHandle > verts;
5429  for( unsigned i = 0; i < 10; ++i )
5430  {
5431  double coords[] = { static_cast< double >( i ), 0, 0 };
5432  EntityHandle h;
5433  mb->create_vertex( coords, h );
5434  verts.push_back( h );
5435  }
5436  Range edges;
5437  for( unsigned i = 1; i < verts.size(); ++i )
5438  {
5439  EntityHandle conn[] = { verts[i - 1], verts[i] };
5440  EntityHandle h;
5441  mb->create_element( MBEDGE, conn, 2, h );
5442  edges.insert( h );
5443  }
5444 
5445  Range skin;
5446  Skinner tool( mb );
5447  rval = tool.find_skin( 0, edges, 0, skin, use_adj );
5448  if( MB_SUCCESS != rval )
5449  {
5450  std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
5451  return MB_FAILURE;
5452  }
5453  if( skin.size() != 2 )
5454  {
5455  std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
5456  return MB_FAILURE;
5457  }
5458 
5459  if( verts.front() > verts.back() ) std::swap( verts.front(), verts.back() );
5460  if( skin.front() != verts.front() || skin.back() != verts.back() )
5461  {
5462  std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
5463  return MB_FAILURE;
5464  }
5465 
5466  // now test again with only one edge
5467  EntityHandle edge = edges.front();
5468  Range range( edge, edge );
5469  skin.clear();
5470  rval = tool.find_skin( 0, range, 0, skin, use_adj );
5471  if( MB_SUCCESS != rval )
5472  {
5473  std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
5474  return MB_FAILURE;
5475  }
5476  if( skin.size() != 2 )
5477  {
5478  std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
5479  return MB_FAILURE;
5480  }
5481 
5482  Range verts2;
5483  mb->get_connectivity( &edge, 1, verts2 );
5484  if( skin.front() != verts2.front() || skin.back() != verts2.back() )
5485  {
5486  std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
5487  return MB_FAILURE;
5488  }
5489 
5490  return MB_SUCCESS;
5491 }
5492 
5494 {
5495  ErrorCode rval;
5496  Core moab;
5497  Interface* mb = &moab;
5498 
5499  /* Create 4 of 5 faces of a wedge: */
5500  /*
5501  4
5502  /|\
5503  / | \
5504  / | \
5505  / 2 \
5506  3.../.\...5
5507  | / \ |
5508  | / \ |
5509  |/ \|
5510  0_________1
5511  */
5512 
5513  const double coords[][3] = { { 0, 0, 0 }, { 2, 0, 0 }, { 1, 0, 1 }, { 0, 2, 0 }, { 2, 2, 0 }, { 1, 2, 1 } };
5514  EntityHandle verts[6];
5515  for( unsigned i = 0; i < 6; ++i )
5516  mb->create_vertex( coords[i], verts[i] );
5517 
5518  EntityHandle faces[4];
5519  EntityHandle tri[] = { verts[0], verts[1], verts[2] };
5520  EntityHandle quad1[] = { verts[0], verts[1], verts[5], verts[3] };
5521  EntityHandle quad2[] = { verts[1], verts[5], verts[4], verts[2] };
5522  EntityHandle quad3[] = { verts[2], verts[4], verts[3], verts[0] };
5523  mb->create_element( MBTRI, tri, 3, faces[0] );
5524  mb->create_element( MBQUAD, quad1, 4, faces[1] );
5525  mb->create_element( MBQUAD, quad2, 4, faces[2] );
5526  mb->create_element( MBQUAD, quad3, 4, faces[3] );
5527  Range source;
5528  std::copy( faces, faces + 4, range_inserter( source ) );
5529 
5530  // Now skin the mesh. The only missing face is the
5531  // back triangle (verts 3, 4, & 5) so the skin should
5532  // be the edges bordering that face.
5533 
5534  Range skin;
5535  Skinner tool( mb );
5536  rval = tool.find_skin( 0, source, 1, skin, use_adj );
5537  if( MB_SUCCESS != rval )
5538  {
5539  std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
5540  return MB_FAILURE;
5541  }
5542  if( skin.size() != 3 || !skin.all_of_type( MBEDGE ) )
5543  {
5544  std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
5545  return MB_FAILURE;
5546  }
5547 
5548  // Check each edge
5549  std::vector< EntityHandle > conn[3];
5550  rval = mb->get_connectivity( &skin.front(), 1, conn[0] );
5551  if( MB_SUCCESS != rval ) return rval;
5552  rval = mb->get_connectivity( &*++skin.begin(), 1, conn[1] );
5553  if( MB_SUCCESS != rval ) return rval;
5554  rval = mb->get_connectivity( &skin.back(), 1, conn[2] );
5555  if( MB_SUCCESS != rval ) return rval;
5556  for( int i = 0; i < 3; ++i )
5557  if( conn[i][0] > conn[i][1] ) std::swap( conn[i][0], conn[i][1] );
5558 
5559  for( int i = 0; i < 3; ++i )
5560  {
5561  EntityHandle s = verts[i + 3], e = verts[( i + 1 ) % 3 + 3];
5562  if( s > e ) std::swap( s, e );
5563  int j = 0;
5564  for( j = 0; j < 3; ++j )
5565  if( conn[j][0] == s && conn[j][1] == e ) break;
5566 
5567  if( j == 3 )
5568  {
5569  std::cerr << "Skin does not contain edge [" << s << "," << e << "] at " << __FILE__ ":" << __LINE__
5570  << std::endl;
5571  return MB_FAILURE;
5572  }
5573  }
5574 
5575  return MB_SUCCESS;
5576 }
5577 
5579 {
5580  ErrorCode rval;
5581  Core moab;
5582  Interface* mb = &moab;
5583 
5584  /* A 2 adjacent hexes hexes */
5585  /*
5586  9-----10----11
5587  / / /|
5588  / / / |
5589  6-----7-----8..5
5590  | . | . | /
5591  |. |. |/
5592  0-----1-----2
5593  */
5594 
5595  const double coords[][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 2, 0, 0 }, { 0, 1, 0 }, { 1, 1, 0 }, { 2, 1, 0 },
5596  { 0, 0, 1 }, { 1, 0, 1 }, { 2, 0, 1 }, { 0, 1, 1 }, { 1, 1, 1 }, { 2, 1, 1 } };
5597  EntityHandle verts[12];
5598  for( unsigned i = 0; i < 12; ++i )
5599  mb->create_vertex( coords[i], verts[i] );
5600 
5601  EntityHandle hex1c[] = { verts[0], verts[1], verts[4], verts[3], verts[6], verts[7], verts[10], verts[9] };
5602  EntityHandle hex2c[] = { verts[1], verts[2], verts[5], verts[4], verts[7], verts[8], verts[11], verts[10] };
5603  EntityHandle hex1, hex2;
5604  mb->create_element( MBHEX, hex1c, 8, hex1 );
5605  mb->create_element( MBHEX, hex2c, 8, hex2 );
5606  Range source;
5607  source.insert( hex1 );
5608  source.insert( hex2 );
5609 
5610  // get all quads and shared face
5611  Range tmp, all_faces;
5612  mb->get_adjacencies( source, 2, true, all_faces, Interface::UNION );
5613  mb->get_adjacencies( source, 2, true, tmp, Interface::INTERSECT );
5614  assert( tmp.size() == 1 );
5615  Range non_shared = subtract( all_faces, tmp );
5616 
5617  // Now skin the mesh.
5618 
5619  Range skin;
5620  Skinner tool( mb );
5621  rval = tool.find_skin( 0, source, 2, skin, use_adj );
5622  if( MB_SUCCESS != rval )
5623  {
5624  std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
5625  return MB_FAILURE;
5626  }
5627  if( skin != non_shared )
5628  {
5629  std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
5630  return MB_FAILURE;
5631  }
5632 
5633  return MB_SUCCESS;
5634 }
5635 
5637 {
5638  // make a 10x10x5 scd mesh
5639  Core moab;
5640  Interface* mb = &moab;
5641  ScdInterface* scdi;
5642  ErrorCode rval = mb->query_interface( scdi );
5643  if( MB_SUCCESS != rval ) return rval;
5644  HomCoord low( 0, 0, 0 ), high( 10, 10, 5 );
5645  ScdBox* this_box;
5646  rval = scdi->construct_box( low, high, NULL, 0, this_box );
5647  if( MB_SUCCESS != rval ) return rval;
5648 
5649  // now skin it with the structured and original method, and compare results
5650  Skinner tool( mb );
5651  Range ents( this_box->start_element(), this_box->start_element() + this_box->num_elements() - 1 ), scd_skin_ents,
5652  skin_ents;
5653  rval = tool.find_skin( 0, ents, false, scd_skin_ents, NULL, true, true, true );
5654  if( MB_SUCCESS != rval ) return rval;
5655 
5656  rval = tool.find_skin( 0, ents, false, skin_ents, NULL, true, true, false );
5657  if( MB_SUCCESS != rval ) return rval;
5658 
5659  // should be same number of entities
5660  if( scd_skin_ents.size() != skin_ents.size() ) return MB_FAILURE;
5661 
5662  skin_ents.clear();
5663  scd_skin_ents.clear();
5664 
5665  // now test getting faces and vertices, also with existing faces now
5666  rval = tool.find_skin( 0, ents, true, scd_skin_ents, NULL, true, true, true );
5667  if( MB_SUCCESS != rval ) return rval;
5668 
5669  rval = tool.find_skin( 0, ents, true, skin_ents, NULL, true, true, false );
5670  if( MB_SUCCESS != rval ) return rval;
5671 
5672  // again, should have same numbers
5673  if( skin_ents.subset_by_type( MBVERTEX ).size() != scd_skin_ents.subset_by_type( MBVERTEX ).size() )
5674  return MB_FAILURE;
5675 
5676  return MB_SUCCESS;
5677 }
5678 
5680 {
5681  Core moab;
5682  Interface* mb = &moab;
5683  ErrorCode error;
5684  const double coords[] = { 0, 0, 0, 1, 0, 0, 2, 0, 0, 2, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 2, 0, 1,
5685  2, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 2, 1, 0, 2, 2, 0, 2, 2, 1, 2, 1, 1, 2, 0, 1, 2 };
5686  const size_t num_vtx = sizeof( coords ) / sizeof( double ) / 3;
5687 
5688  const int conn[] = { 0, 1, 4, 5, 6, 7, 10, 11, 1, 2, 3, 4, 7, 8, 9, 10,
5689  6, 7, 10, 11, 12, 13, 16, 17, 7, 8, 9, 10, 13, 14, 15, 16 };
5690  const size_t num_elems = sizeof( conn ) / sizeof( int ) / 8;
5691 
5692  EntityHandle verts[num_vtx], cells[num_elems];
5693  for( size_t i = 0; i < num_vtx; ++i )
5694  {
5695  error = mb->create_vertex( coords + 3 * i, verts[i] );MB_CHK_ERR( error );
5696  }
5697 
5698  for( size_t i = 0; i < num_elems; ++i )
5699  {
5700  EntityHandle c[8];
5701  for( int j = 0; j < 8; j++ )
5702  c[j] = verts[conn[8 * i + j]];
5703 
5704  error = mb->create_element( MBHEX, c, 8, cells[i] );MB_CHK_ERR( error );
5705  }
5706 
5707  EntityHandle fileset;
5708  error = mb->create_meshset( MESHSET_SET, fileset );MB_CHK_ERR( error );
5709  error = mb->add_entities( fileset, &verts[0], num_vtx );MB_CHK_ERR( error );
5710  error = mb->add_entities( fileset, &cells[0], num_elems );MB_CHK_ERR( error );
5711 
5712  Range fverts, fedges, ffaces, fcells;
5713  error = mb->get_entities_by_dimension( fileset, 0, fverts );MB_CHK_ERR( error );
5714  error = mb->get_entities_by_dimension( fileset, 1, fedges );MB_CHK_ERR( error );
5715  error = mb->get_entities_by_dimension( fileset, 2, ffaces );MB_CHK_ERR( error );
5716  error = mb->get_entities_by_dimension( fileset, 3, fcells );MB_CHK_ERR( error );
5717 
5718  assert( fverts.size() == 18 && fedges.size() == 0 && ffaces.size() == 0 && fcells.size() == 4 );
5719 
5720  Skinner sk( mb );
5721  Range skin_ents;
5722  error = sk.find_skin( fileset, fcells, 2, skin_ents, false, true );MB_CHK_ERR( error );
5723  error = mb->get_entities_by_dimension( fileset, 2, ffaces );MB_CHK_ERR( error );
5724  assert( ffaces.size() == 16 );
5725  error = sk.find_skin( fileset, fcells, 1, skin_ents, false, true );MB_CHK_ERR( error );
5726  error = mb->get_entities_by_dimension( fileset, 1, fedges );MB_CHK_ERR( error );
5727  assert( fedges.size() == 32 );
5728 
5729  const double fcoords[] = { 0, 0, 3, 1, 0, 3, 2, 0, 3, 2, 1, 3, 1, 1, 3, 0, 1, 3 };
5730  const size_t num_fvtx = sizeof( fcoords ) / sizeof( double ) / 3;
5731 
5732  const int fconn[] = { 0, 1, 4, 5, 1, 2, 3, 4 };
5733  const size_t num_faces = sizeof( fconn ) / sizeof( int ) / 4;
5734  EntityHandle nwverts[num_fvtx], faces[num_faces];
5735  for( size_t i = 0; i < num_fvtx; ++i )
5736  {
5737  error = mb->create_vertex( fcoords + 3 * i, nwverts[i] );MB_CHK_ERR( error );
5738  }
5739 
5740  for( size_t i = 0; i < num_faces; ++i )
5741  {
5742  EntityHandle c[4];
5743  for( int j = 0; j < 4; j++ )
5744  c[j] = nwverts[fconn[4 * i + j]];
5745 
5746  error = mb->create_element( MBQUAD, c, 4, faces[i] );MB_CHK_ERR( error );
5747  }
5748  EntityHandle fileset1;
5749  error = mb->create_meshset( MESHSET_SET, fileset1 );MB_CHK_ERR( error );
5750  error = mb->add_entities( fileset1, &nwverts[0], num_fvtx );MB_CHK_ERR( error );
5751  error = mb->add_entities( fileset1, &faces[0], num_faces );MB_CHK_ERR( error );
5752 
5753  Range verts1, edges1, faces1;
5754  error = mb->get_entities_by_dimension( fileset1, 0, verts1 );MB_CHK_ERR( error );
5755  error = mb->get_entities_by_dimension( fileset1, 1, edges1 );MB_CHK_ERR( error );
5756  error = mb->get_entities_by_dimension( fileset1, 2, faces1 );MB_CHK_ERR( error );
5757 
5758  assert( verts1.size() == 6 && edges1.size() == 0 && faces1.size() == 2 );
5759 
5760  // error = sk.find_skin(fileset1, faces1, 1, skin_ents, false, true);MB_CHK_ERR(error);
5761  error = sk.find_skin( fileset1, faces1, false, skin_ents, NULL, true, true, false );MB_CHK_ERR( error );
5762  error = mb->get_entities_by_dimension( fileset1, 1, edges1 );MB_CHK_ERR( error );
5763  assert( edges1.size() == 6 );
5764 
5765  return MB_SUCCESS;
5766 }
5767 
5768 // It is a common problem for readers to incorrectly
5769 // handle invalid/unknown file types and non-existant
5770 // files. For either case, MOAB will try all readers
5771 // (assuming it doesn't recongnize the file extension),
5772 // so we can test all the readers w/out knowing which
5773 // readers we have.
5774 const char* argv0 = 0;
5776 {
5777  Core moab;
5778  Interface* mb = &moab;
5779 
5780  const char BAD_FILE_NAME[] = "non-existant-file.txt";
5781  ErrorCode rval;
5782 
5783  FILE* fptr = fopen( BAD_FILE_NAME, "r" );
5784  if( fptr )
5785  {
5786  fclose( fptr );
5787  std::cout << "Test cannot proceed while file exists: " << BAD_FILE_NAME << std::endl;
5788  return MB_FAILURE;
5789  }
5790 
5791  // try reading a non-existant file
5792 
5793  rval = mb->load_file( BAD_FILE_NAME );
5794  if( MB_FILE_DOES_NOT_EXIST != rval ) return MB_FAILURE;
5795 
5796  // try reading an invalid file
5797  if( !argv0 ) // not set by main, oops!
5798  return MB_FAILURE;
5799  rval = mb->load_file( argv0 );
5800  if( MB_SUCCESS == rval ) return MB_FAILURE;
5801 
5802  return MB_SUCCESS;
5803 }
5804 
5805 #define TEST_ERROR_CODE( E ) \
5806  if( mb->get_error_string( E ) != #E ) \
5807  { \
5808  std::cerr << "Invalid error string from get_error_string for " << #E << ": " << mb->get_error_string( E ) \
5809  << std::endl; \
5810  return MB_FAILURE; \
5811  }
5812 
5814 {
5815  Core moab;
5816  Interface* mb = &moab;
5817 
5834  TEST_ERROR_CODE( MB_FAILURE );
5835 
5836  return MB_SUCCESS;
5837 }
5838 
5839 // Test basic skinning using vert-to-elem adjacencies
5840 ErrorCode mb_skin_verts_common( unsigned dim, bool skin_elems );
5841 
5843 {
5844  return mb_skin_verts_common( 2, false );
5845 }
5846 
5848 {
5849  return mb_skin_verts_common( 3, false );
5850 }
5851 
5853 {
5854  return mb_skin_verts_common( 2, true );
5855 }
5856 
5858 {
5859  return mb_skin_verts_common( 3, true );
5860 }
5861 
5862 ErrorCode mb_skin_verts_common( unsigned dim, bool skin_elems )
5863 {
5864  const int INT = 10; // intervals+1
5865  const char* tmp_file = "structured.vtk";
5866  std::ofstream str( tmp_file );
5867  if( !str )
5868  {
5869  std::cerr << tmp_file << ": filed to create temp file" << std::endl;
5870  return MB_FAILURE;
5871  }
5872  str << "#vtk DataFile Version 2.0" << std::endl
5873  << "mb_skin_verts_common temp file" << std::endl
5874  << "ASCII" << std::endl
5875  << "DATASET STRUCTURED_POINTS" << std::endl
5876  << "DIMENSIONS " << INT << " " << ( dim > 1 ? INT : 1 ) << " " << ( dim > 2 ? INT : 1 ) << std::endl
5877  << "ORIGIN 0 0 0" << std::endl
5878  << "SPACING 1 1 1" << std::endl;
5879  str.close();
5880 
5881  Core moab;
5882  Interface& mb = moab;
5883  ErrorCode rval;
5884 
5885  rval = mb.load_file( tmp_file );
5886  remove( tmp_file );
5887  if( MB_SUCCESS != rval ) return rval;
5888 
5889  Range ents;
5890  rval = mb.get_entities_by_dimension( 0, dim, ents );
5891  if( MB_SUCCESS != rval ) return rval;
5892  if( ents.empty() ) return MB_FAILURE;
5893 
5894  Skinner tool( &mb );
5895 
5896  // mesh is a structured quad/hex mesh, so we can
5897  // determine skin vertices from the number of
5898  // adjacent elements.
5899  unsigned interior_adj = 1;
5900  for( unsigned i = 0; i < dim; ++i )
5901  interior_adj *= 2;
5902  Range expected, verts;
5903  rval = mb.get_entities_by_dimension( 0, 0, verts );
5904  if( MB_SUCCESS != rval ) return rval;
5905  Range::iterator h = expected.begin();
5906  std::vector< EntityHandle > adj;
5907  for( Range::iterator v = verts.begin(); v != verts.end(); ++v )
5908  {
5909  adj.clear();
5910  rval = mb.get_adjacencies( &*v, 1, dim, false, adj );
5911  if( MB_SUCCESS != rval ) return rval;
5912  if( adj.size() < interior_adj ) h = expected.insert( h, *v );
5913  }
5914 
5915  // Get skin vertices using skinner
5916  Range actual;
5917  rval = tool.find_skin( 0, ents, !skin_elems, actual );
5918  if( MB_SUCCESS != rval ) return rval;
5919 
5920  Range extra, missing;
5921  if( !skin_elems )
5922  {
5923  // Check that we got expected result
5924  extra = subtract( actual, expected );
5925  missing = subtract( expected, actual );
5926  if( !extra.empty() || !missing.empty() )
5927  {
5928  std::cout << "Extra vertices returned: " << extra << std::endl
5929  << "Missing vertices: " << missing << std::endl;
5930  return MB_FAILURE;
5931  }
5932  return MB_SUCCESS;
5933  }
5934 
5935  // test that no extra elements we're created
5936  extra.clear();
5937  rval = mb.get_entities_by_dimension( 0, dim - 1, extra );
5938  if( MB_SUCCESS != rval ) return rval;
5939  extra = subtract( extra, actual );
5940  if( !extra.empty() )
5941  {
5942  std::cout << "Extra/non-returned elements created: " << extra << std::endl;
5943  return MB_FAILURE;
5944  }
5945 
5946  // check that each skin vertex has the correct number of adjacent quads
5947  missing.clear();
5948  extra.clear();
5949  for( Range::iterator i = expected.begin(); i != expected.end(); ++i )
5950  {
5951  std::vector< EntityHandle > elem, side;
5952  rval = mb.get_adjacencies( &*i, 1, dim, false, elem );
5953  if( MB_SUCCESS != rval ) return rval;
5954  rval = mb.get_adjacencies( &*i, 1, dim - 1, false, side );
5955  if( MB_SUCCESS != rval ) return rval;
5956  if( elem.size() == 1 )
5957  {
5958  if( side.size() < dim )
5959  missing.insert( *i );
5960  else if( side.size() > dim )
5961  extra.insert( *i );
5962  }
5963  else if( elem.size() == interior_adj )
5964  {
5965  if( !side.empty() ) extra.insert( *i );
5966  }
5967  else
5968  {
5969  if( side.size() < interior_adj / 2 )
5970  missing.insert( *i );
5971  else if( side.size() > interior_adj / 2 )
5972  extra.insert( *i );
5973  }
5974  }
5975  if( !missing.empty() || !extra.empty() )
5976  {
5977  std::cout << "Skin elements missing at vertices: " << missing << std::endl
5978  << "Extra skin elements at vertices: " << extra << std::endl;
5979  return MB_FAILURE;
5980  }
5981 
5982  // check that all returned elements are actually on the skin
5983  extra.clear();
5984  for( Range::iterator i = actual.begin(); i != actual.end(); ++i )
5985  {
5986  Range verts2;
5987  rval = mb.get_adjacencies( &*i, 1, 0, false, verts2 );
5988  if( MB_SUCCESS != rval ) return rval;
5989  verts2 = subtract( verts2, expected );
5990  if( !verts2.empty() ) extra.insert( *i );
5991  }
5992  if( !extra.empty() )
5993  {
5994  std::cout << "Skinner returned elements not on skin: " << extra << std::endl;
5995  return MB_FAILURE;
5996  }
5997 
5998  return MB_SUCCESS;
5999 }
6000 
6001 // Test that skinning of polyhedra works
6003 {
6004  /* Create a mesh composed of 8 hexagonal prisms and
6005  two hexahedra by extruding the following cross section
6006  two steps in the Z direction.
6007 
6008  0-----1
6009  / (0) \
6010  (11)/ \‍(1)
6011  / \
6012  11 2
6013  / \ Y / \
6014  (10)/ \‍(12)^(13)/ \‍(2)
6015  / \ | / \
6016  10 12-----13 3
6017  | | | | |
6018  (9)| | +--|-->X |(3)
6019  | | | |
6020  9 15-----14 4
6021  \ / \ /
6022  (8)\ /(15) (14)\ /(4)
6023  \ / \ /
6024  8 5
6025  \ /
6026  (7)\ /(5)
6027  \ (6) /
6028  7-----6
6029  */
6030 
6031  const double coords2D[][2] = {
6032  { -1, 5 }, // 0
6033  { 1, 5 }, { 3, 3 }, { 5, 1 }, { 5, -1 }, { 3, -3 }, // 5
6034  { 1, -5 }, { -1, -5 }, { -3, -3 }, { -5, -1 }, { -5, 1 }, // 10
6035  { -3, 3 }, { -1, 1 }, { 1, 1 }, { 1, -1 }, { -1, -1 } // 15
6036  };
6037  const int polyconn[4][6] = {
6038  { 0, 1, 2, 13, 12, 11 }, { 2, 3, 4, 5, 14, 13 }, { 5, 6, 7, 8, 15, 14 }, { 8, 9, 10, 11, 12, 15 } };
6039  const int polyside[4][6] = {
6040  { 0, 1, 13, 16, 12, 11 }, { 2, 3, 4, 14, 17, 13 }, { 5, 6, 7, 15, 18, 14 }, { 8, 9, 10, 12, 19, 15 } };
6041 
6042  ErrorCode rval;
6043  Core moab;
6044  Interface& mb = moab;
6045  Range regions, faces, interior_faces;
6046 
6047  // create 48 vertices
6048  EntityHandle verts[3][16];
6049  for( int i = 0; i < 3; ++i )
6050  {
6051  for( int j = 0; j < 16; ++j )
6052  {
6053  double coords[3] = { coords2D[j][0], coords2D[j][1], static_cast< double >( 2 * i ) };
6054  rval = mb.create_vertex( coords, verts[i][j] );
6055  if( MB_SUCCESS != rval ) return rval;
6056  }
6057  }
6058 
6059  // create two hexahedra
6060  EntityHandle hexes[2];
6061  for( int i = 0; i < 2; ++i )
6062  {
6063  EntityHandle conn[8] = { verts[i][15], verts[i][14], verts[i][13], verts[i][12],
6064  verts[i + 1][15], verts[i + 1][14], verts[i + 1][13], verts[i + 1][12] };
6065  rval = mb.create_element( MBHEX, conn, 8, hexes[i] );
6066  if( MB_SUCCESS != rval ) return rval;
6067  regions.insert( hexes[i] );
6068  }
6069 
6070  // create hexagonal faces
6071  EntityHandle hexagons[3][4];
6072  for( int i = 0; i < 3; ++i )
6073  {
6074  for( int j = 0; j < 4; ++j )
6075  {
6076  EntityHandle conn[6];
6077  for( int k = 0; k < 6; ++k )
6078  conn[k] = verts[i][polyconn[j][k]];
6079  rval = mb.create_element( MBPOLYGON, conn, 6, hexagons[i][j] );
6080  if( MB_SUCCESS != rval ) return rval;
6081  faces.insert( hexagons[i][j] );
6082  if( i == 1 ) interior_faces.insert( hexagons[i][j] );
6083  }
6084  }
6085 
6086  // create quadrilateral faces
6087  EntityHandle quads[2][20];
6088  for( int i = 0; i < 2; ++i )
6089  {
6090  for( int j = 0; j < 20; ++j )
6091  {
6092  int c1, c2;
6093  if( j < 12 )
6094  {
6095  c1 = j;
6096  c2 = ( j + 1 ) % 12;
6097  }
6098  else if( j < 16 )
6099  {
6100  c1 = j;
6101  c2 = 2 + 3 * ( ( j - 9 ) % 4 );
6102  }
6103  else
6104  {
6105  c1 = j - 4;
6106  c2 = 12 + ( j - 15 ) % 4;
6107  }
6108  EntityHandle conn[4] = { verts[i][c1], verts[i][c2], verts[i + 1][c2], verts[i + 1][c1] };
6109  rval = mb.create_element( MBQUAD, conn, 4, quads[i][j] );
6110  if( MB_SUCCESS != rval ) return rval;
6111  faces.insert( quads[i][j] );
6112  if( j > 11 ) interior_faces.insert( quads[i][j] );
6113  }
6114  }
6115 
6116  // create polyhedra
6117  EntityHandle poly[2][4];
6118  for( int i = 0; i < 2; ++i )
6119  {
6120  for( int j = 0; j < 4; ++j )
6121  {
6122  EntityHandle conn[8];
6123  for( int k = 0; k < 6; ++k )
6124  conn[k] = quads[i][polyside[j][k]];
6125  conn[6] = hexagons[i][j];
6126  conn[7] = hexagons[i + 1][j];
6127  rval = mb.create_element( MBPOLYHEDRON, conn, 8, poly[i][j] );
6128  if( MB_SUCCESS != rval ) return rval;
6129  regions.insert( poly[i][j] );
6130  }
6131  }
6132 
6133  Range interior_verts;
6134  interior_verts.insert( verts[1][12] );
6135  interior_verts.insert( verts[1][13] );
6136  interior_verts.insert( verts[1][14] );
6137  interior_verts.insert( verts[1][15] );
6138 
6139  Skinner tool( &mb );
6140  Range skin;
6141  rval = tool.find_skin( 0, regions, true, skin, 0, true, false );
6142  if( MB_SUCCESS != rval )
6143  {
6144  std::cout << "Vertex skinning failed with: " << mb.get_error_string( rval ) << std::endl;
6145  return rval;
6146  }
6147 
6148  Range all_verts, all_faces;
6149  rval = mb.get_entities_by_dimension( 0, 0, all_verts );
6150  if( MB_SUCCESS != rval ) return rval;
6151  rval = mb.get_entities_by_dimension( 0, 2, all_faces );
6152  if( MB_SUCCESS != rval ) return rval;
6153 
6154  Range expected = subtract( all_verts, interior_verts );
6155  if( expected != skin )
6156  {
6157  std::cout << "Skinner returned incorrect vertices." << std::endl;
6158  return MB_FAILURE;
6159  }
6160  if( all_faces != faces )
6161  {
6162  std::cout << "Skinner created/deleted faces for vertex-only skinning" << std::endl;
6163  return MB_FAILURE;
6164  }
6165 
6166  skin.clear();
6167  rval = tool.find_skin( 0, regions, false, skin, 0, true, false );
6168  if( MB_SUCCESS != rval )
6169  {
6170  std::cout << "Non-create face skinning failed with: " << mb.get_error_string( rval ) << std::endl;
6171  return rval;
6172  }
6173  expected = subtract( all_faces, interior_faces );
6174  if( expected != skin )
6175  {
6176  std::cout << "Skinner returned incorrect faces." << std::endl;
6177  return MB_FAILURE;
6178  }
6179  if( all_faces != faces )
6180  {
6181  std::cout << "Skinner created/deleted faces for no-create skinning" << std::endl;
6182  return MB_FAILURE;
6183  }
6184 
6185  skin.clear();
6186  rval = tool.find_skin( 0, regions, false, skin, 0, true, true );
6187  if( MB_SUCCESS != rval )
6188  {
6189  std::cout << "Create face skinning failed with: " << mb.get_error_string( rval ) << std::endl;
6190  return rval;
6191  }
6192  Range all_faces2;
6193  rval = mb.get_entities_by_dimension( 0, 2, all_faces2 );
6194  if( MB_SUCCESS != rval ) return rval;
6195  Range difference = subtract( all_faces2, all_faces );
6196  if( difference.size() != 2 )
6197  { // should have created two quads for hex top/bottom
6198  std::cout << "Skinner failed to create new quads or created to many." << std::endl;
6199  return MB_FAILURE;
6200  }
6201  expected.merge( difference );
6202  if( expected != skin )
6203  {
6204  std::cout << "Skinner returned incorrect faces." << std::endl;
6205  return MB_FAILURE;
6206  }
6207  // check that new faces are correct
6208  EntityHandle expected_conn[2][4] = { { verts[0][12], verts[0][13], verts[0][14], verts[0][15] },
6209  { verts[2][12], verts[2][13], verts[2][14], verts[2][15] } };
6210  EntityHandle nq[2] = { difference.front(), difference.back() };
6211  for( int i = 0; i < 2; ++i )
6212  {
6213  const EntityHandle* conn;
6214  int len;
6215  bool found = false;
6216  for( int j = 0; !found && j < 2; ++j )
6217  {
6218  rval = mb.get_connectivity( nq[j], conn, len );
6219  if( MB_SUCCESS != rval ) return rval;
6220  int idx1 = std::find( conn, conn + len, expected_conn[i][0] ) - conn;
6221  if( idx1 == len ) continue;
6222  found = true;
6223  for( int k = 1; k < 4; ++k )
6224  if( conn[( idx1 + k ) % 4] != expected_conn[i][k] ) found = false;
6225  if( !found )
6226  {
6227  found = true;
6228  for( int k = 1; k < 4; ++k )
6229  if( conn[( idx1 + 4 - k ) % 4] != expected_conn[i][k] ) found = false;
6230  }
6231  }
6232  if( !found )
6233  {
6234  std::cerr << "Skinner did not create & return expected quad " << i << std::endl;
6235  return MB_FAILURE;
6236  }
6237  }
6238 
6239  return MB_SUCCESS;
6240 }
6241 
6242 // Test that skinning of higher-order elements works
6244 {
6245  /* Create mesh:
6246 
6247  0---1---2---3---4
6248  | | /
6249  | | /
6250  5 6 7 8 9
6251  | | /
6252  | | /
6253  10--11--12
6254  */
6255 
6256  ErrorCode rval;
6257  Core moab;
6258  Interface& mb = moab;
6259 
6260  double coords[13][3] = { { 0, 4, 0 }, { 2, 4, 0 }, { 4, 4, 0 }, { 6, 4, 0 }, { 8, 4, 0 }, { 0, 2, 0 }, { 2, 2, 0 },
6261  { 4, 2, 0 }, { 5, 2, 0 }, { 6, 2, 0 }, { 0, 0, 0 }, { 2, 0, 0 }, { 4, 0, 0 } };
6262  EntityHandle verts[13];
6263  for( int i = 0; i < 13; ++i )
6264  {
6265  rval = mb.create_vertex( coords[i], verts[i] );
6266  if( MB_SUCCESS != rval ) return rval;
6267  }
6268 
6269  EntityHandle qconn[9] = { verts[0], verts[2], verts[12], verts[10], verts[1],
6270  verts[7], verts[11], verts[5], verts[6] };
6271  EntityHandle tconn[7] = { verts[2], verts[4], verts[12], verts[3], verts[9], verts[7], verts[8] };
6272  EntityHandle quad, tri;
6273  rval = mb.create_element( MBQUAD, qconn, 9, quad );
6274  if( MB_SUCCESS != rval ) return rval;
6275  rval = mb.create_element( MBTRI, tconn, 7, tri );
6276  if( MB_SUCCESS != rval ) return rval;
6277 
6278  Range faces;
6279  faces.insert( quad );
6280  faces.insert( tri );
6281 
6282  Range skin_verts;
6283  const int skin_vert_idx[] = { 0, 1, 2, 3, 4, 5, 9, 10, 11, 12 };
6284  for( size_t i = 0; i < sizeof( skin_vert_idx ) / sizeof( skin_vert_idx[0] ); ++i )
6285  skin_verts.insert( verts[skin_vert_idx[i]] );
6286 
6287  Skinner tool( &mb );
6288  Range skin;
6289 
6290  rval = tool.find_skin( 0, faces, true, skin, 0, use_adj, false );
6291  if( MB_SUCCESS != rval )
6292  {
6293  std::cout << "Vertex skinning failed with: " << mb.get_error_string( rval ) << std::endl;
6294  return rval;
6295  }
6296  if( skin != skin_verts )
6297  {
6298  std::cout << "Skinner returned incorrect vertices." << std::endl;
6299  return MB_FAILURE;
6300  }
6301 
6302  const int skin_edges[5][3] = { { 0, 1, 2 }, { 2, 3, 4 }, { 4, 9, 12 }, { 12, 11, 10 }, { 10, 5, 0 } };
6303  skin.clear();
6304  rval = tool.find_skin( 0, faces, false, skin, 0, use_adj, true );
6305  if( MB_SUCCESS != rval )
6306  {
6307  std::cout << "Edge skinning failed with: " << mb.get_error_string( rval ) << std::endl;
6308  return rval;
6309  }
6310  if( skin.size() != 5u )
6311  {
6312  std::cout << "Skinner returned " << skin.size() << " vertices. Expected 5" << std::endl;
6313  return MB_FAILURE;
6314  }
6315  int num_quadratic = 0;
6316  const EntityHandle* conn;
6317  int len;
6318  for( Range::iterator i = skin.begin(); i != skin.end(); ++i )
6319  {
6320  rval = mb.get_connectivity( *i, conn, len, false );
6321  if( MB_SUCCESS != rval ) return rval;
6322  if( len == 3 )
6323  num_quadratic++;
6324  else if( len != 2 )
6325  {
6326  std::cerr << "Skinner created edge with " << len << " vertices" << std::endl;
6327  return MB_FAILURE;
6328  }
6329  }
6330  if( num_quadratic != 5 )
6331  {
6332  std::cerr << num_quadratic << " of 5 created edges were quadratic" << std::endl;
6333  return MB_FAILURE;
6334  }
6335 
6336  for( int i = 0; i < 5; ++i )
6337  {
6338  bool found = false;
6339  for( Range::iterator j = skin.begin(); j != skin.end(); ++j )
6340  {
6341  mb.get_connectivity( *j, conn, len, false );
6342  if( conn[2] == verts[skin_edges[i][1]] )
6343  {
6344  found = true;
6345  break;
6346  }
6347  }
6348  if( !found )
6349  {
6350  std::cerr << "One or more skin edges is incorrect" << std::endl;
6351  return MB_FAILURE;
6352  }
6353  if( ( conn[0] != verts[skin_edges[i][0]] || conn[1] != verts[skin_edges[i][2]] ) &&
6354  ( conn[0] != verts[skin_edges[i][2]] || conn[1] != verts[skin_edges[i][0]] ) )
6355  {
6356  std::cerr << "Invalid skin edge connectivity" << std::endl;
6357  return MB_FAILURE;
6358  }
6359  }
6360 
6361  return MB_SUCCESS;
6362 }
6364 {
6365  return mb_skin_higher_order_faces_common( false );
6366 }
6368 {
6369  return mb_skin_higher_order_faces_common( true );
6370 }
6371 
6372 // Test that skinning of higher-order elements works
6374 {
6375  // create mesh containing two 27-node hexes
6376  /*
6377  0,2---1,2---2,2---3,2---4,2
6378  | | |
6379  | | |
6380  0,1 1,1 2,1 3,1 4,1
6381  | | |
6382  | | |
6383  0,0---1,0---2,0---3,0---4,0
6384  */
6385 
6386  ErrorCode rval;
6387  Core moab;
6388  Interface& mb = moab;
6389  Range hexes;
6390 
6391  EntityHandle verts[5][3][3];
6392  for( int i = 0; i < 5; ++i )
6393  for( int j = 0; j < 3; ++j )
6394  for( int k = 0; k < 3; ++k )
6395  {
6396  double coords[] = { static_cast< double >( i ), static_cast< double >( j ),
6397  static_cast< double >( k ) };
6398  rval = mb.create_vertex( coords, verts[i][j][k] );
6399  if( MB_SUCCESS != rval ) return rval;
6400  }
6401 
6402  int hex_conn[][3] = { // corners
6403  { 0, 0, 0 },
6404  { 2, 0, 0 },
6405  { 2, 2, 0 },
6406  { 0, 2, 0 },
6407  { 0, 0, 2 },
6408  { 2, 0, 2 },
6409  { 2, 2, 2 },
6410  { 0, 2, 2 },
6411  // mid-edge
6412  { 1, 0, 0 },
6413  { 2, 1, 0 },
6414  { 1, 2, 0 },
6415  { 0, 1, 0 },
6416  { 0, 0, 1 },
6417  { 2, 0, 1 },
6418  { 2, 2, 1 },
6419  { 0, 2, 1 },
6420  { 1, 0, 2 },
6421  { 2, 1, 2 },
6422  { 1, 2, 2 },
6423  { 0, 1, 2 },
6424  // mid-face
6425  { 1, 0, 1 },
6426  { 2, 1, 1 },
6427  { 1, 2, 1 },
6428  { 0, 1, 1 },
6429  { 1, 1, 0 },
6430  { 1, 1, 2 },
6431  // mid-volume
6432  { 1, 1, 1 } };
6433 
6434  EntityHandle hexverts[2][27];
6435  for( int i = 0; i < 2; ++i )
6436  {
6437  EntityHandle h;
6438  for( int j = 0; j < 27; ++j )
6439  hexverts[i][j] = verts[2 * i + hex_conn[j][0]][hex_conn[j][1]][hex_conn[j][2]];
6440  rval = mb.create_element( MBHEX, hexverts[i], 27, h );
6441  if( MB_SUCCESS != rval ) return rval;
6442  hexes.insert( h );
6443  }
6444 
6445  Range interior_verts;
6446  interior_verts.insert( verts[1][1][1] ); // mid-node of hex 1
6447  interior_verts.insert( verts[3][1][1] ); // mid-node of hex 2
6448  interior_verts.insert( verts[2][1][1] ); // mid-node of shared face
6449 
6450  Skinner tool( &mb );
6451  Range skin;
6452 
6453  rval = tool.find_skin( 0, hexes, true, skin, 0, use_adj, false );
6454  if( MB_SUCCESS != rval )
6455  {
6456  std::cout << "Vertex skinning failed with: " << mb.get_error_string( rval ) << std::endl;
6457  return rval;
6458  }
6459  Range extra = intersect( skin, interior_verts );
6460  if( !extra.empty() )
6461  {
6462  std::cout << "Skinner returned " << extra.size() << " interior vertices" << std::endl;
6463  std::cout << extra << std::endl;
6464  return MB_FAILURE;
6465  }
6466  int num_vtx;
6467  mb.get_number_entities_by_dimension( 0, 0, num_vtx );
6468  size_t num_skin = num_vtx - interior_verts.size();
6469  if( skin.size() != num_skin )
6470  {
6471  std::cout << "Skinner returned " << skin.size() << " of " << num_skin << " skin vertices" << std::endl;
6472  return MB_FAILURE;
6473  }
6474 
6475  skin.clear();
6476  rval = tool.find_skin( 0, hexes, false, skin, 0, use_adj, true );
6477  if( MB_SUCCESS != rval )
6478  {
6479  std::cout << "Element skinning failed with: " << mb.get_error_string( rval ) << std::endl;
6480  return rval;
6481  }
6482 
6483  if( skin.size() > 10u )
6484  {
6485  std::cout << "Skinner created too many faces" << std::endl;
6486  return MB_FAILURE;
6487  }
6488 
6489  bool all_okay = true;
6490  bool faces[2][6] = { { false, false, false, false, false, false }, { false, false, false, false, false, false } };
6491  const EntityHandle* conn;
6492  int len;
6493  for( Range::iterator it = skin.begin(); it != skin.end(); ++it )
6494  {
6495  rval = mb.get_connectivity( *it, conn, len );
6496  if( MB_SUCCESS != rval ) return rval;
6497  if( len != 9 )
6498  {
6499  std::cout << "Skinner created face with " << len << " nodes" << std::endl;
6500  all_okay = false;
6501  continue;
6502  }
6503 
6504  int valid, side, sense, offset;
6505  for( int h = 0; h < 2; ++h )
6506  {
6507  valid = CN::SideNumber( MBHEX, hexverts[h], conn, 4, 2, side, sense, offset );
6508  if( valid != 0 ) continue;
6509  if( sense != 1 )
6510  {
6511  std::cout << "Skinner created reversed face for hex " << h << " side " << side << std::endl;
6512  all_okay = false;
6513  continue;
6514  }
6515 
6516  int idx[9], len2;
6517  EntityType sidetype;
6518  CN::SubEntityNodeIndices( MBHEX, 27, 2, side, sidetype, len2, idx );
6519  assert( sidetype == MBQUAD );
6520  assert( len2 == 9 );
6521  if( conn[offset] != hexverts[h][idx[0]] || conn[( offset + 1 ) % 4] != hexverts[h][idx[1]] ||
6522  conn[( offset + 2 ) % 4] != hexverts[h][idx[2]] || conn[( offset + 3 ) % 4] != hexverts[h][idx[3]] ||
6523  conn[4 + offset] != hexverts[h][idx[4]] || conn[4 + ( offset + 1 ) % 4] != hexverts[h][idx[5]] ||
6524  conn[4 + ( offset + 2 ) % 4] != hexverts[h][idx[6]] ||
6525  conn[4 + ( offset + 3 ) % 4] != hexverts[h][idx[7]] || conn[8] != hexverts[h][idx[8]] )
6526  {
6527  std::cout << "Side " << side << " of hex " << h << " has invalid connectivity" << std::endl;
6528  all_okay = false;
6529  }
6530 
6531  faces[h][side] = true;
6532  }
6533  }
6534 
6535  for( int h = 0; h < 2; ++h )
6536  {
6537  for( int i = 0; i < 6; ++i )
6538  {
6539  if( ( h == 0 && i == 1 ) || ( h == 1 && i == 3 ) )
6540  {
6541  if( faces[h][i] )
6542  {
6543  std::cout << "Skinner created interior face for side " << i << " of hex " << h << std::endl;
6544  all_okay = false;
6545  }
6546  }
6547  else if( !faces[h][i] )
6548  {
6549  std::cout << "Skinner failed to create side " << i << " of hex " << h << std::endl;
6550  all_okay = false;
6551  }
6552  }
6553  }
6554 
6555  return all_okay ? MB_SUCCESS : MB_FAILURE;
6556 }
6557 
6558 // Test that skinning of higher-order elements works
6560 {
6561  // create mesh containing 13-node pyramid
6562  /*
6563 
6564  */
6565 
6566  ErrorCode rval;
6567  Core moab;
6568  Interface& mb = moab;
6569  Range pyramids;
6570 
6571  // easier to create a 27 node grid, and then pick a 13-node pyramid
6572  EntityHandle verts[3][3][3];
6573  for( int i = 0; i < 3; ++i )
6574  for( int j = 0; j < 3; ++j )
6575  for( int k = 0; k < 3; ++k )
6576  {
6577  double coords[] = { static_cast< double >( i ), static_cast< double >( j ),
6578  static_cast< double >( k ) };
6579  rval = mb.create_vertex( coords, verts[i][j][k] );
6580  if( MB_SUCCESS != rval ) return rval;
6581  }
6582 
6583  EntityHandle piramid1[13] = { 19, 25, 27, 21, 1, 22, 26, 24, 20, 10, 13, 14, 11 };
6584 
6585  EntityHandle h;
6586 
6587  rval = mb.create_element( MBPYRAMID, piramid1, 13, h );
6588  if( MB_SUCCESS != rval ) return rval;
6589  pyramids.insert( h );
6590 
6591  Range faces;
6592  rval = mb.get_adjacencies( pyramids, 2, true, faces, Interface::UNION );
6593  // triangles should have 6 nodes, quads 8 nodes
6594 
6595  if( MB_SUCCESS != rval ) return rval;
6596 
6597  Range tris = faces.subset_by_type( MBTRI );
6598  Range quads = faces.subset_by_type( MBQUAD );
6599 
6600  for( Range::iterator tit = tris.begin(); tit != tris.end(); tit++ )
6601  {
6602  EntityHandle triangle = *tit;
6603  const EntityHandle* conn;
6604  int num_verts;
6605  rval = mb.get_connectivity( triangle, conn, num_verts );
6606  if( MB_SUCCESS != rval ) return rval;
6607  if( 6 != num_verts ) return MB_FAILURE;
6608  }
6609  for( Range::iterator qit = quads.begin(); qit != quads.end(); qit++ )
6610  {
6611  EntityHandle quad = *qit;
6612  const EntityHandle* conn;
6613  int num_verts;
6614  rval = mb.get_connectivity( quad, conn, num_verts );
6615  if( MB_SUCCESS != rval ) return rval;
6616  if( 8 != num_verts ) return MB_FAILURE;
6617  }
6618 
6619  return MB_SUCCESS;
6620 }
6622 {
6623  return mb_skin_higher_order_regions_common( false );
6624 }
6626 {
6627  return mb_skin_higher_order_regions_common( true );
6628 }
6629 
6631 {
6632  EntityType type, subtype;
6633  switch( dim )
6634  {
6635  case 2:
6636  type = MBTRI;
6637  subtype = MBEDGE;
6638  break;
6639  case 3:
6640  type = MBTET;
6641  subtype = MBTRI;
6642  break;
6643  default:
6644  assert( false );
6645  return MB_FAILURE;
6646  }
6647 
6648  /* 3
6649  /|\
6650  / | \
6651  / | \
6652  / | \
6653  0----1----2
6654  */
6655 
6656  ErrorCode rval;
6657  Core moab;
6658  Interface& mb = moab;
6659  Range hexes;
6660 
6661  double coords[][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 2, 0, 0 }, { 1, 2, 0 }, { 1, 2, 2 } };
6662  EntityHandle verts[5];
6663  const int nvtx = 2 + dim;
6664  for( int i = 0; i < nvtx; ++i )
6665  {
6666  rval = mb.create_vertex( coords[i], verts[i] );
6667  if( MB_SUCCESS != rval ) return rval;
6668  }
6669  // NOTE: order connectivity such that side 1 is shared!
6670  EntityHandle conn[2][4] = { { verts[0], verts[1], verts[3], verts[4] },
6671  { verts[2], verts[3], verts[1], verts[4] } };
6672  const int conn_len = dim + 1;
6673  Range elems;
6674  for( int i = 0; i < 2; ++i )
6675  {
6676  EntityHandle h;
6677  rval = mb.create_element( type, conn[i], conn_len, h );
6678  if( MB_SUCCESS != rval ) return rval;
6679  elems.insert( h );
6680  }
6681 
6682  // create one reversed side
6683  EntityHandle side_conn[3];
6684  int side_indices[3] = { 0, 0, 0 };
6685  CN::SubEntityVertexIndices( type, dim - 1, 0, side_indices );
6686  side_conn[0] = conn[0][side_indices[1]];
6687  side_conn[1] = conn[0][side_indices[0]];
6688  side_conn[2] = conn[0][side_indices[2]];
6689  EntityHandle side;
6690  rval = mb.create_element( subtype, side_conn, dim, side );
6691  if( MB_SUCCESS != rval ) return rval;
6692 
6693  Range forward, reverse;
6694  Skinner tool( &mb );
6695  rval = tool.find_skin( 0, elems, false, forward, &reverse, use_adj, true );
6696  if( MB_SUCCESS != rval )
6697  {
6698  std::cout << "Skinner failed." << std::endl;
6699  return rval;
6700  }
6701 
6702  // expect all faces created by the skinner to be forward,
6703  // so the only reversed side should be the one created above.
6704  if( reverse.size() != 1 || reverse.front() != side )
6705  {
6706  std::cout << "Expected 1 reversed side, got: " << reverse.size() << std::endl;
6707  return MB_FAILURE;
6708  }
6709 
6710  return MB_SUCCESS;
6711 }
6713 {
6714  return mb_skin_reversed_common( 2, false );
6715 }
6717 {
6718  return mb_skin_reversed_common( 2, true );
6719 }
6721 {
6722  return mb_skin_reversed_common( 3, false );
6723 }
6725 {
6726  return mb_skin_reversed_common( 3, true );
6727 }
6728 
6729 ErrorCode mb_skin_subset_common( int dimension, bool use_adj )
6730 {
6731  EntityType type;
6732  switch( dimension )
6733  {
6734  case 2:
6735  type = MBTRI;
6736  break;
6737  case 3:
6738  type = MBPRISM;
6739  break;
6740  default:
6741  assert( false );
6742  return MB_FAILURE;
6743  }
6744 
6745  /* 0
6746  /|\
6747  / | \
6748  5 | 1
6749  |\ | /|
6750  | \|/ |
6751  | 6 |
6752  | /|\ |
6753  |/ | \|
6754  4 | 2
6755  \ | /
6756  \|/
6757  3
6758  */
6759 
6760  ErrorCode rval;
6761  Core moab;
6762  Interface& mb = moab;
6763  Range expected_verts;
6764 
6765  const double coords2D[7][2] = { { 0, 2 }, { 1, 1 }, { 1, -1 }, { 0, -2 }, { -1, -1 }, { -1, 1 }, { 0, 0 } };
6766  EntityHandle verts[2][7] = { { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 } };
6767  for( int d = 1; d < dimension; ++d )
6768  {
6769  for( int i = 0; i < 7; ++i )
6770  {
6771  double coords[3] = { coords2D[i][0], coords2D[i][1], static_cast< double >( d - 1 ) };
6772  rval = mb.create_vertex( coords, verts[d - 1][i] );
6773  if( MB_SUCCESS != rval ) return rval;
6774  if( i != 4 && i != 5 ) expected_verts.insert( verts[d - 1][i] );
6775  }
6776  }
6777 
6778  EntityHandle elems[6];
6779  for( int i = 0; i < 6; ++i )
6780  {
6781  EntityHandle conn[6] = { verts[0][6], verts[0][( i + 1 ) % 6], verts[0][i],
6782  verts[1][6], verts[1][( i + 1 ) % 6], verts[1][i] };
6783  rval = mb.create_element( type, conn, CN::VerticesPerEntity( type ), elems[i] );
6784  if( MB_SUCCESS != rval ) return rval;
6785  }
6786 
6787  Range input;
6788  input.insert( elems[0] );
6789  input.insert( elems[1] );
6790  input.insert( elems[2] );
6791 
6792  Range skin;
6793  Skinner tool( &mb );
6794  rval = tool.find_skin( 0, input, true, skin, 0, use_adj, false );
6795  if( MB_SUCCESS != rval )
6796  {
6797  std::cout << "Skinner failed to find skin vertices" << std::endl;
6798  return MB_FAILURE;
6799  }
6800  if( skin != expected_verts )
6801  {
6802  std::cout << "Skinner returned incorrect skin vertices" << std::endl;
6803  return MB_FAILURE;
6804  }
6805  int n = 0;
6806  mb.get_number_entities_by_dimension( 0, dimension - 1, n );
6807  if( n > 0 )
6808  {
6809  std::cout << "Skinner created lower-dimension entities for vertex-only skinning" << std::endl;
6810  return MB_FAILURE;
6811  }
6812 
6813  std::vector< EntityHandle > sv( skin.begin(), skin.end() );
6814  std::vector< int > counts( sv.size(), 0 );
6815  skin.clear();
6816  rval = tool.find_skin( 0, input, false, skin, 0, use_adj, true );
6817  if( MB_SUCCESS != rval )
6818  {
6819  std::cout << "Skinner failed to find skin elements" << std::endl;
6820  return MB_FAILURE;
6821  }
6822  for( Range::iterator i = skin.begin(); i != skin.end(); ++i )
6823  {
6824  const EntityHandle* conn;
6825  int len;
6826  rval = mb.get_connectivity( *i, conn, len );
6827  if( MB_SUCCESS != rval ) return rval;
6828  for( int j = 0; j < len; ++j )
6829  {
6830  size_t idx = std::find( sv.begin(), sv.end(), conn[j] ) - sv.begin();
6831  if( idx == sv.size() )
6832  {
6833  std::cout << "Skinner returned non-skin element" << std::endl;
6834  return MB_FAILURE;
6835  }
6836  counts[idx]++;
6837  }
6838  }
6839  for( size_t i = 0; i < counts.size(); ++i )
6840  {
6841  if( counts[i] < dimension )
6842  { // 2 for dim==2, {3,4,5} for dim==3
6843  std::cout << "Skinner did not return all skin elements" << std::endl;
6844  return MB_FAILURE;
6845  }
6846  }
6847  mb.get_number_entities_by_dimension( 0, dimension - 1, n );
6848  if( (size_t)n != skin.size() )
6849  {
6850  std::cout << "Skinner created extra lower-dimension entities" << std::endl;
6851  return MB_FAILURE;
6852  }
6853 
6854  return MB_SUCCESS;
6855 }
6856 
6858 {
6859  return mb_skin_subset_common( 2, false );
6860 }
6862 {
6863  return mb_skin_subset_common( 2, true );
6864 }
6866 {
6867  return mb_skin_subset_common( 3, false );
6868 }
6870 {
6871  return mb_skin_subset_common( 3, true );
6872 }
6873 
6874 ErrorCode mb_skin_full_common( int dimension, bool use_adj )
6875 {
6876  EntityType type;
6877  switch( dimension )
6878  {
6879  case 2:
6880  type = MBQUAD;
6881  break;
6882  case 3:
6883  type = MBHEX;
6884  break;
6885  default:
6886  assert( false );
6887  return MB_FAILURE;
6888  }
6889 
6890  /*
6891  3----4----5
6892  | | |
6893  | | |
6894  0----1----2
6895  */
6896 
6897  ErrorCode rval;
6898  Core moab;
6899  Interface& mb = moab;
6900 
6901  // create vertices
6902  const double coords2D[6][2] = { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } };
6903  EntityHandle v[2][6] = { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 } };
6904  for( int d = 1; d < dimension; ++d )
6905  {
6906  for( int i = 0; i < 6; ++i )
6907  {
6908  double coords[3] = { coords2D[i][0], coords2D[i][1], static_cast< double >( d - 1 ) };
6909  rval = mb.create_vertex( coords, v[d - 1][i] );
6910  if( MB_SUCCESS != rval ) return rval;
6911  }
6912  }
6913 
6914  // create elements
6915  Range input;
6916  EntityHandle elems[2], econn[2][8];
6917  ;
6918  for( int i = 0; i < 2; ++i )
6919  {
6920  EntityHandle conn[8] = { v[0][i], v[0][i + 1], v[0][i + 4], v[0][i + 3],
6921  v[1][i], v[1][i + 1], v[1][i + 4], v[1][i + 3] };
6922  memcpy( econn[i], conn, sizeof( conn ) );
6923  rval = mb.create_element( type, conn, CN::VerticesPerEntity( type ), elems[i] );
6924  if( MB_SUCCESS != rval ) return rval;
6925  input.insert( elems[i] );
6926  }
6927 
6928  // create sides
6929  // NOTE: Shared side is element 0 side 1 and element 1 side 3
6930  Range expected;
6931  for( int i = 0; i < CN::NumSubEntities( type, dimension - 1 ); ++i )
6932  {
6933  EntityType subtype;
6934  int len;
6935  const short* indices = CN::SubEntityVertexIndices( type, dimension - 1, i, subtype, len );
6936  EntityHandle conn[4];
6937  assert( (size_t)len <= sizeof( conn ) / sizeof( conn[0] ) );
6938  for( int j = 0; j < 2; ++j )
6939  {
6940  if( j == 1 && i == 3 ) // don't create shared face twice
6941  continue;
6942  for( int k = 0; k < len; ++k )
6943  conn[k] = econn[j][indices[k]];
6944  EntityHandle h;
6945  rval = mb.create_element( subtype, conn, len, h );
6946  if( MB_SUCCESS != rval ) return rval;
6947  if( j != 0 || i != 1 ) // don't insert shared face
6948  expected.insert( h );
6949  }
6950  }
6951 
6952  Range skin;
6953  Skinner tool( &mb );
6954  rval = tool.find_skin( 0, input, false, skin, 0, use_adj, true );
6955  if( MB_SUCCESS != rval )
6956  {
6957  std::cout << "Skinner failed to find skin elements" << std::endl;
6958  return MB_FAILURE;
6959  }
6960  if( skin != expected )
6961  {
6962  std::cout << "Skinner returned incorrect skin elements" << std::endl;
6963  return MB_FAILURE;
6964  }
6965 
6966  int n = 0;
6967  mb.get_number_entities_by_dimension( 0, dimension - 1, n );
6968  if( (size_t)n != expected.size() + 1 )
6969  {
6970  std::cout << "Skinner created extra lower-dimension entities" << std::endl;
6971  return MB_FAILURE;
6972  }
6973 
6974  return MB_SUCCESS;
6975 }
6976 
6978 {
6979  return mb_skin_full_common( 2, false );
6980 }
6982 {
6983  return mb_skin_full_common( 2, true );
6984 }
6986 {
6987  return mb_skin_full_common( 3, false );
6988 }
6990 {
6991  return mb_skin_full_common( 3, true );
6992 }
6993 
6995 {
6996  Core moab;
6997  Interface& mb = moab;
6998  ErrorCode rval;
6999  Skinner tool( &mb );
7000 
7001  /* Mesh with vertices and quads numbered.
7002  Groups are indicated by letters {A,B,C,D}
7003 
7004  0----1----2----3----4----5
7005  | (0)| (1)| (2)| (3)| (4)|
7006  | A | A | B | B | B |
7007  6----7----8----9---10---11
7008  | (5)| (6)| (7)| (8)| (9)|
7009  | A | A | A | B | B |
7010  12---13---14---15---16---17
7011  |(10)|(11)|(12)|(13)|(14)|
7012  | A | C | D | D | D |
7013  18---19---20---21---22---23
7014  |(15)|(16)|(17)|(18)|(19)|
7015  | C | C | C | D | D |
7016  24---25---26---27---28---29
7017  */
7018 
7019  const int num_vtx = 30;
7020  EntityHandle vtx[num_vtx];
7021  for( int i = 0; i < 6; ++i )
7022  {
7023  for( int j = 0; j < 5; ++j )
7024  {
7025  double coords[3] = { static_cast< double >( i ), static_cast< double >( j ), 0 };
7026  rval = mb.create_vertex( coords, vtx[6 * j + i] );
7027  if( MB_SUCCESS != rval ) return rval;
7028  }
7029  }
7030 
7031  EntityHandle quads[20];
7032  for( int i = 0; i < 5; ++i )
7033  {
7034  for( int j = 0; j < 4; ++j )
7035  {
7036  int v = 6 * j + i;
7037  EntityHandle conn[4] = { vtx[v + 6], vtx[v + 7], vtx[v + 1], vtx[v + 0] };
7038  rval = mb.create_element( MBQUAD, conn, 4, quads[5 * j + i] );
7039  if( MB_SUCCESS != rval ) return rval;
7040  }
7041  }
7042 
7043  // Define four groups of quads (as labeled above)
7044  const int Aquads[] = { 0, 1, 5, 6, 7, 10 };
7045  const int Aquads_size = sizeof( Aquads ) / sizeof( Aquads[0] );
7046  const int Bquads[] = { 2, 3, 4, 8, 9 };
7047  const int Bquads_size = sizeof( Bquads ) / sizeof( Bquads[0] );
7048  const int Cquads[] = { 11, 15, 16, 17 };
7049  const int Cquads_size = sizeof( Cquads ) / sizeof( Cquads[0] );
7050  const int Dquads[] = { 12, 13, 14, 18, 19 };
7051  const int Dquads_size = sizeof( Dquads ) / sizeof( Dquads[0] );
7052 
7053  // Define the results we expect for each group as a loop
7054  // of vertex indices
7055  const int Askin[] = { 0, 1, 2, 8, 9, 15, 14, 13, 19, 18, 12, 6 };
7056  const int Ashared[] = { -1, -1, 1, 1, 1, 3, 2, 2, 2, -1, -1, -1 };
7057  const int Askin_size = sizeof( Askin ) / sizeof( Askin[0] );
7058  const int Bskin[] = { 2, 3, 4, 5, 11, 17, 16, 15, 9, 8 };
7059  const int Bshared[] = { -1, -1, -1, -1, -1, 3, 3, 0, 0, 0 };
7060  const int Bskin_size = sizeof( Bskin ) / sizeof( Bskin[0] );
7061  const int Cskin[] = { 18, 19, 13, 14, 20, 21, 27, 26, 25, 24 };
7062  const int Cshared[] = { 0, 0, 0, 3, 3, 3, -1, -1, -1, -1 };
7063  const int Cskin_size = sizeof( Cskin ) / sizeof( Cskin[0] );
7064  const int Dskin[] = { 14, 15, 16, 17, 23, 29, 28, 27, 21, 20 };
7065  const int Dshared[] = { 0, 1, 1, -1, -1, -1, -1, 2, 2, 2 };
7066  const int Dskin_size = sizeof( Dskin ) / sizeof( Dskin[0] );
7067 
7068  // Make the above stuff indexable for easier looping
7069  const int* const gquads[4] = { Aquads, Bquads, Cquads, Dquads };
7070  const int gquads_size[4] = { Aquads_size, Bquads_size, Cquads_size, Dquads_size };
7071  const int* const skin[4] = { Askin, Bskin, Cskin, Dskin };
7072  const int* const shared[4] = { Ashared, Bshared, Cshared, Dshared };
7073  const int skin_size[4] = { Askin_size, Bskin_size, Cskin_size, Dskin_size };
7074 
7075  // Create an Range for each group of quads
7076  Range ranges[4];
7077  for( int grp = 0; grp < 4; ++grp )
7078  for( int i = 0; i < gquads_size[grp]; ++i )
7079  ranges[grp].insert( quads[gquads[grp][i]] );
7080 
7081  // run test 4 times, one for each of:
7082  // o no adjacencies, no edges
7083  // o no adjacencies, edges
7084  // o adjacencies, edges
7085  // o adjacencies, no edges
7086  //
7087  // Be careful here: once we specify use_adj, we can't
7088  // unspecify it (the adjacencies will exist so the skinner
7089  // will use them, regardless of the passed flag.)
7090  int error_count = 0;
7091  for( int run = 0; run < 4; ++run )
7092  {
7093  const bool use_adj = run > 1;
7094  if( run == 3 )
7095  {
7096  Range dead;
7097  mb.get_entities_by_type( 0, MBEDGE, dead );
7098  mb.delete_entities( dead );
7099  }
7100 
7101  // test each group
7102  Range edges[4];
7103  for( int grp = 0; grp < 4; ++grp )
7104  {
7105  // get the skin edges
7106  rval = tool.find_skin( 0, ranges[grp], 1, edges[grp], use_adj );
7107  if( MB_SUCCESS != rval )
7108  {
7109  std::cout << "Skinner failed for run " << run << " group " << grp << std::endl;
7110  return rval;
7111  }
7112 
7113  // check that we have the expected result
7114  std::vector< bool > seen( skin_size[grp], false );
7115  for( Range::iterator e = edges[grp].begin(); e != edges[grp].end(); ++e )
7116  {
7117  const EntityHandle* conn;
7118  int len;
7119  rval = mb.get_connectivity( *e, conn, len );
7120  if( MB_SUCCESS != rval ) return rval;
7121  if( len != 2 ) return MB_FAILURE;
7122  const int idx1 = std::find( vtx, vtx + num_vtx, conn[0] ) - vtx;
7123  const int idx2 = std::find( vtx, vtx + num_vtx, conn[1] ) - vtx;
7124  int pos = std::find( skin[grp], skin[grp] + skin_size[grp], idx1 ) - skin[grp];
7125  if( pos == skin_size[grp] )
7126  {
7127  std::cout << "Non-skin vertex in skin for run " << run << " group " << grp << std::endl;
7128  std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
7129  ++error_count;
7130  continue;
7131  }
7132 
7133  if( skin[grp][( pos + skin_size[grp] - 1 ) % skin_size[grp]] == idx2 )
7134  pos = ( pos + skin_size[grp] - 1 ) % skin_size[grp];
7135  else if( skin[grp][( pos + 1 ) % skin_size[grp]] != idx2 )
7136  {
7137  std::cout << "Non-skin edge in skin for run " << run << " group " << grp << std::endl;
7138  std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
7139  ++error_count;
7140  continue;
7141  }
7142 
7143  if( seen[pos] )
7144  {
7145  std::cout << "Duplicate edge in skin for run " << run << " group " << grp << std::endl;
7146  std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
7147  ++error_count;
7148  }
7149  seen[pos] = true;
7150 
7151  int shared_with = shared[grp][pos];
7152  if( shared_with < 0 ) // not shared with another group
7153  continue;
7154  if( shared_with > grp ) // didn't skin other group yet
7155  continue;
7156  if( edges[shared_with].find( *e ) == edges[shared_with].end() )
7157  {
7158  std::cout << "Skin edge duplicated for run " << run << " group " << grp << std::endl;
7159  std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << " not in skin for group " << shared_with
7160  << std::endl;
7161  ++error_count;
7162  }
7163  }
7164 
7165  int missing = std::count( seen.begin(), seen.end(), false );
7166  if( missing )
7167  {
7168  std::cout << "Missking " << missing << " skin edges for run " << run << " group " << grp << std::endl;
7169  error_count += missing;
7170  }
7171  }
7172  }
7173 
7174  return error_count ? MB_FAILURE : MB_SUCCESS;
7175 }
7176 
7178  EntityHandle meshset,
7179  const Tag* tag_handles,
7180  const void* const* values,
7181  int num_tags,
7182  Range& result,
7183  int condition,
7184  bool recursive )
7185 {
7186  ErrorCode rval;
7187  Range tmp;
7188  const EntityType LAST = recursive ? MBENTITYSET : MBMAXTYPE;
7189  for( EntityType t = MBVERTEX; t < LAST; ++t )
7190  {
7191  tmp.clear();
7192  rval = mb->get_entities_by_type_and_tag( meshset, t, tag_handles, values, num_tags, tmp, condition, recursive );
7193  if( MB_SUCCESS != rval ) return rval;
7194  result.insert( tmp.begin(), tmp.end() );
7195  }
7196  return MB_SUCCESS;
7197 }
7198 
7199 /** Check that functions which accept a type return the
7200  * result for all types when passed MBMAXTYPE
7201  */
7203 {
7204  Core moab;
7205  Interface* mb = &moab;
7206  ErrorCode rval = create_some_mesh( mb );
7207  if( MB_SUCCESS != rval ) return rval;
7208 
7209  Range r1, r2;
7210  rval = mb->get_entities_by_type( 0, MBMAXTYPE, r1, false );MB_CHK_ERR( rval );
7211  rval = mb->get_entities_by_handle( 0, r2, false );MB_CHK_ERR( rval );
7212  CHECK( r1 == r2 );
7213 
7214  std::vector< EntityHandle > v1, v2;
7215  rval = mb->get_entities_by_type( 0, MBMAXTYPE, v1, false );MB_CHK_ERR( rval );
7216  rval = mb->get_entities_by_handle( 0, v2, false );MB_CHK_ERR( rval );
7217  CHECK( v1 == v2 );
7218 
7219  int c1, c2;
7220  rval = mb->get_number_entities_by_type( 0, MBMAXTYPE, c1, false );MB_CHK_ERR( rval );
7221  rval = mb->get_number_entities_by_handle( 0, c2, false );MB_CHK_ERR( rval );
7222  CHECK( c1 == c2 );
7223 
7224  Range h1, h2;
7225  Range::iterator it = r1.begin() + r1.size() / 2;
7226  h1.insert( r1.begin(), it );
7227  if( it != r1.end() ) h2.insert( ++it, r1.end() );
7228 
7229  EntityHandle s1, s2;
7230  rval = mb->create_meshset( MESHSET_SET, s1 );MB_CHK_ERR( rval );
7231  rval = mb->create_meshset( MESHSET_ORDERED, s2 );MB_CHK_ERR( rval );
7232  rval = mb->add_entities( s1, r1 );MB_CHK_ERR( rval );
7233  rval = mb->add_entities( s2, r2 );MB_CHK_ERR( rval );
7234  rval = mb->add_entities( s2, &s1, 1 );MB_CHK_ERR( rval );
7235 
7236  r1.clear();
7237  r2.clear();
7238  rval = mb->get_entities_by_type( s1, MBMAXTYPE, r1, false );MB_CHK_ERR( rval );
7239  rval = mb->get_entities_by_handle( s1, r2, false );MB_CHK_ERR( rval );
7240  CHECK( r1 == r2 );
7241 
7242  r1.clear();
7243  r2.clear();
7244  rval = mb->get_entities_by_type( s2, MBMAXTYPE, r1, false );MB_CHK_ERR( rval );
7245  rval = mb->get_entities_by_handle( s2, r2, false );MB_CHK_ERR( rval );
7246  CHECK( r1 == r2 );
7247 
7248  r1.clear();
7249  r2.clear();
7250  rval = mb->get_entities_by_type( s2, MBMAXTYPE, r1, true );MB_CHK_ERR( rval );
7251  rval = mb->get_entities_by_handle( s2, r2, true );MB_CHK_ERR( rval );
7252  CHECK( r1 == r2 );
7253 
7254  v1.clear();
7255  v2.clear();
7256  rval = mb->get_entities_by_type( s1, MBMAXTYPE, v1, false );MB_CHK_ERR( rval );
7257  rval = mb->get_entities_by_handle( s1, v2, false );MB_CHK_ERR( rval );
7258  CHECK( v1 == v2 );
7259 
7260  v1.clear();
7261  v2.clear();
7262  rval = mb->get_entities_by_type( s2, MBMAXTYPE, v1, false );MB_CHK_ERR( rval );
7263  rval = mb->get_entities_by_handle( s2, v2, false );MB_CHK_ERR( rval );
7264  CHECK( v1 == v2 );
7265 
7266  v1.clear();
7267  v2.clear();
7268  rval = mb->get_entities_by_type( s2, MBMAXTYPE, v1, true );MB_CHK_ERR( rval );
7269  rval = mb->get_entities_by_handle( s2, v2, true );MB_CHK_ERR( rval );
7270  CHECK( v1 == v2 );
7271 
7272  rval = mb->get_number_entities_by_type( s1, MBMAXTYPE, c1, false );MB_CHK_ERR( rval );
7273  rval = mb->get_number_entities_by_handle( s1, c2, false );MB_CHK_ERR( rval );
7274  CHECK( c1 == c2 );
7275 
7276  rval = mb->get_number_entities_by_type( s2, MBMAXTYPE, c1, false );MB_CHK_ERR( rval );
7277  rval = mb->get_number_entities_by_handle( s2, c2, false );MB_CHK_ERR( rval );
7278  CHECK( c1 == c2 );
7279 
7280  rval = mb->get_number_entities_by_type( s2, MBMAXTYPE, c1, true );MB_CHK_ERR( rval );
7281  rval = mb->get_number_entities_by_handle( s2, c2, true );MB_CHK_ERR( rval );
7282  CHECK( c1 == c2 );
7283 
7284  r1.clear();
7285  rval = mb->get_entities_by_handle( s1, r1 );MB_CHK_ERR( rval );
7286  Tag t1;
7287  rval = mb->tag_get_handle( "maxtype1", 1, MB_TYPE_INTEGER, t1, MB_TAG_SPARSE | MB_TAG_EXCL );MB_CHK_ERR( rval );
7288  std::vector< int > d1( r1.size() );
7289  Range::iterator ri;
7290  std::vector< int >::iterator ii = d1.begin();
7291  for( ri = r1.begin(); ri != r1.end(); ++ri, ++ii )
7292  *ii = ( (int)ID_FROM_HANDLE( *ri ) ) % 20;
7293  rval = mb->tag_set_data( t1, r1, &d1[0] );MB_CHK_ERR( rval );
7294 
7295  r1.clear();
7296  r2.clear();
7297  rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7298  rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7299  rval = get_by_all_types_and_tag( mb, 0, &t1, 0, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7300  CHECK( r1 == r2 );
7301  CHECK( (unsigned)c1 == r2.size() );
7302 
7303  r1.clear();
7304  r2.clear();
7305  rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7306  rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7307  rval = get_by_all_types_and_tag( mb, s1, &t1, 0, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7308  CHECK( r1 == r2 );
7309  CHECK( (unsigned)c1 == r2.size() );
7310 
7311  r1.clear();
7312  r2.clear();
7313  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7314  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7315  rval = get_by_all_types_and_tag( mb, s2, &t1, 0, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7316  CHECK( r1 == r2 );
7317  CHECK( (unsigned)c1 == r2.size() );
7318 
7319  r1.clear();
7320  r2.clear();
7321  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7322  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7323  rval = get_by_all_types_and_tag( mb, s2, &t1, 0, 1, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7324  CHECK( r1 == r2 );
7325  CHECK( (unsigned)c1 == r2.size() );
7326 
7327  int value = 3;
7328  const void* vallist[2] = { &value, 0 };
7329 
7330  r1.clear();
7331  r2.clear();
7332  rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7333  rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7334  rval = get_by_all_types_and_tag( mb, 0, &t1, vallist, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7335  CHECK( r1 == r2 );
7336  CHECK( (unsigned)c1 == r2.size() );
7337 
7338  r1.clear();
7339  r2.clear();
7340  rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7341  rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7342  rval = get_by_all_types_and_tag( mb, s1, &t1, vallist, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7343  CHECK( r1 == r2 );
7344  CHECK( (unsigned)c1 == r2.size() );
7345 
7346  r1.clear();
7347  r2.clear();
7348  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7349  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7350  rval = get_by_all_types_and_tag( mb, s2, &t1, vallist, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7351  CHECK( r1 == r2 );
7352  CHECK( (unsigned)c1 == r2.size() );
7353 
7354  r1.clear();
7355  r2.clear();
7356  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7357  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7358  rval = get_by_all_types_and_tag( mb, s2, &t1, vallist, 1, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7359  CHECK( r1 == r2 );
7360  CHECK( (unsigned)c1 == r2.size() );
7361 
7362  r1.clear();
7363  r2.clear();
7364  rval = mb->get_entities_by_handle( s1, r1 );MB_CHK_ERR( rval );
7365  r2.insert( r1.back() );
7366  r1.clear();
7367  rval = mb->get_entities_by_handle( s2, r1 );MB_CHK_ERR( rval );
7368  r2.insert( r1.front() );
7369 
7370  Tag t2;
7371  rval = mb->tag_get_handle( "maxtype2", 1, MB_TYPE_INTEGER, t2, MB_TAG_DENSE | MB_TAG_EXCL );MB_CHK_ERR( rval );
7372  d1.resize( r2.size() );
7373  ii = d1.begin();
7374  ;
7375  for( ri = r2.begin(); ri != r2.end(); ++ri, ++ii )
7376  *ii = ( (int)ID_FROM_HANDLE( *ri ) ) % 2;
7377  rval = mb->tag_set_data( t2, r2, &d1[0] );MB_CHK_ERR( rval );
7378 
7379  Tag tags[] = { t1, t2 };
7380 
7381  r1.clear();
7382  r2.clear();
7383  rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7384  rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7385  rval = get_by_all_types_and_tag( mb, 0, tags, 0, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7386  CHECK( r1 == r2 );
7387  CHECK( (unsigned)c1 == r2.size() );
7388 
7389  r1.clear();
7390  r2.clear();
7391  rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7392  rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7393  rval = get_by_all_types_and_tag( mb, s1, tags, 0, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7394  CHECK( r1 == r2 );
7395  CHECK( (unsigned)c1 == r2.size() );
7396 
7397  r1.clear();
7398  r2.clear();
7399  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7400  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7401  rval = get_by_all_types_and_tag( mb, s2, tags, 0, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7402  CHECK( r1 == r2 );
7403  CHECK( (unsigned)c1 == r2.size() );
7404 
7405  r1.clear();
7406  r2.clear();
7407  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7408  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7409  rval = get_by_all_types_and_tag( mb, s2, tags, 0, 2, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7410  CHECK( r1 == r2 );
7411  CHECK( (unsigned)c1 == r2.size() );
7412 
7413  int val2 = 1;
7414  vallist[1] = &val2;
7415 
7416  r1.clear();
7417  r2.clear();
7418  rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7419  rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7420  rval = get_by_all_types_and_tag( mb, 0, tags, vallist, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7421  CHECK( r1 == r2 );
7422  CHECK( (unsigned)c1 == r2.size() );
7423 
7424  r1.clear();
7425  r2.clear();
7426  rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7427  rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7428  rval = get_by_all_types_and_tag( mb, s1, tags, vallist, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7429  CHECK( r1 == r2 );
7430  CHECK( (unsigned)c1 == r2.size() );
7431 
7432  r1.clear();
7433  r2.clear();
7434  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7435  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7436  rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
7437  CHECK( r1 == r2 );
7438  CHECK( (unsigned)c1 == r2.size() );
7439 
7440  r1.clear();
7441  r2.clear();
7442  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7443  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7444  rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
7445  CHECK( r1 == r2 );
7446  CHECK( (unsigned)c1 == r2.size() );
7447 
7448  r1.clear();
7449  r2.clear();
7450  rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false );MB_CHK_ERR( rval );
7451  rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false );MB_CHK_ERR( rval );
7452  rval = get_by_all_types_and_tag( mb, 0, tags, vallist, 2, r2, Interface::UNION, false );MB_CHK_ERR( rval );
7453  CHECK( r1 == r2 );
7454  CHECK( (unsigned)c1 == r2.size() );
7455 
7456  r1.clear();
7457  r2.clear();
7458  rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false );MB_CHK_ERR( rval );
7459  rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false );MB_CHK_ERR( rval );
7460  rval = get_by_all_types_and_tag( mb, s1, tags, vallist, 2, r2, Interface::UNION, false );MB_CHK_ERR( rval );
7461  CHECK( r1 == r2 );
7462  CHECK( (unsigned)c1 == r2.size() );
7463 
7464  r1.clear();
7465  r2.clear();
7466  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false );MB_CHK_ERR( rval );
7467  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false );MB_CHK_ERR( rval );
7468  rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::UNION, false );MB_CHK_ERR( rval );
7469  CHECK( r1 == r2 );
7470  CHECK( (unsigned)c1 == r2.size() );
7471 
7472  r1.clear();
7473  r2.clear();
7474  rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, true );MB_CHK_ERR( rval );
7475  rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, true );MB_CHK_ERR( rval );
7476  rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::UNION, true );MB_CHK_ERR( rval );
7477  CHECK( r1 == r2 );
7478  CHECK( (unsigned)c1 == r2.size() );
7479 
7480  return MB_SUCCESS;
7481 }
7482 
7483 /** Test behavior of various functions when passed the root set
7484  */
7486 {
7487  ErrorCode rval;
7488  Core moab;
7489  Interface* mb = &moab;
7490  EntityHandle rs = mb->get_root_set();
7491 
7492  // expect root set to have zero handle
7493  CHECK( !rs );
7494 
7495  // check type
7496  EntityType type = mb->type_from_handle( rs );
7497  CHECK( MBENTITYSET == type );
7498 
7499  // Create a set to test with
7500  EntityHandle some_set;
7501  rval = mb->create_meshset( MESHSET_SET, some_set );MB_CHK_ERR( rval );
7502  Range sets;
7503  sets.insert( some_set );
7504 
7505  int exp_dim = mb->dimension_from_handle( some_set );
7506  int dim = mb->dimension_from_handle( rs );
7507  CHECK( exp_dim == dim );
7508 
7509  // test some stuff that should fail
7510  rval = mb->clear_meshset( &rs, 1 );
7511  CHECK( MB_SUCCESS != rval );
7512  rval = mb->set_meshset_options( rs, MESHSET_ORDERED );
7513  CHECK( MB_SUCCESS != rval );
7514  rval = mb->subtract_meshset( rs, some_set );
7515  CHECK( MB_SUCCESS != rval );
7516  rval = mb->intersect_meshset( rs, some_set );
7517  CHECK( MB_SUCCESS != rval );
7518  rval = mb->unite_meshset( rs, some_set );
7519  CHECK( MB_SUCCESS != rval );
7520 
7521  // add/remove should fail for root set?
7522  rval = mb->add_entities( rs, &some_set, 1 );
7523  CHECK( MB_SUCCESS != rval );
7524  rval = mb->remove_entities( rs, &some_set, 1 );
7525  CHECK( MB_SUCCESS != rval );
7526  rval = mb->replace_entities( rs, &some_set, &some_set, 1 );
7527  CHECK( MB_SUCCESS != rval );
7528 
7529  // check flags
7530  unsigned flags;
7531  rval = mb->get_meshset_options( rs, flags );
7532  CHECK( flags & MESHSET_SET );
7533  CHECK( !( flags & MESHSET_ORDERED ) );
7534  CHECK( flags & MESHSET_TRACK_OWNER );
7535 
7536  // contains tests
7537  bool c = mb->contains_entities( rs, &some_set, 1 );
7538  CHECK( c );
7539 
7540  Range sets2;
7541  rval = mb->get_contained_meshsets( rs, sets2 );MB_CHK_ERR( rval );
7542  CHECK( sets == sets2 );
7543 
7544  int count;
7545  rval = mb->num_contained_meshsets( rs, &count );MB_CHK_ERR( rval );
7546  CHECK( count == (int)sets.size() );
7547 
7548  // The expected behavior for parent/child queries on the root set
7549  // is to return an error.
7550 
7551  rval = mb->get_parent_meshsets( rs, sets2 );
7552  CHECK( MB_SUCCESS != rval );
7553  rval = mb->get_parent_meshsets( rs, sets2, 2 );
7554  CHECK( MB_SUCCESS != rval );
7555 
7556  rval = mb->get_child_meshsets( rs, sets2 );
7557  CHECK( MB_SUCCESS != rval );
7558  rval = mb->get_child_meshsets( rs, sets2, 2 );
7559  CHECK( MB_SUCCESS != rval );
7560 
7561  rval = mb->num_parent_meshsets( rs, &count );
7562  CHECK( MB_SUCCESS != rval );
7563  rval = mb->num_parent_meshsets( rs, &count, 2 );
7564  CHECK( MB_SUCCESS != rval );
7565 
7566  rval = mb->num_child_meshsets( rs, &count );
7567  CHECK( MB_SUCCESS != rval );
7568  rval = mb->num_child_meshsets( rs, &count, 2 );
7569  CHECK( MB_SUCCESS != rval );
7570 
7571  rval = mb->add_parent_meshset( rs, some_set );
7572  CHECK( MB_SUCCESS != rval );
7573  rval = mb->add_parent_meshsets( rs, &some_set, 1 );
7574  CHECK( MB_SUCCESS != rval );
7575  rval = mb->add_child_meshset( rs, some_set );
7576  CHECK( MB_SUCCESS != rval );
7577  rval = mb->add_child_meshsets( rs, &some_set, 1 );
7578  CHECK( MB_SUCCESS != rval );
7579  rval = mb->add_parent_child( rs, some_set );
7580  CHECK( MB_SUCCESS != rval );
7581  rval = mb->remove_parent_child( rs, some_set );
7582  CHECK( MB_SUCCESS != rval );
7583  rval = mb->remove_parent_meshset( rs, some_set );
7584  CHECK( MB_SUCCESS != rval );
7585  rval = mb->remove_child_meshset( rs, some_set );
7586  CHECK( MB_SUCCESS != rval );
7587 
7588  return MB_SUCCESS;
7589 }
7590 
7591 /* Create a regular 2x2x2 hex mesh */
7593 {
7594  const double coords[] = { 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 1, 0, 1, 1, 0, 2, 1, 0, 0, 2, 0, 1, 2, 0, 2, 2, 0,
7595  0, 0, 1, 1, 0, 1, 2, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 0, 2, 1, 1, 2, 1, 2, 2, 1,
7596  0, 0, 2, 1, 0, 2, 2, 0, 2, 0, 1, 2, 1, 1, 2, 2, 1, 2, 0, 2, 2, 1, 2, 2, 2, 2, 2 };
7597  const size_t num_vtx = sizeof( coords ) / sizeof( double ) / 3;
7598  assert( num_vtx == 27u );
7599 
7600  const int conn[] = { 0, 1, 4, 3, 9, 10, 13, 12, 1, 2, 5, 4, 10, 11, 14, 13, 3, 4, 7, 6, 12, 13,
7601  16, 15, 4, 5, 8, 9, 13, 14, 17, 16, 9, 10, 13, 12, 18, 19, 22, 21, 10, 11, 14, 13,
7602  19, 20, 23, 22, 12, 13, 16, 15, 21, 22, 25, 24, 13, 14, 17, 18, 22, 23, 26, 25 };
7603  const size_t num_elem = sizeof( conn ) / sizeof( conn[0] ) / 8;
7604  assert( num_elem == 8u );
7605 
7606  EntityHandle verts[num_vtx], hexes[num_elem];
7607  for( size_t i = 0; i < num_vtx; ++i )
7608  {
7609  ErrorCode err = iface->create_vertex( coords + 3 * i, verts[i] );
7610  if( MB_SUCCESS != err ) return err;
7611  }
7612 
7613  for( size_t i = 0; i < num_elem; ++i )
7614  {
7615  EntityHandle c[8];
7616  for( int j = 0; j < 8; ++j )
7617  {
7618  assert( conn[8 * i + j] < (int)num_vtx );
7619  c[j] = verts[conn[8 * i + j]];
7620  }
7621  ErrorCode err = iface->create_element( MBHEX, c, 8, hexes[i] );
7622  if( MB_SUCCESS != err ) return err;
7623  }
7624 
7625  return MB_SUCCESS;
7626 }
7627 
7628 inline bool contained( const std::vector< EntityHandle >& list, EntityHandle h )
7629 {
7630  std::vector< EntityHandle >::const_iterator i;
7631  i = std::lower_bound( list.begin(), list.end(), h );
7632  return i != list.end() && *i == h;
7633 }
7634 
7636 {
7637  ErrorCode rval;
7638 
7639  // get sorted array of vertex handles so that we can
7640  // check that all vertices in connectivity are valid
7641  // handles
7642  std::vector< EntityHandle > vertices, storage;
7643  rval = iface->get_entities_by_type( 0, MBVERTEX, vertices );MB_CHK_ERR( rval );
7644  std::sort( vertices.begin(), vertices.end() );
7645 
7646  // get all the elements
7647  Range elements, tmp;
7648  for( int d = 1; d < 4; ++d )
7649  {
7650  tmp.clear();
7651  rval = iface->get_entities_by_dimension( 0, d, tmp );MB_CHK_ERR( rval );
7652  elements.merge( tmp );
7653  }
7654 
7655  // check that all connectivity handles are valid
7656  Range::iterator it;
7657  ErrorCode result = MB_SUCCESS;
7658  for( it = elements.begin(); it != elements.end(); ++it )
7659  {
7660  const EntityHandle* conn;
7661  int len;
7662  rval = iface->get_connectivity( *it, conn, len, false, &storage );MB_CHK_ERR( rval );
7663  for( int i = 0; i < len; ++i )
7664  {
7665  if( !contained( vertices, conn[i] ) )
7666  {
7667  printf( "Invalid handle (%s %d) in connectivity of %s %d\n",
7668  CN::EntityTypeName( TYPE_FROM_HANDLE( conn[i] ) ), (int)ID_FROM_HANDLE( conn[i] ),
7669  CN::EntityTypeName( TYPE_FROM_HANDLE( *it ) ), (int)ID_FROM_HANDLE( *it ) );
7670  result = MB_FAILURE;
7671  }
7672  }
7673  }
7674 
7675  return result;
7676 }
7677 
7678 static void usage( const char* exe )
7679 {
7680  cerr << "Usage: " << exe << " [-nostress] [-d input_file_dir]\n";
7681  exit( 1 );
7682 }
7683 
7686 #define RUN_TEST_ERR( A ) _run_test( ( A ), #A )
7687 
7688 typedef ErrorCode ( *TestFunc )();
7689 static int _run_test( TestFunc func, const char* func_str )
7690 {
7691  ++number_tests;
7692  return run_test( func, func_str );
7693 }
7694 
7695 /*!
7696  main routine for test harness
7697 */
7698 int main( int argc, char* argv[] )
7699 {
7700 #ifdef MOAB_HAVE_MPI
7701  int fail = MPI_Init( &argc, &argv );
7702  if( fail ) return fail;
7703 #endif
7704 
7705  argv0 = argv[0];
7706 
7707  // Check command line arg to see if we should avoid doing the stress test
7708 #ifdef MOAB_HAVE_NETCDF
7709  bool stress_test = true;
7710 #endif
7711 
7712  std::cout << "Size of mConnMap = " << sizeof( CN::mConnectivityMap ) << std::endl;
7713  std::cout << "Size of mUpConnMap = " << sizeof( CN::mUpConnMap ) << std::endl;
7714  std::cout << "Size of CN = " << sizeof( CN ) << std::endl;
7715 
7716  for( int i = 1; i < argc; ++i )
7717  {
7718 
7719  if( string( argv[i] ) == "-h" || string( argv[i] ) == "--help" ) usage( argv[0] );
7720 #if MOAB_HAVE_NETCDF
7721  else if( string( argv[i] ) == "-nostress" )
7722  stress_test = false;
7723 #endif
7724  else
7725  {
7726  cerr << "Invalid argument: " << argv[i] << endl;
7727  usage( argv[0] );
7728  }
7729  }
7730 
7731  // Print out Header information
7732 
7733  cout << "\n\nMOAB Comprehensive test suite:\n\n";
7734 
7757 #if MOAB_HAVE_NETCDF
7758  number_tests_failed += RUN_TEST_ERR( mb_adjacencies_test );
7759  number_tests_failed += RUN_TEST_ERR( mb_tags_test );
7760  number_tests_failed += RUN_TEST_ERR( mb_delete_mesh_test );
7761  number_tests_failed += RUN_TEST_ERR( mb_entity_conversion_test );
7762  number_tests_failed += RUN_TEST_ERR( mb_mesh_set_tracking_test );
7763 #endif
7809 #if MOAB_HAVE_NETCDF
7810  number_tests_failed += RUN_TEST_ERR( mb_merge_test );
7811  if( stress_test ) number_tests_failed += RUN_TEST_ERR( mb_stress_test );
7812 #endif
7813 
7814  // summary
7815 
7816  cout << "\nMB TEST SUMMARY: \n"
7817  << " Number Tests: " << number_tests << "\n"
7818  << " Number Successful: " << number_tests - number_tests_failed << "\n"
7819  << " Number Failed: " << number_tests_failed << "\n\n";
7820 
7821 #ifdef MOAB_HAVE_MPI
7822  fail = MPI_Finalize();
7823  if( fail ) return fail;
7824 #endif
7825 
7826  return number_tests_failed;
7827 }