MOAB: Mesh Oriented datABase  (version 5.3.0)
MBTest.cpp
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 /*!
00017   MBTest.cpp
00018   Test Harness for MB mesh database system
00019 */
00020 
00021 #ifdef WIN32
00022 #ifdef _DEBUG
00023 // turn off warnings that say they debugging identifier has been truncated
00024 // this warning comes up when using some STL containers
00025 #pragma warning( disable : 4786 )
00026 #endif
00027 #endif
00028 
00029 #include <iostream>
00030 #include <fstream>
00031 #include <algorithm>
00032 #include <cstdio>
00033 #include <ctime>
00034 #include <cassert>
00035 #include <cmath>
00036 #include <cstdio>
00037 #include "moab/Interface.hpp"
00038 #include "MBTagConventions.hpp"
00039 #include "moab/Range.hpp"
00040 #include "moab/Skinner.hpp"
00041 #include "moab/MeshTopoUtil.hpp"
00042 #include "moab/CN.hpp"
00043 #include "moab/OrientedBox.hpp"
00044 #include "moab/CartVect.hpp"
00045 #include "moab/WriteUtilIface.hpp"
00046 
00047 #ifdef MOAB_HAVE_MPI
00048 #include "moab_mpi.h"
00049 #endif
00050 
00051 #ifndef IS_BUILDING_MB
00052 #define IS_BUILDING_MB
00053 #endif
00054 #include "Internals.hpp"
00055 #include "moab/Core.hpp"
00056 #include "SequenceManager.hpp"
00057 #include "EntitySequence.hpp"
00058 #include "RangeSeqIntersectIter.hpp"
00059 #include "moab/Error.hpp"
00060 #include "moab/ScdInterface.hpp"
00061 
00062 /* Use the following define to specify that our tests
00063    return an error code and not the default void */
00064 #define TEST_USES_ERR_CODES
00065 #include "TestUtil.hpp"
00066 
00067 using namespace std;
00068 using namespace moab;
00069 
00070 #define CHKERR( A )                                                                                        \
00071     do                                                                                                     \
00072     {                                                                                                      \
00073         if( MB_SUCCESS != ( A ) )                                                                          \
00074         {                                                                                                  \
00075             std::cerr << "Failure (error code " << ( A ) << ") at " __FILE__ ":" << __LINE__ << std::endl; \
00076             return A;                                                                                      \
00077         }                                                                                                  \
00078     } while( false )
00079 
00080 #ifdef MOAB_HAVE_NETCDF
00081 ErrorCode load_file_one( Interface* iface )
00082 {
00083     std::string file_name = TestDir + "/mbtest1.g";
00084     ErrorCode error       = iface->load_mesh( file_name.c_str() );
00085     if( MB_SUCCESS != error )
00086     {
00087         std::cout << "Failed to load input file: " << file_name << std::endl;
00088         std::string error_reason;
00089         iface->get_last_error( error_reason );
00090         cout << error_reason << std::endl;
00091     }
00092     return error;
00093 }
00094 #endif
00095 
00096 /* Create a regular 2x2x2 hex mesh */
00097 ErrorCode create_some_mesh( Interface* iface );
00098 
00099 ErrorCode check_valid_connectivity( Interface* iface );
00100 
00101 /*!
00102   @test
00103   Vertex Coordinates
00104   @li Get coordinates of vertex 1 correctly
00105   @li Get coordinates of vertex 8 correctly
00106   @li Get coordinates of vertex 6 correctly
00107 */
00108 ErrorCode mb_vertex_coordinate_test()
00109 {
00110     Core moab;
00111     Interface* MB   = &moab;
00112     ErrorCode error = create_some_mesh( MB );MB_CHK_ERR( error );
00113 
00114     Range vertices;
00115     error = MB->get_entities_by_type( 0, MBVERTEX, vertices );MB_CHK_ERR( error );
00116 
00117     std::vector< double > all_coords( 3 * vertices.size() );
00118     double* coord_iter = &all_coords[0];
00119     for( Range::iterator iter = vertices.begin(); iter != vertices.end(); ++iter )
00120     {
00121         error = MB->get_coords( &( *iter ), 1, coord_iter );MB_CHK_ERR( error );
00122         coord_iter += 3;
00123     }
00124 
00125     // check blocked coordinates
00126     const size_t N = vertices.size() + 1;
00127     std::vector< double > x( N ), y( N ), z( N );
00128     // set last value so we can check later that nothing wrote past the
00129     // intended end of an array
00130     x[vertices.size()] = y[vertices.size()] = z[vertices.size()] = -3.14159;
00131     error                                                        = MB->get_coords( vertices, &x[0], &y[0], &z[0] );
00132     for( size_t i = 0; i < vertices.size(); ++i )
00133     {
00134         CHECK_REAL_EQUAL( all_coords[3 * i], x[i], 1E-12 );
00135         CHECK_REAL_EQUAL( all_coords[3 * i + 1], y[i], 1E-12 );
00136         CHECK_REAL_EQUAL( all_coords[3 * i + 2], z[i], 1E-12 );
00137     }
00138     // checkthat get_coords did not write past intended end of arrays
00139     CHECK_REAL_EQUAL( -3.14159, x[vertices.size()], 1E-12 );
00140     CHECK_REAL_EQUAL( -3.14159, y[vertices.size()], 1E-12 );
00141     CHECK_REAL_EQUAL( -3.14159, z[vertices.size()], 1E-12 );
00142 
00143     // add invalid handle to end of range and try query again
00144     vertices.insert( vertices.back() + 1 );
00145     error = MB->get_coords( vertices, &x[0], &y[0], &z[0] );
00146     CHECK_EQUAL( MB_ENTITY_NOT_FOUND, error );
00147 
00148     // Try getting coordinates for a hex (should fail)
00149     Range hexes;
00150     error = MB->get_entities_by_type( 0, MBHEX, hexes );MB_CHK_ERR( error );
00151     EntityHandle handle = hexes.front();
00152     error               = MB->get_coords( &handle, 1, &x[0] );MB_CHK_ERR( error );
00153     CHECK_REAL_EQUAL( 0.5, x[0], 1E-12 );
00154     CHECK_REAL_EQUAL( 0.5, x[1], 1E-12 );
00155     CHECK_REAL_EQUAL( 0.5, x[2], 1E-12 );
00156 
00157     return MB_SUCCESS;
00158 }
00159 
00160 /*!
00161   @test
00162   MB Vertex Tag Test
00163   @li Add, Set and correctly get an int tag
00164   @li Add, Set and correctly get a boolean tag
00165   @li Add, Set and correctly get a double tag
00166   @li Add, Set and correctly get a struct tag
00167 */
00168 ErrorCode mb_vertex_tag_test()
00169 {
00170     Core moab;
00171     Interface* MB   = &moab;
00172     ErrorCode error = create_some_mesh( MB );
00173     if( MB_SUCCESS != error ) return error;
00174 
00175     // Add an int Vertex Tag to the database
00176 
00177     Tag tag_id;
00178 
00179     // Create a dense tag for all vertices
00180     error = MB->tag_get_handle( "int_tag", 1, MB_TYPE_INTEGER, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
00181     if( error != MB_SUCCESS ) return error;
00182 
00183     // put a value in vertex 1 and retrieve
00184     std::vector< EntityHandle > verts;
00185     error = MB->get_entities_by_type( 0, MBVERTEX, verts );
00186     if( MB_SUCCESS != error ) return error;
00187     EntityHandle handle = verts[0];
00188     int input_value     = 11;
00189     error               = MB->tag_set_data( tag_id, &handle, 1, &input_value );
00190     if( MB_SUCCESS != error ) return error;
00191 
00192     int output_value;
00193     error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
00194     if( MB_SUCCESS != error )
00195         return error;
00196     else if( output_value != input_value )
00197         return MB_FAILURE;
00198 
00199     // put a value in vertex 5 and retrieve
00200 
00201     handle      = verts[5];
00202     input_value = 11;
00203     error       = MB->tag_set_data( tag_id, &handle, 1, &input_value );
00204     if( MB_SUCCESS != error ) return error;
00205     error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
00206     if( MB_SUCCESS != error )
00207         return error;
00208     else if( output_value != input_value )
00209         return MB_FAILURE;
00210 
00211     // put a value in vertex 98088234 which doesn't exist
00212     handle      = *std::max_element( verts.begin(), verts.end() ) + 1;
00213     input_value = 11;
00214 
00215     error = MB->tag_set_data( tag_id, &handle, 1, &input_value );
00216     if( error == MB_SUCCESS ) return error;
00217 
00218     error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
00219     if( error == MB_SUCCESS ) return error;
00220 
00221     if( output_value != input_value ) return MB_FAILURE;
00222 
00223     // Add a bool Vertex Tag to the database
00224 
00225     error = MB->tag_get_handle( "bool_tag", sizeof( bool ), MB_TYPE_OPAQUE, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
00226     if( error != MB_SUCCESS ) return error;
00227 
00228     // put a value in vertex 5 and retrieve
00229 
00230     handle                 = verts[5];
00231     bool bool_input_value  = true;
00232     bool bool_output_value = false;
00233     error                  = MB->tag_set_data( tag_id, &handle, 1, &bool_input_value );
00234     if( error != MB_SUCCESS ) return error;
00235     error = MB->tag_get_data( tag_id, &handle, 1, &bool_output_value );
00236     if( error != MB_SUCCESS )
00237         return error;
00238     else if( bool_output_value != bool_input_value )
00239         return MB_FAILURE;
00240 
00241     // Add a double Vertex Tag to the database
00242 
00243     error = MB->tag_get_handle( "double_tag", 1, MB_TYPE_DOUBLE, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
00244     if( error != MB_SUCCESS ) return error;
00245 
00246     // put a value in vertex 8: and retrieve
00247 
00248     handle                     = verts[8];
00249     double double_input_value  = 1.0;
00250     double double_output_value = 0.0;
00251     error                      = MB->tag_set_data( tag_id, &handle, 1, &double_input_value );
00252     if( error != MB_SUCCESS ) return error;
00253 
00254     error = MB->tag_get_data( tag_id, &handle, 1, &double_output_value );
00255     if( error != MB_SUCCESS )
00256         return error;
00257     else if( double_output_value != double_input_value )
00258         return MB_FAILURE;
00259 
00260     // Add a struct Vertex Tag to the database
00261 
00262     struct TagStruct
00263     {
00264         int test_int;
00265         double test_double;
00266     };
00267     error =
00268         MB->tag_get_handle( "struct_tag", sizeof( TagStruct ), MB_TYPE_OPAQUE, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
00269     if( error != MB_SUCCESS ) return error;
00270 
00271     // put a value in vertex 7 and retrieve
00272 
00273     handle = verts[7];
00274     TagStruct input_tag_struct;
00275     input_tag_struct.test_int    = 55;
00276     input_tag_struct.test_double = -1.2345;
00277     TagStruct output_tag_struct;
00278     error = MB->tag_set_data( tag_id, &handle, 1, &input_tag_struct );
00279     if( error != MB_SUCCESS ) return error;
00280     error = MB->tag_get_data( tag_id, &handle, 1, &output_tag_struct );
00281     if( error != MB_SUCCESS )
00282         return error;
00283     else if( output_tag_struct.test_int != input_tag_struct.test_int ||
00284              output_tag_struct.test_double != input_tag_struct.test_double )
00285         return MB_FAILURE;
00286 
00287     // Create sparse tags for 10 random entities including some outside the
00288     // range of allowable entities.
00289 
00290     error = MB->tag_get_handle( "sparse_int_tag", 1, MB_TYPE_INTEGER, tag_id, MB_TAG_SPARSE | MB_TAG_EXCL );
00291 
00292     if( error != MB_SUCCESS ) return error;
00293 
00294     // print_yes = true;
00295     int i;
00296     for( i = 0; i < 10; i++ )
00297     {
00298         // use invalid handles for odd values
00299 
00300         if( i % 2 )
00301             handle = verts[i] + *std::max_element( verts.begin(), verts.end() );
00302         else
00303             handle = verts[i];
00304 
00305         input_value = 11;
00306         error       = MB->tag_set_data( tag_id, &handle, 1, &input_value );
00307 
00308         // should fail on odd values of i
00309         if( !( i % 2 ) )
00310         {
00311             if( error != MB_SUCCESS )  // even case and if failed
00312                 return error;
00313         }
00314         else
00315         {
00316             if( error == MB_SUCCESS )  // odd case and it says it worked!
00317                 return MB_FAILURE;
00318         }
00319 
00320         error = MB->tag_get_data( tag_id, &handle, 1, &output_value );
00321         if( ( i % 2 ) && error != MB_FAILURE && error != MB_TAG_NOT_FOUND ) return error;
00322 
00323         if( ( i % 2 ) && output_value != input_value ) return MB_FAILURE;
00324     }
00325 
00326     // get the tag_name of the last tag created above
00327     std::string int_tag_name;
00328     error = MB->tag_get_name( tag_id, int_tag_name );
00329     if( error != MB_SUCCESS ) return error;
00330 
00331     if( int_tag_name != "sparse_int_tag" ) return MB_FAILURE;
00332 
00333     // get the tag handle of the last tag created above
00334     Tag int_tag_handle;
00335     error = MB->tag_get_handle( int_tag_name.c_str(), 1, MB_TYPE_INTEGER, int_tag_handle );
00336     if( MB_SUCCESS != error ) return error;
00337 
00338     if( int_tag_handle != tag_id ) return MB_FAILURE;
00339 
00340     // test tag_get_tags_on_entity and tag_delete_data
00341     std::vector< Tag > all_tags;
00342     handle = verts[0];
00343     error  = MB->tag_get_tags_on_entity( handle, all_tags );
00344     if( MB_SUCCESS != error ) return error;
00345 
00346     if( !all_tags.empty() )
00347     {
00348         error = MB->tag_delete_data( all_tags[0], &handle, 1 );
00349         if( MB_SUCCESS != error ) return error;
00350 
00351         error = MB->tag_delete( all_tags[0] );
00352         if( MB_SUCCESS != error ) return error;
00353     }
00354     // delete tags test
00355 
00356     // delete 2 of the sparse tags that were created above.
00357     handle = verts[2];
00358     error  = MB->tag_delete_data( tag_id, &handle, 1 );
00359     if( error != MB_SUCCESS ) return error;
00360 
00361     handle = verts[6];
00362     error  = MB->tag_delete_data( tag_id, &handle, 1 );
00363     if( error != MB_SUCCESS ) return error;
00364 
00365     // delete all the rest of the sparse tags.
00366 
00367     error = MB->tag_delete( tag_id );
00368     if( error != MB_SUCCESS ) return error;
00369 
00370     // delete the dense tag named bool_tag
00371     Tag bool_tag_handle;
00372     error = MB->tag_get_handle( "bool_tag", sizeof( bool ), MB_TYPE_OPAQUE, bool_tag_handle );
00373     if( error != MB_SUCCESS ) return error;
00374 
00375     error = MB->tag_delete( bool_tag_handle );
00376     if( error != MB_SUCCESS ) return error;
00377 
00378     return error;
00379 }
00380 
00381 ErrorCode mb_temporary_test()
00382 {
00383     Core moab;
00384     Interface* gMB = &moab;
00385 
00386     double array[3] = { 0.0, 0.0, 0.0 };
00387     EntityHandle h_node1;
00388     ErrorCode result = gMB->create_vertex( array, h_node1 );
00389     if( MB_SUCCESS != result ) return result;
00390 
00391     EntityHandle ordered_meshset1;
00392     result = gMB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, ordered_meshset1 );
00393     if( MB_SUCCESS != result ) return result;
00394 
00395     EntityHandle ordered_meshset2;
00396     result = gMB->create_meshset( MESHSET_ORDERED | MESHSET_TRACK_OWNER, ordered_meshset2 );
00397     if( MB_SUCCESS != result ) return result;
00398 
00399     result = gMB->add_entities( ordered_meshset1, &h_node1, 1 );
00400     if( MB_SUCCESS != result ) return result;
00401 
00402     result = gMB->remove_entities( ordered_meshset1, &h_node1, 1 );
00403     if( MB_SUCCESS != result ) return result;
00404 
00405     result = gMB->add_entities( ordered_meshset2, &h_node1, 1 );
00406     if( MB_SUCCESS != result ) return result;
00407 
00408     bool create_if_missing = false;
00409     std::vector< EntityHandle > meshsets;
00410     result = gMB->get_adjacencies( &h_node1, 1, 4, create_if_missing, meshsets );
00411     if( MB_SUCCESS != result ) return result;
00412 
00413     if( 1u != meshsets.size() ) return MB_FAILURE;
00414 
00415     return MB_SUCCESS;
00416 }
00417 
00418 ErrorCode mb_adjacent_vertex_test()
00419 {
00420     Core moab;
00421     Interface* mb  = &moab;
00422     ErrorCode rval = create_some_mesh( mb );
00423     if( MB_SUCCESS != rval ) return rval;
00424 
00425     Range hexes, expt_vert, got_vert, some_hexes;
00426     Range::const_iterator i, j;
00427     int n;
00428 
00429     // get all hexes
00430     rval = mb->get_entities_by_type( 0, MBHEX, hexes );
00431     if( rval != MB_SUCCESS ) return rval;
00432     if( hexes.empty() )  // can't do test if no elements
00433         return MB_FAILURE;
00434 
00435     // get every third hex and its vertices
00436     n = 0;
00437     for( i = hexes.begin(); i != hexes.end(); ++i )
00438     {
00439         if( ++n % 3 ) continue;
00440         some_hexes.insert( *i );
00441         const EntityHandle* conn;
00442         int len;
00443         rval = mb->get_connectivity( *i, conn, len );
00444         if( MB_SUCCESS != rval ) return rval;
00445         for( int k = 0; k < len; ++k )
00446             expt_vert.insert( conn[k] );
00447     }
00448 
00449     // use get_adjacencies to get vertices
00450     rval = mb->get_adjacencies( some_hexes, 0, false, got_vert, Interface::UNION );
00451     if( MB_SUCCESS != rval )
00452     {
00453         std::cout << "get_adjacencies failed with error code " << rval << std::endl;
00454         return rval;
00455     }
00456 
00457     i = expt_vert.begin();
00458     j = got_vert.begin();
00459     while( i != expt_vert.end() && j != got_vert.end() )
00460     {
00461         if( *i < *j )
00462         {
00463             std::cout << "Result missing vertex: " << *i << std::endl;
00464             return MB_FAILURE;
00465         }
00466         else if( *j < *i )
00467         {
00468             std::cout << "Result contains extra vertex: " << *j << std::endl;
00469             return MB_FAILURE;
00470         }
00471         ++i;
00472         ++j;
00473     }
00474 
00475     if( i != expt_vert.end() )
00476     {
00477         std::cout << "Result missing vertex: " << *i << std::endl;
00478         return MB_FAILURE;
00479     }
00480     else if( j != got_vert.end() )
00481     {
00482         std::cout << "Result contains extra vertex: " << *j << std::endl;
00483         return MB_FAILURE;
00484     }
00485 
00486     return MB_SUCCESS;
00487 }
00488 #ifdef MOAB_HAVE_NETCDF
00489 ErrorCode mb_adjacencies_test()
00490 {
00491     Core moab;
00492     Interface* mb    = &moab;
00493     ErrorCode result = load_file_one( mb );
00494     if( MB_SUCCESS != result ) return result;
00495 
00496     // this test does the following:
00497     // 1. For each element, creates vertex-element adjacencies (only for
00498     //    lowest-id vertex)
00499     // 2. Creates all lower-order ancillary entities
00500     // 3. Checks for proper number of same
00501     //
00502     // assume mesh has already been read
00503 
00504     EntityType seq_type;
00505     Range handle_range;
00506 
00507     // lets create a skin of the hexes
00508     // this may be far from being the most efficient, but
00509     // it certainly does exercise the adjacency routines
00510 
00511     Range::iterator iter;
00512     Range::reverse_iterator riter;
00513 
00514     // first get the hexes
00515     Range hexes;
00516     result = mb->get_entities_by_type( 0, MBHEX, hexes );
00517     if( MB_SUCCESS != result ) return result;
00518 
00519     unsigned int num_hexes = hexes.size();
00520 
00521     // make sure we got hexes
00522     for( riter = hexes.rbegin(); riter != hexes.rend(); ++riter )
00523     {
00524         if( TYPE_FROM_HANDLE( *riter ) != MBHEX ) return MB_FAILURE;
00525     }
00526 
00527     // get all the nodes that these hexes are connected to
00528     Range nodes;
00529     result = mb->get_adjacencies( hexes, 0, false, nodes, Interface::UNION );
00530     if( MB_SUCCESS != result ) return result;
00531 
00532     // make sure we got nodes
00533     for( iter = nodes.begin(); iter != nodes.end(); ++iter )
00534     {
00535         if( TYPE_FROM_HANDLE( *iter ) != MBVERTEX ) return MB_FAILURE;
00536     }
00537 
00538     // find the interior nodes; assume a structured mesh
00539     Range interior_nodes;
00540     std::vector< EntityHandle > attached_hexes;
00541     for( iter = nodes.begin(); iter != nodes.end(); )
00542     {
00543         attached_hexes.clear();
00544         result = mb->get_adjacencies( &( *iter ), 1, 3, false, attached_hexes );
00545         if( MB_SUCCESS != result ) return result;
00546         attached_hexes.erase( std::remove_if( attached_hexes.begin(), attached_hexes.end(),
00547                                               type_not_equals( mb, MBHEX ) ),
00548                               attached_hexes.end() );
00549 
00550         // if this node has less than 8 hexes attached to it, it is not
00551         // an interior node
00552         if( attached_hexes.size() == 8 )
00553         {
00554             // add to the interior nodes list and remove from the nodes list
00555             interior_nodes.insert( *iter );
00556             iter = nodes.erase( iter );
00557         }
00558         else
00559             ++iter;
00560     }
00561 
00562     // get interior quads from interior nodes
00563     Range interior_quads;
00564     result = mb->get_adjacencies( interior_nodes, 2, true, interior_quads, Interface::UNION );
00565     if( MB_SUCCESS != result ) return result;
00566 
00567     // get a list of quads generated adjacent to the exterior nodes
00568     Range temp_quads, exterior_quads;
00569     result = mb->get_adjacencies( nodes, 2, true, temp_quads, Interface::UNION );
00570     if( MB_SUCCESS != result ) return result;
00571 
00572     // now remove any interior quads from the previous quads list
00573     // and we should be left with exterior quads
00574     std::set_difference( temp_quads.begin(), temp_quads.end(), interior_quads.begin(), interior_quads.end(),
00575                          range_inserter( exterior_quads ) );
00576 
00577     // check to make sure we have the right number of quads; for hexes, should be
00578     // .5(6*num_hexes - num_exterior_quads)
00579     unsigned int num_expected_int_quads = ( 6 * num_hexes - exterior_quads.size() ) / 2;
00580     if( num_expected_int_quads != interior_quads.size() ) return MB_FAILURE;
00581 
00582     // delete the interior quads
00583     result = mb->delete_entities( interior_quads );
00584     if( MB_SUCCESS != result ) return result;
00585 
00586     Range remaining_quads;
00587     result = mb->get_entities_by_type( 0, MBQUAD, remaining_quads );
00588     if( MB_SUCCESS != result ) return result;
00589 
00590     if( remaining_quads.size() != exterior_quads.size() ) return MB_FAILURE;
00591 
00592     // 3. Checks for proper number of same
00593     // re-retrieve and store the handle ranges for all element types
00594 
00595     int num_ents;
00596 
00597     for( seq_type = MBEDGE; seq_type != MBENTITYSET; seq_type++ )
00598     {
00599         handle_range.clear();
00600 
00601         result = mb->get_entities_by_type( 0, seq_type, handle_range );
00602         if( MB_SUCCESS != result ) return result;
00603 
00604         result = mb->get_number_entities_by_type( 0, seq_type, num_ents );
00605         if( MB_SUCCESS != result ) return result;
00606 
00607         if( handle_range.size() != (unsigned int)num_ents ) return MB_FAILURE;
00608     }
00609 
00610     return result;
00611 }
00612 
00613 #endif
00614 
00615 ErrorCode mb_adjacencies_create_delete_test()
00616 {
00617     Core moab;
00618     Interface* mb = &moab;
00619     ErrorCode rval;
00620 
00621     double coords[] = { 0, 0, 0, 2, 0, 0, 1, 2, 0 };
00622     Range verts;
00623     rval = mb->create_vertices( coords, 3, verts );
00624     if( MB_SUCCESS != rval ) return rval;
00625     if( verts.size() != 3 ) return MB_FAILURE;
00626     EntityHandle vert_arr[3];
00627 
00628     EntityHandle tri;
00629     std::copy( verts.begin(), verts.end(), vert_arr );
00630     rval = mb->create_element( MBTRI, vert_arr, 3, tri );
00631     if( MB_SUCCESS != rval ) return rval;
00632 
00633     vert_arr[2] = vert_arr[0];
00634     EntityHandle forward_edge, reverse_edge;
00635     rval = mb->create_element( MBEDGE, vert_arr, 2, forward_edge );
00636     if( MB_SUCCESS != rval ) return rval;
00637 
00638     std::vector< EntityHandle > results;
00639     rval = mb->get_adjacencies( &forward_edge, 1, 2, false, results );
00640     if( results.size() != 1 || results.front() != tri )
00641     {
00642         std::cerr << "Adjacency query from forward edge to tri failed at " << __FILE__ << ":" << __LINE__ << std::endl;
00643         return MB_FAILURE;
00644     }
00645     results.clear();
00646     rval = mb->get_adjacencies( &tri, 1, 1, false, results );
00647     if( results.size() != 1 || results.front() != forward_edge )
00648     {
00649         std::cerr << "Adjacency query from tri to forward edge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
00650         return MB_FAILURE;
00651     }
00652 
00653     rval = mb->delete_entities( &forward_edge, 1 );
00654     if( MB_SUCCESS != rval ) return rval;
00655 
00656     results.clear();
00657     rval = mb->get_adjacencies( &tri, 1, 1, false, results );
00658     if( !results.empty() )
00659     {
00660         std::cerr << "Adjacency query from tri returned non-existent edge at " << __FILE__ << ":" << __LINE__
00661                   << std::endl;
00662         return MB_FAILURE;
00663     }
00664 
00665     rval = mb->create_element( MBEDGE, vert_arr + 1, 2, reverse_edge );
00666     if( MB_SUCCESS != rval ) return rval;
00667 
00668     results.clear();
00669     rval = mb->get_adjacencies( &reverse_edge, 1, 2, false, results );
00670     if( results.size() != 1 || results.front() != tri )
00671     {
00672         std::cerr << "Adjacency query from reverse edge to tri failed at " << __FILE__ << ":" << __LINE__ << std::endl;
00673         return MB_FAILURE;
00674     }
00675     results.clear();
00676     rval = mb->get_adjacencies( &tri, 1, 1, false, results );
00677     if( results.size() != 1 || results.front() != reverse_edge )
00678     {
00679         std::cerr << "Adjacency query from tri to reverse edge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
00680         return MB_FAILURE;
00681     }
00682 
00683     return MB_SUCCESS;
00684 }
00685 
00686 static ErrorCode create_two_hex_full_mesh( Interface* mb, EntityHandle vertices[12], EntityHandle hexes[2],
00687                                            EntityHandle hex1_faces[6], EntityHandle hex2_faces[6],
00688                                            EntityHandle hex1_edges[12], EntityHandle hex2_edges[12] )
00689 {
00690     ErrorCode rval;
00691     // create a simple mesh containing 2 hexes
00692     const double coords[] = { 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 1, 0, 1, 1, 0, 2, 1, 0,
00693                               0, 0, 1, 1, 0, 1, 2, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1 };
00694     for( int i = 0; i < 12; ++i )
00695         if( MB_SUCCESS != mb->create_vertex( coords + 3 * i, vertices[i] ) ) return MB_FAILURE;
00696     EntityHandle hex1_conn[]           = { vertices[6], vertices[7],  vertices[1], vertices[0],
00697                                  vertices[9], vertices[10], vertices[4], vertices[3] };
00698     EntityHandle hex2_conn[]           = { vertices[7],  vertices[8],  vertices[2], vertices[1],
00699                                  vertices[10], vertices[11], vertices[5], vertices[4] };
00700     EntityHandle shared_quad_conn[]    = { vertices[7], vertices[1], vertices[4], vertices[10] };
00701     EntityHandle hex1_face_conn[][4]   = { { vertices[6], vertices[7], vertices[10], vertices[9] },
00702                                          { vertices[7], vertices[6], vertices[0], vertices[1] },
00703                                          { vertices[1], vertices[0], vertices[3], vertices[4] },
00704                                          { vertices[9], vertices[10], vertices[4], vertices[3] },
00705                                          { vertices[3], vertices[0], vertices[6], vertices[9] } };
00706     EntityHandle hex2_face_conn[][4]   = { { vertices[7], vertices[8], vertices[11], vertices[10] },
00707                                          { vertices[8], vertices[7], vertices[1], vertices[2] },
00708                                          { vertices[2], vertices[1], vertices[4], vertices[5] },
00709                                          { vertices[10], vertices[11], vertices[5], vertices[4] },
00710                                          { vertices[5], vertices[2], vertices[8], vertices[11] } };
00711     EntityHandle shared_edge_conn[][2] = { { vertices[1], vertices[7] },
00712                                            { vertices[7], vertices[10] },
00713                                            { vertices[10], vertices[4] },
00714                                            { vertices[4], vertices[1] } };
00715     EntityHandle hex1_edge_conn[][2]   = { { vertices[6], vertices[7] }, { vertices[9], vertices[10] },
00716                                          { vertices[3], vertices[4] }, { vertices[0], vertices[1] },
00717                                          { vertices[6], vertices[9] }, { vertices[9], vertices[3] },
00718                                          { vertices[3], vertices[0] }, { vertices[0], vertices[6] } };
00719     EntityHandle hex2_edge_conn[][2]   = { { vertices[7], vertices[8] },  { vertices[10], vertices[11] },
00720                                          { vertices[4], vertices[5] },  { vertices[1], vertices[2] },
00721                                          { vertices[8], vertices[11] }, { vertices[11], vertices[5] },
00722                                          { vertices[5], vertices[2] },  { vertices[2], vertices[8] } };
00723     rval                               = mb->create_element( MBHEX, hex1_conn, 8, hexes[0] );
00724     if( MB_SUCCESS != rval ) return rval;
00725     rval = mb->create_element( MBHEX, hex2_conn, 8, hexes[1] );
00726     if( MB_SUCCESS != rval ) return rval;
00727     rval = mb->create_element( MBQUAD, shared_quad_conn, 4, hex1_faces[0] );
00728     if( MB_SUCCESS != rval ) return rval;
00729     hex2_faces[0] = hex1_faces[0];
00730     for( int i = 0; i < 5; ++i )
00731     {
00732         rval = mb->create_element( MBQUAD, hex1_face_conn[i], 4, hex1_faces[i + 1] );
00733         if( MB_SUCCESS != rval ) return rval;
00734         rval = mb->create_element( MBQUAD, hex2_face_conn[i], 4, hex2_faces[i + 1] );
00735         if( MB_SUCCESS != rval ) return rval;
00736     }
00737     for( int i = 0; i < 4; ++i )
00738     {
00739         rval = mb->create_element( MBEDGE, shared_edge_conn[i], 2, hex1_edges[i] );
00740         if( MB_SUCCESS != rval ) return rval;
00741         hex2_edges[i] = hex1_edges[i];
00742     }
00743     for( int i = 0; i < 8; ++i )
00744     {
00745         rval = mb->create_element( MBEDGE, hex1_edge_conn[i], 2, hex1_edges[i + 4] );
00746         if( MB_SUCCESS != rval ) return rval;
00747         rval = mb->create_element( MBEDGE, hex2_edge_conn[i], 2, hex2_edges[i + 4] );
00748         if( MB_SUCCESS != rval ) return rval;
00749     }
00750     return MB_SUCCESS;
00751 }
00752 
00753 ErrorCode mb_upward_adjacencies_test()
00754 {
00755     ErrorCode rval;
00756     Core moab;
00757     Interface* mb = &moab;
00758 
00759     // create a simple mesh containing 2 hexes
00760     EntityHandle vertices[12], hexes[2], hex1_faces[6], hex2_faces[6], hex1_edges[12], hex2_edges[12];
00761     rval = create_two_hex_full_mesh( mb, vertices, hexes, hex1_faces, hex2_faces, hex1_edges, hex2_edges );MB_CHK_ERR( rval );
00762 
00763     // test adjacences from dim to 3
00764     for( int dim = 0; dim < 3; ++dim )
00765     {
00766         std::vector< EntityHandle > hex1_ent, hex2_ent, shared;
00767         const EntityHandle *list1, *list2;
00768         int n;
00769         switch( dim )
00770         {
00771             case 0:
00772                 rval = mb->get_connectivity( hexes[0], list1, n );MB_CHK_ERR( rval );
00773                 rval = mb->get_connectivity( hexes[1], list2, n );MB_CHK_ERR( rval );
00774                 break;
00775             case 1:
00776                 list1 = hex1_edges;
00777                 list2 = hex2_edges;
00778                 n     = 12;
00779                 break;
00780             case 2:
00781                 list1 = hex1_faces;
00782                 list2 = hex2_faces;
00783                 n     = 6;
00784                 break;
00785         }
00786         // split entities into those uniquely in hex1, those uniquely in hex2
00787         // and those shared between the two
00788         for( int i = 0; i < n; ++i )
00789         {
00790             if( std::find( list2, list2 + n, list1[i] ) - list2 == n )
00791                 hex1_ent.push_back( list1[i] );
00792             else
00793                 shared.push_back( list1[i] );
00794             if( std::find( list1, list1 + n, list2[i] ) - list1 == n ) hex2_ent.push_back( list2[i] );
00795         }
00796         // for each shared entity check that get_adjacencies returns both hexes
00797         for( size_t j = 0; j < shared.size(); ++j )
00798         {
00799             std::vector< EntityHandle > adj;
00800             rval = mb->get_adjacencies( &shared[j], 1, 3, false, adj );MB_CHK_ERR( rval );
00801             if( adj.size() != 2 )
00802             {
00803                 std::cout << "Expected 2 hexes adjacent to " << dim << "D entity " << j << ". Got " << adj.size()
00804                           << " hexes." << std::endl;
00805                 return MB_FAILURE;
00806             }
00807             if( !( adj[0] == hexes[0] && adj[1] == hexes[1] ) && !( adj[0] == hexes[1] && adj[1] == hexes[0] ) )
00808             {
00809                 std::cout << "Got incorrect hexes adjacent to " << dim << "D entity " << j << std::endl;
00810                 return MB_FAILURE;
00811             }
00812         }
00813 
00814         for( size_t j = 0; j < hex1_ent.size(); ++j )
00815         {
00816             std::vector< EntityHandle > adj;
00817             rval = mb->get_adjacencies( &hex1_ent[j], 1, 3, false, adj );MB_CHK_ERR( rval );
00818             CHECK( adj.size() == 1 && adj[0] == hexes[0] );
00819         }
00820 
00821         for( size_t j = 0; j < hex2_ent.size(); ++j )
00822         {
00823             std::vector< EntityHandle > adj;
00824             rval = mb->get_adjacencies( &hex2_ent[j], 1, 3, false, adj );MB_CHK_ERR( rval );
00825             CHECK( adj.size() == 1 && adj[0] == hexes[1] );
00826         }
00827     }
00828 
00829     // For each edge, get adjacent faces, and for each face
00830     // get adjacent hexes.  Result should be the same as
00831     // direct query from edges to hexes
00832     std::vector< EntityHandle > all_edges( 24 );
00833     std::copy( hex1_edges, hex1_edges + 12, all_edges.begin() );
00834     std::copy( hex2_edges, hex2_edges + 12, all_edges.begin() + 12 );
00835     std::sort( all_edges.begin(), all_edges.end() );
00836     all_edges.erase( std::unique( all_edges.begin(), all_edges.end() ), all_edges.end() );
00837     for( size_t j = 0; j < all_edges.size(); ++j )
00838     {
00839         std::vector< EntityHandle > edge_hexes, edge_faces, face_hexes;
00840         rval = mb->get_adjacencies( &all_edges[j], 1, 3, false, edge_hexes );MB_CHK_ERR( rval );
00841         rval = mb->get_adjacencies( &all_edges[j], 1, 2, false, edge_faces );MB_CHK_ERR( rval );
00842         rval = mb->get_adjacencies( &edge_faces[0], edge_faces.size(), 3, false, face_hexes, Interface::UNION );MB_CHK_ERR( rval );
00843         if( edge_hexes.size() != face_hexes.size() )
00844         {
00845             std::cout << "Inconsistent adjacency data for edge " << j << ". edge->face->hex resulted in "
00846                       << face_hexes.size() << "hexes while edge->hex resulted in " << edge_hexes.size() << std::endl;
00847             return MB_FAILURE;
00848         }
00849         switch( edge_hexes.size() )
00850         {
00851             case 1:
00852                 CHECK( edge_hexes[0] == face_hexes[0] );
00853                 break;
00854             case 2:
00855                 CHECK( ( edge_hexes[0] == face_hexes[0] && edge_hexes[1] == face_hexes[1] ) ||
00856                        ( edge_hexes[0] == face_hexes[1] && edge_hexes[1] == face_hexes[0] ) );
00857                 break;
00858             default:
00859                 std::cout << "Got " << edge_hexes.size() << " hexes adjacent to edge " << j << std::endl;
00860                 return MB_FAILURE;
00861         }
00862     }
00863     return MB_SUCCESS;
00864 }
00865 
00866 ErrorCode mb_adjacent_create_test()
00867 {
00868     Core moab;
00869     Interface& mb = moab;
00870     ErrorCode rval;
00871 
00872     // create vertices
00873     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 },
00874                                  { 0.5, -0.5, 0.5 },  { 0.5, -0.5, -0.5 },  { 0.5, 0.5, -0.5 },  { 0.5, 0.5, 0.5 } };
00875     EntityHandle verts[8]    = { 0 };
00876     for( int i = 0; i < 8; ++i )
00877     {
00878         rval = mb.create_vertex( coords[i], verts[i] );MB_CHK_ERR( rval );
00879     }
00880     // create a single hex
00881     const EntityHandle hconn[8] = { verts[0], verts[1], verts[2], verts[3], verts[4], verts[5], verts[6], verts[7] };
00882     EntityHandle hex;
00883     rval = mb.create_element( MBHEX, hconn, 8, hex );MB_CHK_ERR( rval );
00884     // create hex faces
00885     std::vector< EntityHandle > quads;
00886     rval = mb.get_adjacencies( &hex, 1, 2, true, quads, Interface::UNION );MB_CHK_ERR( rval );
00887     CHECK_EQUAL( (size_t)6, quads.size() );
00888     // check that we got each of the 6 expected faces, with outwards
00889     // normals assuming CCW order and correct connectivity
00890     const EntityHandle faces[6][4] = {
00891         { verts[0], verts[1], verts[5], verts[4] }, { verts[1], verts[2], verts[6], verts[5] },
00892         { verts[2], verts[3], verts[7], verts[6] }, { verts[3], verts[0], verts[4], verts[7] },
00893         { verts[3], verts[2], verts[1], verts[0] }, { verts[4], verts[5], verts[6], verts[7] }
00894     };
00895     for( int i = 0; i < 6; ++i )
00896     {  // for each expected face
00897         // get sorted list of verts first for easy comparison
00898         std::vector< EntityHandle > exp_sorted( 4 );
00899         std::copy( faces[i], faces[i] + 4, exp_sorted.begin() );
00900         std::sort( exp_sorted.begin(), exp_sorted.end() );
00901         // search for matching face in output
00902         int j = 0;
00903         std::vector< EntityHandle > conn;
00904         for( ; j < 6; ++j )
00905         {
00906             conn.clear();
00907             rval = mb.get_connectivity( &quads[j], 1, conn );MB_CHK_ERR( rval );
00908             CHECK_EQUAL( (size_t)4, conn.size() );
00909             std::vector< EntityHandle > sorted( conn );
00910             std::sort( sorted.begin(), sorted.end() );
00911             if( sorted == exp_sorted ) break;
00912         }
00913         if( j == 6 )
00914         {
00915             std::cerr << "No adjacent face matching hex face " << i << std::endl;
00916             CHECK( j < 6 );
00917         }
00918         // check order
00919         int k = std::find( conn.begin(), conn.end(), faces[i][0] ) - conn.begin();
00920         for( j = 1; j < 4; ++j )
00921             if( faces[i][j] != conn[( j + k ) % 4] ) break;
00922         if( j != 4 )
00923         {
00924             std::cerr << "Incorrect vertex order for hex face " << i << std::endl;
00925             std::cerr << "Expected: " << faces[i][0] << ", " << faces[i][1] << ", " << faces[i][2] << ", "
00926                       << faces[i][3] << std::endl;
00927             std::cerr << "Actual:   " << conn[0] << ", " << conn[1] << ", " << conn[2] << ", " << conn[3] << std::endl;
00928             CHECK( false );
00929         }
00930     }
00931     return MB_SUCCESS;
00932 }
00933 
00934 ErrorCode nothing_but_type( Range& range, EntityType type )
00935 {
00936 
00937     // make sure there's nothing but hexes in hex_ms
00938     Range::iterator iter, end_iter;
00939     iter     = range.begin();
00940     end_iter = range.end();
00941 
00942     for( ; iter != end_iter; ++iter )
00943     {
00944         if( TYPE_FROM_HANDLE( *iter ) != type ) { return MB_FAILURE; }
00945     }
00946     return MB_SUCCESS;
00947 }
00948 
00949 ErrorCode check_esets( Interface* MB, const int num_sets )
00950 {
00951     int entity_sets_size;
00952     ErrorCode result = MB->get_number_entities_by_type( 0, MBENTITYSET, entity_sets_size );
00953     if( MB_SUCCESS != result || entity_sets_size != num_sets ) return MB_FAILURE;
00954 
00955     return MB_SUCCESS;
00956 }
00957 
00958 ErrorCode mb_mesh_sets_test( int flags )
00959 {
00960     Core moab;
00961     Interface* MB    = &moab;
00962     ErrorCode result = create_some_mesh( MB );
00963     if( MB_SUCCESS != result ) return result;
00964 
00965     Range temp_range;
00966     std::vector< EntityHandle > temp_vector;
00967     EntityType ent_type;
00968 
00969     EntityHandle ms_array[MBENTITYSET]     = { 0 };
00970     unsigned int number_array[MBENTITYSET] = { 0 };
00971     unsigned int num_dim_array[4]          = { 0, 0, 0, 0 };
00972     int count, start_num_sets;
00973 
00974     result = MB->get_number_entities_by_type( 0, MBENTITYSET, start_num_sets );
00975     if( MB_SUCCESS != result ) return result;
00976 
00977     // add entities to meshsets
00978     for( ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++ )
00979     {
00980         result = MB->create_meshset( flags, ms_array[ent_type] );
00981         if( result != MB_SUCCESS ) return result;
00982 
00983         temp_range.clear();
00984         result = MB->get_entities_by_type( 0, ent_type, temp_range );
00985         if( result != MB_SUCCESS ) return result;
00986         result = MB->get_number_entities_by_type( 0, ent_type, count );
00987         if( result != MB_SUCCESS ) return result;
00988         if( (unsigned)count != temp_range.size() ) return MB_FAILURE;
00989         result = MB->add_entities( ms_array[ent_type], temp_range );
00990         if( result != MB_SUCCESS ) return result;
00991 
00992         number_array[ent_type] = temp_range.size();  // KGM
00993         num_dim_array[CN::Dimension( ent_type )] += count;
00994 
00995         // Check to make sure mesh set really has correct number of entities in it
00996         temp_range.clear();
00997         temp_vector.clear();
00998         result = MB->get_entities_by_handle( ms_array[ent_type], temp_range );
00999         if( result != MB_SUCCESS ) return result;
01000         if( number_array[ent_type] != temp_range.size() )
01001         {
01002             cout << "Number of entities in meshset test is not correct" << endl;
01003             return MB_FAILURE;
01004         }
01005         if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
01006 
01007         result = MB->get_entities_by_handle( ms_array[ent_type], temp_vector );
01008         if( result != MB_SUCCESS ) return result;
01009         if( number_array[ent_type] != temp_vector.size() )
01010         {
01011             cout << "Number of entities in meshset test is not correct" << endl;
01012             return MB_FAILURE;
01013         }
01014 
01015         temp_range.clear();
01016         result = MB->get_entities_by_type( ms_array[ent_type], ent_type, temp_range );
01017         if( result != MB_SUCCESS ) return result;
01018         if( number_array[ent_type] != temp_range.size() )
01019         {
01020             cout << "Number of entities by type in meshset test is not correct" << endl;
01021             return MB_FAILURE;
01022         }
01023         if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
01024 
01025         temp_range.clear();
01026         result = MB->get_entities_by_type( ms_array[ent_type], MBVERTEX, temp_range );
01027         if( result != MB_SUCCESS ) return result;
01028         if( 0 != temp_range.size() ) return MB_FAILURE;
01029 
01030         temp_range.clear();
01031         result = MB->get_entities_by_dimension( ms_array[ent_type], CN::Dimension( ent_type ), temp_range );
01032         if( result != MB_SUCCESS ) return result;
01033         if( number_array[ent_type] != temp_range.size() )
01034         {
01035             cout << "Number of entities by dimension in meshset test is not correct" << endl;
01036             return MB_FAILURE;
01037         }
01038         if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
01039 
01040         temp_range.clear();
01041         result = MB->get_entities_by_dimension( ms_array[ent_type], 0, temp_range );
01042         if( result != MB_SUCCESS ) return result;
01043         if( 0 != temp_range.size() )
01044         {
01045             cout << "Number of entities by dimension in meshset test is not correct" << endl;
01046             return MB_FAILURE;
01047         }
01048 
01049         result = MB->get_number_entities_by_handle( ms_array[ent_type], count );
01050         if( result != MB_SUCCESS ) return result;
01051         if( (unsigned)count != number_array[ent_type] ) return MB_FAILURE;
01052 
01053         result = MB->get_number_entities_by_type( ms_array[ent_type], ent_type, count );
01054         if( result != MB_SUCCESS ) return result;
01055         if( (unsigned)count != number_array[ent_type] ) return MB_FAILURE;
01056 
01057         result = MB->get_number_entities_by_type( ms_array[ent_type], MBVERTEX, count );
01058         if( result != MB_SUCCESS ) return result;
01059         if( count != 0 ) return MB_FAILURE;
01060 
01061         result = MB->get_number_entities_by_dimension( ms_array[ent_type], CN::Dimension( ent_type ), count );
01062         if( result != MB_SUCCESS ) return result;
01063         if( (unsigned)count != number_array[ent_type] ) return MB_FAILURE;
01064 
01065         result = MB->get_number_entities_by_dimension( ms_array[ent_type], 0, count );
01066         if( result != MB_SUCCESS ) return result;
01067         if( count != 0 ) return MB_FAILURE;
01068     }
01069 
01070     result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE );
01071     if( MB_SUCCESS != result ) return result;
01072 
01073     for( int dim = 1; dim < 4; ++dim )
01074     {
01075         result = MB->get_number_entities_by_dimension( 0, dim, count );
01076         if( MB_SUCCESS != result ) return MB_FAILURE;
01077         if( (unsigned)count != num_dim_array[dim] ) return MB_FAILURE;
01078     }
01079 
01080     //----------TEST RECURSIVE OPERATIONS----------------//
01081     EntityHandle recursive1, recursive2;
01082     result = MB->create_meshset( MESHSET_SET, recursive1 );
01083     if( result != MB_SUCCESS ) return result;
01084     result = MB->create_meshset( 0, recursive2 );
01085     if( result != MB_SUCCESS ) return result;
01086     unsigned num_sets = MBENTITYSET - MBEDGE;
01087     result            = MB->add_entities( recursive2, ms_array + MBEDGE, num_sets );
01088     if( MB_SUCCESS != result ) return result;
01089     result = MB->add_entities( recursive1, &recursive2, 1 );
01090     if( MB_SUCCESS != result ) return result;
01091 
01092     temp_range.clear();
01093     result = MB->get_entities_by_type( recursive1, MBENTITYSET, temp_range );
01094     if( MB_SUCCESS != result ) return result;
01095     if( temp_range.size() != 1 || *( temp_range.begin() ) != recursive2 ) return MB_FAILURE;
01096 
01097     temp_range.clear();
01098     result = MB->get_entities_by_type( recursive2, MBENTITYSET, temp_range );
01099     if( MB_SUCCESS != result ) return result;
01100     if( temp_range.size() != num_sets || !temp_range.all_of_type( MBENTITYSET ) ) return MB_FAILURE;
01101 
01102     temp_range.clear();
01103     result = MB->get_entities_by_handle( recursive1, temp_range );
01104     if( MB_SUCCESS != result ) return result;
01105     if( temp_range.size() != 1 || *( temp_range.begin() ) != recursive2 ) return MB_FAILURE;
01106 
01107     temp_range.clear();
01108     result = MB->get_entities_by_handle( recursive2, temp_range );
01109     if( MB_SUCCESS != result ) return result;
01110     if( temp_range.size() != num_sets || !temp_range.all_of_type( MBENTITYSET ) ) return MB_FAILURE;
01111 
01112     unsigned total = 0;
01113     for( ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++ )
01114     {
01115         total += number_array[ent_type];
01116         temp_range.clear();
01117         result = MB->get_entities_by_type( recursive1, ent_type, temp_range, true );
01118         if( result != MB_SUCCESS ) return result;
01119         if( number_array[ent_type] != temp_range.size() )
01120         {
01121             cout << "Recursive number of entities by type in meshset test is not correct" << endl;
01122             return MB_FAILURE;
01123         }
01124         if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
01125         result = MB->get_number_entities_by_type( recursive1, ent_type, count, true );
01126         if( result != MB_SUCCESS ) return result;
01127         if( number_array[ent_type] != (unsigned)count )
01128         {
01129             cout << "Recursive number of entities by type in meshset test is not correct" << endl;
01130             return MB_FAILURE;
01131         }
01132         if( !temp_range.all_of_type( ent_type ) ) return MB_FAILURE;
01133     }
01134     if( 0 == total )
01135     {
01136         cout << "Invalid test input.  No entities!" << endl;
01137         return MB_FAILURE;
01138     }
01139 
01140     for( int dim = 1; dim < 4; ++dim )
01141     {
01142         temp_range.clear();
01143         result = MB->get_entities_by_dimension( recursive1, dim, temp_range, true );
01144         if( MB_SUCCESS != result ) return MB_FAILURE;
01145         if( temp_range.size() != num_dim_array[dim] ) return MB_FAILURE;
01146         if( !temp_range.all_of_dimension( dim ) ) return MB_FAILURE;
01147         result = MB->get_number_entities_by_dimension( recursive1, dim, count, true );
01148         if( MB_SUCCESS != result ) return MB_FAILURE;
01149         if( (unsigned)count != num_dim_array[dim] ) return MB_FAILURE;
01150     }
01151 
01152     temp_range.clear();
01153     result = MB->get_entities_by_handle( recursive1, temp_range, true );
01154     if( result != MB_SUCCESS ) return result;
01155     if( total != temp_range.size() )
01156     {
01157         cout << "Recursive number of entities in meshset test is not correct" << endl;
01158         return MB_FAILURE;
01159     }
01160 
01161     // try circular relation
01162     result = MB->add_entities( recursive2, &recursive1, 1 );
01163     if( MB_SUCCESS != result )
01164     {
01165         std::cout << "Failed to create circular set containment" << std::endl;
01166         return result;
01167     }
01168     temp_range.clear();
01169     result = MB->get_entities_by_handle( recursive1, temp_range, true );
01170     if( result != MB_SUCCESS ) return result;
01171     if( total != temp_range.size() )
01172     {
01173         cout << "Recursive number of entities in meshset test is not correct" << endl;
01174         return MB_FAILURE;
01175     }
01176 
01177     result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 2 );
01178     if( MB_SUCCESS != result ) return result;
01179 
01180     //----------TEST BOOLEAN OPERATIONS----------------//
01181 
01182     EntityHandle temp_ms1, temp_ms2;
01183     result = MB->create_meshset( flags, temp_ms1 );
01184     if( result != MB_SUCCESS ) return result;
01185     result = MB->create_meshset( flags, temp_ms2 );
01186     if( result != MB_SUCCESS ) return result;
01187 
01188     // Subtract
01189     // add all edges and hexes of ms_array[MBHEX] and ms_array[MBEDGE] to temp_ms1
01190     // get all Edge entities
01191     temp_range.clear();
01192     result = MB->get_entities_by_handle( ms_array[MBEDGE], temp_range );
01193     if( result != MB_SUCCESS ) return result;
01194 
01195     // add Edges to ms1
01196     result = MB->add_entities( temp_ms1, temp_range );
01197     if( result != MB_SUCCESS ) return result;
01198 
01199     temp_range.clear();
01200     result = MB->get_entities_by_handle( ms_array[MBHEX], temp_range );
01201     if( result != MB_SUCCESS ) return result;
01202 
01203     // add Hexes to ms1
01204     result = MB->add_entities( temp_ms1, temp_range );
01205     if( result != MB_SUCCESS ) return result;
01206 
01207     // subtract bars meshset out of hex meshset
01208     result = MB->subtract_meshset( temp_ms1, ms_array[MBEDGE] );
01209     if( result != MB_SUCCESS ) return result;
01210 
01211     // Perform the check
01212     temp_range.clear();
01213     result = MB->get_entities_by_handle( temp_ms1, temp_range );
01214     if( result != MB_SUCCESS ) return result;
01215 
01216     if( number_array[MBHEX] != temp_range.size() )
01217     {
01218         cout << "MBset subtraction is bad" << endl;
01219         return MB_FAILURE;
01220     }
01221     // make sure there's nothing but hexes in hex_ms
01222     if( nothing_but_type( temp_range, MBHEX ) != MB_SUCCESS ) return MB_FAILURE;
01223 
01224     result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 4 );
01225     if( MB_SUCCESS != result ) return result;
01226 
01227     //------------Intersect------------
01228     //
01229     // clean out the temp_ms1
01230     MB->clear_meshset( &temp_ms1, 1 );
01231 
01232     temp_range.clear();
01233     // get all quad entities
01234     temp_range.clear();
01235     result = MB->get_entities_by_handle( ms_array[MBQUAD], temp_range );
01236     if( result != MB_SUCCESS ) return result;
01237 
01238     // add tets them to ms1
01239     result = MB->add_entities( temp_ms1, temp_range );
01240     if( result != MB_SUCCESS ) return result;
01241 
01242     // get all tet entities
01243     temp_range.clear();
01244     result = MB->get_entities_by_handle( ms_array[MBTET], temp_range );
01245     if( result != MB_SUCCESS ) return result;
01246 
01247     // add tets them to ms1
01248     result = MB->add_entities( temp_ms1, temp_range );
01249     if( result != MB_SUCCESS ) return result;
01250 
01251     // intersect temp_ms1 (which contains all quads and tets) with tet meshset
01252     // temp_ms1 meshset is altered
01253     result = MB->intersect_meshset( temp_ms1, ms_array[MBTET] );
01254     if( result != MB_SUCCESS ) return result;
01255 
01256     // Perform the check, only tets should be in temp_ms1
01257     temp_range.clear();
01258     result = MB->get_entities_by_handle( temp_ms1, temp_range );
01259     if( result != MB_SUCCESS ) return result;
01260     if( number_array[MBTET] != temp_range.size() )
01261     {
01262         cout << "MBset intersection is bad" << endl;
01263         return MB_FAILURE;
01264     }
01265 
01266     // make sure there's nothing but tet in range
01267     if( nothing_but_type( temp_range, MBTET ) != MB_SUCCESS ) return MB_FAILURE;
01268 
01269     result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 4 );
01270     if( MB_SUCCESS != result ) return result;
01271 
01272     //-------------Unite--------------
01273     // fill temp_ms1 with tets and tris
01274     // get all tris
01275     temp_range.clear();
01276     result = MB->get_entities_by_handle( ms_array[MBTRI], temp_range );
01277     if( result != MB_SUCCESS ) return result;
01278 
01279     // add tets them to ms1
01280     result = MB->add_entities( temp_ms1, temp_range );
01281     if( result != MB_SUCCESS ) return result;
01282 
01283     temp_range.clear();
01284     result = MB->get_entities_by_handle( ms_array[MBTET], temp_range );
01285     if( result != MB_SUCCESS ) return result;
01286 
01287     // add tets them to ms1
01288     result = MB->add_entities( temp_ms1, temp_range );
01289     if( result != MB_SUCCESS ) return result;
01290 
01291     // fill temp_ms2 with tris and hexes
01292     temp_range.clear();
01293     result = MB->get_entities_by_handle( ms_array[MBTRI], temp_range );
01294     if( result != MB_SUCCESS ) return result;
01295 
01296     // add tets them to ms1
01297     result = MB->add_entities( temp_ms2, temp_range );
01298     if( result != MB_SUCCESS ) return result;
01299 
01300     temp_range.clear();
01301     result = MB->get_entities_by_handle( ms_array[MBQUAD], temp_range );
01302     if( result != MB_SUCCESS ) return result;
01303 
01304     // add tets them to ms1
01305     result = MB->add_entities( temp_ms2, temp_range );
01306     if( result != MB_SUCCESS ) return result;
01307 
01308     // temp_ms1 is now filled with tets and tris
01309     // temp_ms2 is now filled with quads and tris
01310     int size1 = 0, size2 = 0;
01311     result = MB->get_number_entities_by_handle( ms_array[MBTRI], size1 );
01312     if( result != MB_SUCCESS ) return result;
01313 
01314     result = MB->intersect_meshset( temp_ms1, temp_ms2 );
01315     if( result != MB_SUCCESS ) return result;
01316     result = MB->get_number_entities_by_handle( temp_ms1, size2 );
01317     if( result != MB_SUCCESS ) return result;
01318 
01319     if( size1 != size2 ) { return MB_FAILURE; }
01320 
01321     temp_range.clear();
01322     result = MB->get_entities_by_handle( temp_ms1, temp_range );
01323     if( result != MB_SUCCESS ) return result;
01324 
01325     // make sure there's nothing but tris in temp_range
01326     if( nothing_but_type( temp_range, MBTRI ) != MB_SUCCESS ) return MB_FAILURE;
01327 
01328     result = check_esets( MB, start_num_sets + MBENTITYSET - MBEDGE + 4 );
01329     if( MB_SUCCESS != result ) return result;
01330 
01331     //-------------Misc tests--------------
01332     EntityHandle temp_ms3;
01333     result = MB->create_meshset( flags, temp_ms3 );
01334     if( result != MB_SUCCESS ) return result;
01335 
01336     EntityHandle handle_array[] = { 1, 2, 3, 4, 5, 7, 8, 9, 10 };
01337     const int num_handle        = sizeof( handle_array ) / sizeof( handle_array[0] );
01338     // add ents to set
01339     result = MB->add_entities( temp_ms3, handle_array, num_handle );
01340     if( result != MB_SUCCESS ) return result;
01341 
01342     // try adding again
01343     result = MB->add_entities( temp_ms3, handle_array, num_handle );
01344     if( result != MB_SUCCESS ) return result;
01345 
01346     int num_ents;
01347     result = MB->get_number_entities_by_handle( temp_ms3, num_ents );
01348     if( result != MB_SUCCESS ) return result;
01349 
01350     int num_expected = ( flags & MESHSET_SET ) ? num_handle : 2 * num_handle;
01351     if( num_ents != num_expected ) return MB_FAILURE;
01352 
01353     return MB_SUCCESS;
01354 }
01355 
01356 static bool compare_lists( std::vector< EntityHandle > vect, const EntityHandle* array, int count, bool ordered = true )
01357 {
01358     if( vect.size() != (size_t)count ) return false;
01359     for( int i = 0; i < count; ++i )
01360     {
01361         if( ordered )
01362         {
01363             if( vect[i] != array[i] ) return false;
01364         }
01365         else if( std::find( vect.begin(), vect.end(), array[i] ) == vect.end() )
01366             return false;
01367     }
01368     return true;
01369 }
01370 
01371 // Test parent/child stuff in meshsets
01372 ErrorCode mb_mesh_set_parent_child_test()
01373 {
01374     Core moab;
01375     Interface* MB = &moab;
01376 
01377     ErrorCode rval;
01378     std::vector< EntityHandle > list;
01379     Range range;
01380     Range::iterator iter;
01381     int count;
01382 
01383     // create a few mesh sets
01384     const int num_sets = 10;
01385     EntityHandle sets[num_sets];
01386     for( int i = 0; i < num_sets; ++i )
01387     {
01388         rval = MB->create_meshset( i % 2 ? MESHSET_SET : 0, sets[i] );
01389         if( MB_SUCCESS != rval ) return rval;
01390     }
01391 
01392     // test adding child meshsets
01393 
01394     // add first child
01395     rval = MB->add_child_meshset( sets[0], sets[1] );
01396     if( MB_SUCCESS != rval ) return rval;
01397     list.clear();
01398     rval = MB->get_child_meshsets( sets[0], list );
01399     if( MB_SUCCESS != rval ) return rval;
01400     if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
01401     // try to add child again
01402     rval = MB->add_child_meshset( sets[0], sets[1] );
01403     if( MB_SUCCESS != rval ) return rval;
01404     list.clear();
01405     rval = MB->get_child_meshsets( sets[0], list );
01406     if( MB_SUCCESS != rval ) return rval;
01407     if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
01408 
01409     // add second child
01410     rval = MB->add_child_meshset( sets[0], sets[2] );
01411     if( MB_SUCCESS != rval ) return rval;
01412     list.clear();
01413     rval = MB->get_child_meshsets( sets[0], list );
01414     if( MB_SUCCESS != rval ) return rval;
01415     if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
01416     // try adding child again
01417     rval = MB->add_child_meshset( sets[0], sets[1] );
01418     if( MB_SUCCESS != rval ) return rval;
01419     list.clear();
01420     rval = MB->get_child_meshsets( sets[0], list );
01421     if( MB_SUCCESS != rval ) return rval;
01422     if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
01423 
01424     // add third child
01425     rval = MB->add_child_meshset( sets[0], sets[3] );
01426     if( MB_SUCCESS != rval ) return rval;
01427     list.clear();
01428     rval = MB->get_child_meshsets( sets[0], list );
01429     if( MB_SUCCESS != rval ) return rval;
01430     if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
01431     // try adding child again
01432     rval = MB->add_child_meshset( sets[0], sets[1] );
01433     if( MB_SUCCESS != rval ) return rval;
01434     list.clear();
01435     rval = MB->get_child_meshsets( sets[0], list );
01436     if( MB_SUCCESS != rval ) return rval;
01437     if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
01438 
01439     // add fourth child
01440     rval = MB->add_child_meshset( sets[0], sets[4] );
01441     if( MB_SUCCESS != rval ) return rval;
01442     list.clear();
01443     rval = MB->get_child_meshsets( sets[0], list );
01444     if( MB_SUCCESS != rval ) return rval;
01445     if( !compare_lists( list, sets + 1, 4 ) ) return MB_FAILURE;
01446 
01447     // make sure range query returns same result
01448     std::sort( list.begin(), list.end() );
01449     rval = MB->get_child_meshsets( sets[0], range );
01450     iter = range.begin();
01451     for( unsigned i = 0; i < 4; ++i, ++iter )
01452         if( *iter != list[i] ) return MB_FAILURE;
01453 
01454     // remove first child
01455     rval = MB->remove_child_meshset( sets[0], sets[1] );
01456     if( MB_SUCCESS != rval ) return rval;
01457     list.clear();
01458     rval = MB->get_child_meshsets( sets[0], list );
01459     if( MB_SUCCESS != rval ) return rval;
01460     if( !compare_lists( list, sets + 2, 3 ) ) return MB_FAILURE;
01461     // try removing child again
01462     rval = MB->remove_child_meshset( sets[0], sets[1] );
01463     if( MB_SUCCESS != rval ) return rval;
01464 
01465     // remove second child
01466     rval = MB->remove_child_meshset( sets[0], sets[2] );
01467     if( MB_SUCCESS != rval ) return rval;
01468     list.clear();
01469     rval = MB->get_child_meshsets( sets[0], list );
01470     if( !compare_lists( list, sets + 3, 2 ) ) return MB_FAILURE;
01471     // try removing child again
01472     rval = MB->remove_child_meshset( sets[0], sets[2] );
01473     if( MB_SUCCESS != rval ) return rval;
01474 
01475     // remove third child
01476     rval = MB->remove_child_meshset( sets[0], sets[3] );
01477     if( MB_SUCCESS != rval ) return rval;
01478     list.clear();
01479     rval = MB->get_child_meshsets( sets[0], list );
01480     if( list.size() != 1 || list[0] != sets[4] ) return MB_FAILURE;
01481 
01482     // remove fourth child
01483     rval = MB->remove_child_meshset( sets[0], sets[4] );
01484     if( MB_SUCCESS != rval ) return rval;
01485     list.clear();
01486     rval = MB->get_child_meshsets( sets[0], list );
01487     if( !list.empty() ) return MB_FAILURE;
01488 
01489     // test adding parent meshsets
01490 
01491     // add first parent
01492     rval = MB->add_parent_meshset( sets[0], sets[1] );
01493     if( MB_SUCCESS != rval ) return rval;
01494     list.clear();
01495     rval = MB->get_parent_meshsets( sets[0], list );
01496     if( MB_SUCCESS != rval ) return rval;
01497     if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
01498     // try to add parent again
01499     rval = MB->add_parent_meshset( sets[0], sets[1] );
01500     if( MB_SUCCESS != rval ) return rval;
01501     list.clear();
01502     rval = MB->get_parent_meshsets( sets[0], list );
01503     if( MB_SUCCESS != rval ) return rval;
01504     if( !compare_lists( list, sets + 1, 1 ) ) return MB_FAILURE;
01505 
01506     // add second parent
01507     rval = MB->add_parent_meshset( sets[0], sets[2] );
01508     if( MB_SUCCESS != rval ) return rval;
01509     list.clear();
01510     rval = MB->get_parent_meshsets( sets[0], list );
01511     if( MB_SUCCESS != rval ) return rval;
01512     if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
01513     // try adding parent again
01514     rval = MB->add_parent_meshset( sets[0], sets[1] );
01515     if( MB_SUCCESS != rval ) return rval;
01516     list.clear();
01517     rval = MB->get_parent_meshsets( sets[0], list );
01518     if( MB_SUCCESS != rval ) return rval;
01519     if( !compare_lists( list, sets + 1, 2 ) ) return MB_FAILURE;
01520 
01521     // add third parent
01522     rval = MB->add_parent_meshset( sets[0], sets[3] );
01523     if( MB_SUCCESS != rval ) return rval;
01524     list.clear();
01525     rval = MB->get_parent_meshsets( sets[0], list );
01526     if( MB_SUCCESS != rval ) return rval;
01527     if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
01528     // try adding parent again
01529     rval = MB->add_parent_meshset( sets[0], sets[1] );
01530     if( MB_SUCCESS != rval ) return rval;
01531     list.clear();
01532     rval = MB->get_parent_meshsets( sets[0], list );
01533     if( MB_SUCCESS != rval ) return rval;
01534     if( !compare_lists( list, sets + 1, 3 ) ) return MB_FAILURE;
01535 
01536     // add fourth parent
01537     rval = MB->add_parent_meshset( sets[0], sets[4] );
01538     if( MB_SUCCESS != rval ) return rval;
01539     list.clear();
01540     rval = MB->get_parent_meshsets( sets[0], list );
01541     if( MB_SUCCESS != rval ) return rval;
01542     if( !compare_lists( list, sets + 1, 4 ) ) return MB_FAILURE;
01543 
01544     // make sure range query returns same result
01545     std::sort( list.begin(), list.end() );
01546     rval = MB->get_parent_meshsets( sets[0], range );
01547     iter = range.begin();
01548     for( unsigned i = 0; i < 4; ++i, ++iter )
01549         if( *iter != list[i] ) return MB_FAILURE;
01550 
01551     // remove first parent
01552     rval = MB->remove_parent_meshset( sets[0], sets[1] );
01553     if( MB_SUCCESS != rval ) return rval;
01554     list.clear();
01555     rval = MB->get_parent_meshsets( sets[0], list );
01556     if( MB_SUCCESS != rval ) return rval;
01557     if( !compare_lists( list, sets + 2, 3 ) ) return MB_FAILURE;
01558     // try removing parent again
01559     rval = MB->remove_parent_meshset( sets[0], sets[1] );
01560     if( MB_SUCCESS != rval ) return rval;
01561 
01562     // remove second parent
01563     rval = MB->remove_parent_meshset( sets[0], sets[2] );
01564     if( MB_SUCCESS != rval ) return rval;
01565     list.clear();
01566     rval = MB->get_parent_meshsets( sets[0], list );
01567     if( !compare_lists( list, sets + 3, 2 ) ) return MB_FAILURE;
01568     // try removing parent again
01569     rval = MB->remove_parent_meshset( sets[0], sets[2] );
01570     if( MB_SUCCESS != rval ) return rval;
01571 
01572     // remove third parent
01573     rval = MB->remove_parent_meshset( sets[0], sets[3] );
01574     if( MB_SUCCESS != rval ) return rval;
01575     list.clear();
01576     rval = MB->get_parent_meshsets( sets[0], list );
01577     if( list.size() != 1 || list[0] != sets[4] ) return MB_FAILURE;
01578 
01579     // remove fourth parent
01580     rval = MB->remove_parent_meshset( sets[0], sets[4] );
01581     if( MB_SUCCESS != rval ) return rval;
01582     list.clear();
01583     rval = MB->get_parent_meshsets( sets[0], list );
01584     if( !list.empty() ) return MB_FAILURE;
01585 
01586     // setup tests of recursive child query
01587     //              0
01588     //            /   \         .
01589     //          1       2
01590     //        /   \   /   \       .
01591     //      3       4       5
01592     //        \   /   \   /
01593     //          6       7
01594     rval = MB->add_child_meshset( sets[0], sets[1] );
01595     if( MB_SUCCESS != rval ) return rval;
01596     rval = MB->add_child_meshset( sets[0], sets[2] );
01597     if( MB_SUCCESS != rval ) return rval;
01598     rval = MB->add_child_meshset( sets[1], sets[3] );
01599     if( MB_SUCCESS != rval ) return rval;
01600     rval = MB->add_child_meshset( sets[1], sets[4] );
01601     if( MB_SUCCESS != rval ) return rval;
01602     rval = MB->add_child_meshset( sets[2], sets[4] );
01603     if( MB_SUCCESS != rval ) return rval;
01604     rval = MB->add_child_meshset( sets[2], sets[5] );
01605     if( MB_SUCCESS != rval ) return rval;
01606     rval = MB->add_child_meshset( sets[3], sets[6] );
01607     if( MB_SUCCESS != rval ) return rval;
01608     rval = MB->add_child_meshset( sets[4], sets[6] );
01609     if( MB_SUCCESS != rval ) return rval;
01610     rval = MB->add_child_meshset( sets[4], sets[7] );
01611     if( MB_SUCCESS != rval ) return rval;
01612     rval = MB->add_child_meshset( sets[5], sets[7] );
01613     if( MB_SUCCESS != rval ) return rval;
01614 
01615     // test query at depth of 1
01616     list.clear();
01617     rval = MB->get_child_meshsets( sets[0], list, 1 );
01618     if( MB_SUCCESS != rval ) return rval;
01619     if( list.size() != 2 || list[0] != sets[1] || list[1] != sets[2] ) return MB_FAILURE;
01620     rval = MB->num_child_meshsets( sets[0], &count, 1 );
01621     if( MB_SUCCESS != rval ) return rval;
01622     if( count != 2 ) return MB_FAILURE;
01623 
01624     // test query at depth of 2
01625     list.clear();
01626     rval = MB->get_child_meshsets( sets[0], list, 2 );
01627     if( MB_SUCCESS != rval ) return rval;
01628     if( !compare_lists( list, sets + 1, 5, false ) ) return MB_FAILURE;
01629     rval = MB->num_child_meshsets( sets[0], &count, 2 );
01630     if( MB_SUCCESS != rval ) return rval;
01631     if( count != 5 ) return MB_FAILURE;
01632 
01633     // test query at depth of 3
01634     list.clear();
01635     rval = MB->get_child_meshsets( sets[0], list, 3 );
01636     if( MB_SUCCESS != rval ) return rval;
01637     if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
01638     rval = MB->num_child_meshsets( sets[0], &count, 3 );
01639     if( MB_SUCCESS != rval ) return rval;
01640     if( count != 7 ) return MB_FAILURE;
01641 
01642     // test query at depth of 4
01643     list.clear();
01644     rval = MB->get_child_meshsets( sets[0], list, 4 );
01645     if( MB_SUCCESS != rval ) return rval;
01646     if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
01647     rval = MB->num_child_meshsets( sets[0], &count, 4 );
01648     if( MB_SUCCESS != rval ) return rval;
01649     if( count != 7 ) return MB_FAILURE;
01650 
01651     // test query at all
01652     list.clear();
01653     rval = MB->get_child_meshsets( sets[0], list, 0 );
01654     if( MB_SUCCESS != rval ) return rval;
01655     if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
01656     rval = MB->num_child_meshsets( sets[0], &count, 0 );
01657     if( MB_SUCCESS != rval ) return rval;
01658     if( count != 7 ) return MB_FAILURE;
01659 
01660     // clean up child links
01661     rval = MB->remove_child_meshset( sets[0], sets[1] );
01662     if( MB_SUCCESS != rval ) return rval;
01663     rval = MB->remove_child_meshset( sets[0], sets[2] );
01664     if( MB_SUCCESS != rval ) return rval;
01665     rval = MB->remove_child_meshset( sets[1], sets[3] );
01666     if( MB_SUCCESS != rval ) return rval;
01667     rval = MB->remove_child_meshset( sets[1], sets[4] );
01668     if( MB_SUCCESS != rval ) return rval;
01669     rval = MB->remove_child_meshset( sets[2], sets[4] );
01670     if( MB_SUCCESS != rval ) return rval;
01671     rval = MB->remove_child_meshset( sets[2], sets[5] );
01672     if( MB_SUCCESS != rval ) return rval;
01673     rval = MB->remove_child_meshset( sets[3], sets[6] );
01674     if( MB_SUCCESS != rval ) return rval;
01675     rval = MB->remove_child_meshset( sets[4], sets[6] );
01676     if( MB_SUCCESS != rval ) return rval;
01677     rval = MB->remove_child_meshset( sets[4], sets[7] );
01678     if( MB_SUCCESS != rval ) return rval;
01679     rval = MB->remove_child_meshset( sets[5], sets[7] );
01680     if( MB_SUCCESS != rval ) return rval;
01681     for( int i = 0; i < 5; ++i )
01682         if( MB_SUCCESS != MB->num_child_meshsets( sets[i], &count ) || count ) return MB_FAILURE;
01683 
01684     // setup tests of recursive parent query
01685     //          6       7
01686     //        /   \   /   \       .
01687     //      3       4       5
01688     //        \   /   \   /
01689     //          1       2
01690     //            \   /
01691     //              0
01692     rval = MB->add_parent_meshset( sets[0], sets[1] );
01693     if( MB_SUCCESS != rval ) return rval;
01694     rval = MB->add_parent_meshset( sets[0], sets[2] );
01695     if( MB_SUCCESS != rval ) return rval;
01696     rval = MB->add_parent_meshset( sets[1], sets[3] );
01697     if( MB_SUCCESS != rval ) return rval;
01698     rval = MB->add_parent_meshset( sets[1], sets[4] );
01699     if( MB_SUCCESS != rval ) return rval;
01700     rval = MB->add_parent_meshset( sets[2], sets[4] );
01701     if( MB_SUCCESS != rval ) return rval;
01702     rval = MB->add_parent_meshset( sets[2], sets[5] );
01703     if( MB_SUCCESS != rval ) return rval;
01704     rval = MB->add_parent_meshset( sets[3], sets[6] );
01705     if( MB_SUCCESS != rval ) return rval;
01706     rval = MB->add_parent_meshset( sets[4], sets[6] );
01707     if( MB_SUCCESS != rval ) return rval;
01708     rval = MB->add_parent_meshset( sets[4], sets[7] );
01709     if( MB_SUCCESS != rval ) return rval;
01710     rval = MB->add_parent_meshset( sets[5], sets[7] );
01711     if( MB_SUCCESS != rval ) return rval;
01712 
01713     // test query at depth of 1
01714     list.clear();
01715     rval = MB->get_parent_meshsets( sets[0], list, 1 );
01716     if( MB_SUCCESS != rval ) return rval;
01717     if( list.size() != 2 || list[0] != sets[1] || list[1] != sets[2] ) return MB_FAILURE;
01718     rval = MB->num_parent_meshsets( sets[0], &count, 1 );
01719     if( MB_SUCCESS != rval ) return rval;
01720     if( count != 2 ) return MB_FAILURE;
01721 
01722     // test query at depth of 2
01723     list.clear();
01724     rval = MB->get_parent_meshsets( sets[0], list, 2 );
01725     if( MB_SUCCESS != rval ) return rval;
01726     if( !compare_lists( list, sets + 1, 5, false ) ) return MB_FAILURE;
01727     rval = MB->num_parent_meshsets( sets[0], &count, 2 );
01728     if( MB_SUCCESS != rval ) return rval;
01729     if( count != 5 ) return MB_FAILURE;
01730 
01731     // test query at depth of 3
01732     list.clear();
01733     rval = MB->get_parent_meshsets( sets[0], list, 3 );
01734     if( MB_SUCCESS != rval ) return rval;
01735     if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
01736     rval = MB->num_parent_meshsets( sets[0], &count, 3 );
01737     if( MB_SUCCESS != rval ) return rval;
01738     if( count != 7 ) return MB_FAILURE;
01739 
01740     // test query at depth of 4
01741     list.clear();
01742     rval = MB->get_parent_meshsets( sets[0], list, 4 );
01743     if( MB_SUCCESS != rval ) return rval;
01744     if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
01745     rval = MB->num_parent_meshsets( sets[0], &count, 4 );
01746     if( MB_SUCCESS != rval ) return rval;
01747     if( count != 7 ) return MB_FAILURE;
01748 
01749     // test query at all
01750     list.clear();
01751     rval = MB->get_parent_meshsets( sets[0], list, 0 );
01752     if( MB_SUCCESS != rval ) return rval;
01753     if( !compare_lists( list, sets + 1, 7, false ) ) return MB_FAILURE;
01754     rval = MB->num_parent_meshsets( sets[0], &count, 0 );
01755     if( MB_SUCCESS != rval ) return rval;
01756     if( count != 7 ) return MB_FAILURE;
01757 
01758     // clean up parent links
01759     rval = MB->remove_parent_meshset( sets[0], sets[1] );
01760     if( MB_SUCCESS != rval ) return rval;
01761     rval = MB->remove_parent_meshset( sets[0], sets[2] );
01762     if( MB_SUCCESS != rval ) return rval;
01763     rval = MB->remove_parent_meshset( sets[1], sets[3] );
01764     if( MB_SUCCESS != rval ) return rval;
01765     rval = MB->remove_parent_meshset( sets[1], sets[4] );
01766     if( MB_SUCCESS != rval ) return rval;
01767     rval = MB->remove_parent_meshset( sets[2], sets[4] );
01768     if( MB_SUCCESS != rval ) return rval;
01769     rval = MB->remove_parent_meshset( sets[2], sets[5] );
01770     if( MB_SUCCESS != rval ) return rval;
01771     rval = MB->remove_parent_meshset( sets[3], sets[6] );
01772     if( MB_SUCCESS != rval ) return rval;
01773     rval = MB->remove_parent_meshset( sets[4], sets[6] );
01774     if( MB_SUCCESS != rval ) return rval;
01775     rval = MB->remove_parent_meshset( sets[4], sets[7] );
01776     if( MB_SUCCESS != rval ) return rval;
01777     rval = MB->remove_parent_meshset( sets[5], sets[7] );
01778     if( MB_SUCCESS != rval ) return rval;
01779     for( int i = 0; i < 5; ++i )
01780         if( MB_SUCCESS != MB->num_parent_meshsets( sets[i], &count ) || count ) return MB_FAILURE;
01781 
01782     // test combined parent/child links
01783 
01784     // test creation
01785     rval = MB->add_parent_child( sets[9], sets[8] );
01786     if( MB_SUCCESS != rval ) return rval;
01787     list.clear();
01788     rval = MB->get_child_meshsets( sets[9], list );
01789     if( MB_SUCCESS != rval ) return rval;
01790     if( list.size() != 1 || list[0] != sets[8] ) return MB_FAILURE;
01791     list.clear();
01792     rval = MB->get_parent_meshsets( sets[8], list );
01793     if( MB_SUCCESS != rval ) return rval;
01794     if( list.size() != 1 || list[0] != sets[9] ) return MB_FAILURE;
01795 
01796     // test deletion of parent/child
01797     rval = MB->add_parent_child( sets[7], sets[9] );
01798     if( MB_SUCCESS != rval ) return rval;
01799     rval = MB->delete_entities( &sets[9], 1 );
01800     if( MB_SUCCESS != rval ) return rval;
01801     list.clear();
01802     rval = MB->get_parent_meshsets( sets[8], list );
01803     if( !list.empty() ) return MB_FAILURE;
01804     list.clear();
01805     rval = MB->get_child_meshsets( sets[7], list );
01806     if( !list.empty() ) return MB_FAILURE;
01807 
01808     // clean up remaining sets
01809     return MB->delete_entities( sets, 9 );
01810 }
01811 
01812 ErrorCode mb_mesh_sets_set_test()
01813 {
01814     return mb_mesh_sets_test( MESHSET_SET );
01815 }
01816 
01817 ErrorCode mb_mesh_sets_list_test()
01818 {
01819     return mb_mesh_sets_test( MESHSET_ORDERED );
01820 }
01821 
01822 // Verify that all query functions *append* to output Range
01823 ErrorCode mb_mesh_set_appends( int flags )
01824 {
01825     Core moab;
01826     Interface* mb  = &moab;
01827     ErrorCode rval = create_some_mesh( mb );
01828     if( MB_SUCCESS != rval ) return rval;
01829 
01830     // get all handles and subdivide into vertex and non-vertex ents
01831     Range all_ents, verts, elems, results;
01832     rval = mb->get_entities_by_handle( 0, all_ents );
01833     if( MB_SUCCESS != rval ) return rval;
01834     Range::iterator ve = all_ents.upper_bound( MBVERTEX );
01835     verts.merge( all_ents.begin(), ve );
01836     elems.merge( ve, all_ents.end() );
01837 
01838     // If we're not testing queries from the root set,
01839     // create a set containing all the vertices
01840     EntityHandle set = 0;
01841     if( flags != -1 )
01842     {
01843         rval = mb->create_meshset( flags, set );
01844         if( MB_SUCCESS != rval ) return rval;
01845         rval = mb->add_entities( set, verts );
01846         if( MB_SUCCESS != rval ) return rval;
01847     }
01848 
01849     // Test get_entities_by_handle.  This one doesn't make
01850     // much sense if we're testing the root set, but it doesn't
01851     // hurt to test it anyway.
01852     results = elems;
01853     rval    = mb->get_entities_by_handle( set, results );
01854     if( MB_SUCCESS != rval ) return rval;
01855     if( results != all_ents ) return MB_FAILURE;
01856 
01857     // Test get_entities_by_dimension
01858     results = elems;
01859     rval    = mb->get_entities_by_dimension( set, 0, results );
01860     if( MB_SUCCESS != rval ) return rval;
01861     if( results != all_ents ) return MB_FAILURE;
01862 
01863     // Test get_entities_by_type
01864     results = elems;
01865     rval    = mb->get_entities_by_type( set, MBVERTEX, results );
01866     if( MB_SUCCESS != rval ) return rval;
01867     if( results != all_ents ) return MB_FAILURE;
01868 
01869     // choose a single entity for testing tag queries
01870     EntityHandle entity = verts.front();
01871     Range expected( elems );
01872     expected.insert( entity );
01873 
01874     Tag sparse, dense;
01875     const int zero = 0, one = 1;
01876     const void* vals[] = { &one };
01877 
01878     // Test get_entities_by_type_and_tag w/ sparse tag and no value
01879     rval = mb->tag_get_handle( "mb_mesh_set_appends_sparse", 1, MB_TYPE_INTEGER, sparse, MB_TAG_SPARSE | MB_TAG_EXCL );
01880     if( MB_SUCCESS != rval ) return rval;
01881     rval = mb->tag_set_data( sparse, &entity, 1, &one );
01882     if( MB_SUCCESS != rval ) return rval;
01883     results = elems;
01884     rval =
01885         mb->get_entities_by_type_and_tag( set, TYPE_FROM_HANDLE( entity ), &sparse, 0, 1, results, Interface::UNION );
01886     if( MB_SUCCESS != rval ) return rval;
01887     if( results != expected ) return MB_FAILURE;
01888     // Test again, but specify tag value
01889     results = elems;
01890     rval    = mb->get_entities_by_type_and_tag( set, TYPE_FROM_HANDLE( entity ), &sparse, vals, 1, results,
01891                                              Interface::UNION );
01892     if( MB_SUCCESS != rval ) return rval;
01893     if( results != expected ) return MB_FAILURE;
01894 
01895     // Test get_entities_by_type_and_tag w/ dense tag
01896     rval =
01897         mb->tag_get_handle( "mb_mesh_set_appends_dense", 1, MB_TYPE_INTEGER, dense, MB_TAG_DENSE | MB_TAG_EXCL, &zero );
01898     if( MB_SUCCESS != rval ) return rval;
01899     rval = mb->tag_set_data( dense, &entity, 1, &one );
01900     if( MB_SUCCESS != rval ) return rval;
01901     results = elems;
01902     rval =
01903         mb->get_entities_by_type_and_tag( set, TYPE_FROM_HANDLE( entity ), &dense, vals, 1, results, Interface::UNION );
01904     if( MB_SUCCESS != rval ) return rval;
01905     if( results != expected ) return MB_FAILURE;
01906 
01907     return MB_SUCCESS;
01908 }
01909 
01910 ErrorCode mb_mesh_set_set_appends()
01911 {
01912     return mb_mesh_set_appends( MESHSET_SET );
01913 }
01914 
01915 ErrorCode mb_mesh_set_list_appends()
01916 {
01917     return mb_mesh_set_appends( MESHSET_ORDERED );
01918 }
01919 
01920 ErrorCode mb_mesh_set_root_appends()
01921 {
01922     return mb_mesh_set_appends( -1 );
01923 }
01924 
01925 ErrorCode mb_mesh_set_set_replace_test()
01926 {
01927     Core moab;
01928     Interface* mb = &moab;
01929     ErrorCode rval;
01930     Range r;
01931     // create 10 vertices to put in set
01932     std::vector< double > coords( 30 );
01933     rval = mb->create_vertices( &coords[0], 10, r );MB_CHK_ERR( rval );
01934     std::vector< EntityHandle > verts( r.size() );
01935     std::copy( r.begin(), r.end(), verts.begin() );
01936     r.clear();
01937     // create a set
01938     EntityHandle set;
01939     rval = mb->create_meshset( MESHSET_SET, set );MB_CHK_ERR( rval );
01940     // put every other vertex in set
01941     for( size_t i = 0; i < 10; i += 2 )
01942         r.insert( verts[i] );
01943     rval = mb->add_entities( set, r );MB_CHK_ERR( rval );
01944     r.clear();
01945     // swap 3 of the vertices
01946     EntityHandle old_ents[3] = { verts[2], verts[4], verts[6] };
01947     EntityHandle new_ents[3] = { verts[1], verts[9], verts[5] };
01948     rval                     = mb->replace_entities( set, old_ents, new_ents, 3 );MB_CHK_ERR( rval );
01949     // check new set contents
01950     rval = mb->get_entities_by_handle( set, r );MB_CHK_ERR( rval );
01951     Range r2;
01952     r2.insert( verts[0] );
01953     r2.insert( verts[1] );
01954     r2.insert( verts[9] );
01955     r2.insert( verts[5] );
01956     r2.insert( verts[8] );
01957     if( r != r2 )
01958     {
01959         std::cerr << "Range does not contain expected values." << std::endl
01960                   << "  Expected: " << r2 << std::endl
01961                   << "  Actual  : " << r << std::endl;
01962         return MB_FAILURE;
01963     }
01964 
01965     return MB_SUCCESS;
01966 }
01967 
01968 ErrorCode mb_mesh_set_list_replace_test()
01969 {
01970     Core moab;
01971     Interface* mb = &moab;
01972     ErrorCode rval;
01973     // create 10 vertices to put in set
01974     Range r;
01975     std::vector< double > coords( 30 );
01976     rval = mb->create_vertices( &coords[0], 10, r );MB_CHK_ERR( rval );
01977     std::vector< EntityHandle > verts( r.size() );
01978     std::copy( r.begin(), r.end(), verts.begin() );
01979     r.clear();
01980     // create a set
01981     EntityHandle set;
01982     rval = mb->create_meshset( MESHSET_ORDERED, set );MB_CHK_ERR( rval );
01983     // put all vertices in set, but add the first one a second time
01984     std::vector< EntityHandle > list( verts );
01985     list.push_back( verts.front() );
01986     rval = mb->add_entities( set, &list[0], list.size() );MB_CHK_ERR( rval );
01987     // swap 3 of the vertices
01988     EntityHandle old_ents[3] = { verts[2], verts[4], verts[6] };
01989     EntityHandle new_ents[3] = { verts[1], verts[9], verts[5] };
01990     rval                     = mb->replace_entities( set, old_ents, new_ents, 3 );MB_CHK_ERR( rval );
01991     // check new set contents
01992     std::vector< EntityHandle > list2;
01993     rval = mb->get_entities_by_handle( set, list2 );MB_CHK_ERR( rval );
01994     list[2] = verts[1];
01995     list[4] = verts[9];
01996     list[6] = verts[5];
01997     if( list != list2 )
01998     {
01999         std::cerr << "Range does not contain expected values." << std::endl;
02000         std::cerr << "  Expected: ";
02001         std::copy( list.begin(), list.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
02002         std::cerr << std::endl << "  Actual  : ";
02003         std::copy( list2.begin(), list2.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
02004         std::cerr << std::endl;
02005         return MB_FAILURE;
02006     }
02007     // now try replacing a repeated value
02008     rval = mb->replace_entities( set, &verts[0], &verts[3], 1 );MB_CHK_ERR( rval );
02009     list[0] = list[10] = verts[3];
02010     list2.clear();
02011     rval = mb->get_entities_by_handle( set, list2 );MB_CHK_ERR( rval );
02012     if( list != list2 )
02013     {
02014         std::cerr << "Range does not contain expected values." << std::endl;
02015         std::cerr << "  Expected: ";
02016         std::copy( list.begin(), list.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
02017         std::cerr << std::endl << "  Actual  : ";
02018         std::copy( list2.begin(), list2.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
02019         std::cerr << std::endl;
02020         return MB_FAILURE;
02021     }
02022 
02023     return MB_SUCCESS;
02024 }
02025 
02026 /* Test the following changes to a meshset:
02027   set       MB-> tracking
02028   tracking  MB-> set
02029   unordered MB-> ordered
02030   ordered   MB-> unordered
02031 */
02032 ErrorCode mb_mesh_set_flag_test()
02033 {
02034     Core moab;
02035     Interface* mb = &moab;
02036 
02037     ErrorCode rval;
02038     // create 10 vertices to put in set
02039     Range verts;
02040     std::vector< double > coords( 30 );
02041     rval = mb->create_vertices( &coords[0], 10, verts );MB_CHK_ERR( rval );
02042 
02043     // CHECK SET->TRACKING
02044     // create a set and add the verts
02045     EntityHandle set;
02046     rval = mb->create_meshset( MESHSET_SET, set );MB_CHK_ERR( rval );
02047     rval = mb->add_entities( set, verts );MB_CHK_ERR( rval );
02048     // the verts should not be tracking adjacencies
02049     Range adj_sets;
02050     rval = mb->get_adjacencies( verts, 4, false, adj_sets );MB_CHK_ERR( rval );
02051     if( !adj_sets.empty() )
02052     {
02053         std::cerr << "range should be empty but contains:" << std::endl;
02054         rval = mb->list_entities( adj_sets );
02055         return MB_FAILURE;
02056     }
02057     // check to make sure the flags on MESHSET_SET
02058     unsigned int flags;
02059     rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
02060     if( !( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || ( MESHSET_ORDERED & flags ) )
02061     {
02062         std::cerr << "set should be MESHSET_SET only, flags=" << flags << std::endl;
02063         return MB_FAILURE;
02064     }
02065     // change to a tracking set and check flags
02066     rval = mb->set_meshset_options( set, MESHSET_TRACK_OWNER );MB_CHK_ERR( rval );
02067     rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
02068     if( ( MESHSET_SET & flags ) || !( MESHSET_TRACK_OWNER & flags ) || ( MESHSET_ORDERED & flags ) )
02069     {
02070         std::cerr << "set should be MESHSET_TRACK_OWNER only, flags=" << flags << std::endl;
02071         return MB_FAILURE;
02072     }
02073     // check adjacencies
02074     rval = mb->get_adjacencies( verts, 4, false, adj_sets );MB_CHK_ERR( rval );
02075     if( 1 != adj_sets.size() )
02076     {
02077         std::cerr << "range should contain a set, adj_sets.size()=" << adj_sets.size() << std::endl;
02078         rval = mb->list_entities( adj_sets );
02079         return MB_FAILURE;
02080     }
02081 
02082     // CHECK TRACKING->SET
02083     // change to a standard set and check flags
02084     rval = mb->set_meshset_options( set, MESHSET_SET );MB_CHK_ERR( rval );
02085     rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
02086     if( !( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || ( MESHSET_ORDERED & flags ) )
02087     {
02088         std::cerr << "set should be MESHSET_SET only, flags=" << flags << std::endl;
02089         return MB_FAILURE;
02090     }
02091     // the set should no longer be adjacent to the vertices
02092     adj_sets.clear();
02093     rval = mb->get_adjacencies( verts, 4, false, adj_sets );MB_CHK_ERR( rval );
02094     if( !adj_sets.empty() )
02095     {
02096         std::cerr << "range should be empty but contains:" << std::endl;
02097         rval = mb->list_entities( adj_sets );
02098         return MB_FAILURE;
02099     }
02100     // CHECK UNORDERED->ORDERED
02101     // add a duplicate vert
02102     rval = mb->add_entities( set, &verts.front(), 1 );MB_CHK_ERR( rval );
02103     // unordered sets cannot hold duplicates so size shouldn't change
02104     std::vector< EntityHandle > entities;
02105     rval = mb->get_entities_by_handle( set, entities );
02106     if( 10 != entities.size() )
02107     {
02108         std::cerr << "set should not hold duplicate entities" << std::endl;
02109         return MB_FAILURE;
02110     }
02111     // change to an ordered set and check flags
02112     rval = mb->set_meshset_options( set, MESHSET_ORDERED );MB_CHK_ERR( rval );
02113     rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
02114     if( ( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || !( MESHSET_ORDERED & flags ) )
02115     {
02116         std::cerr << "set should be MESHSET_ORDERED only, flags=" << flags << std::endl;
02117         return MB_FAILURE;
02118     }
02119     // swap the order with some entities to that the handles aren't ordered
02120     rval = mb->clear_meshset( &set, 1 );MB_CHK_ERR( rval );
02121     entities.clear();
02122     entities.resize( 2 );
02123     entities[0] = verts[1];
02124     entities[1] = verts[0];
02125     rval        = mb->add_entities( set, &entities[0], 2 );MB_CHK_ERR( rval );
02126     // check to ensure the entities keep their order
02127     entities.clear();
02128     rval = mb->get_entities_by_handle( set, entities );
02129     if( verts[0] != entities[1] || verts[1] != entities[0] )
02130     {
02131         std::cerr << "ordered set did not keep its order" << std::endl;
02132         return MB_FAILURE;
02133     }
02134 
02135     // CHECK ORDERED->UNORDERED
02136     // change to an unordered set and check flags
02137     rval = mb->set_meshset_options( set, MESHSET_SET );MB_CHK_ERR( rval );
02138     rval = mb->get_meshset_options( set, flags );MB_CHK_ERR( rval );
02139     if( !( MESHSET_SET & flags ) || ( MESHSET_TRACK_OWNER & flags ) || MESHSET_ORDERED & flags )
02140     {
02141         std::cerr << "set should be MESHSET_SET only, flags=" << flags << std::endl;
02142         return MB_FAILURE;
02143     }
02144     // the entities in the set should now be ordered by handle
02145     entities.clear();
02146     rval = mb->get_entities_by_handle( set, entities );
02147     if( verts[0] != entities[0] || verts[1] != entities[1] )
02148     {
02149         std::cerr << "unordered set is still ordered" << std::endl;
02150         return MB_FAILURE;
02151     }
02152     return MB_SUCCESS;
02153 }
02154 
02155 #ifdef MOAB_HAVE_NETCDF
02156 // number of entities of type MBVERTEX, MBEDGE, MBDTri, MBQUAD, MBTET, and MBHEX
02157 // in mbtest1.g  (all other values are 0.
02158 static const EntityType types[]                       = { MBVERTEX, MBEDGE, MBTRI, MBQUAD, MBTET, MBHEX };
02159 const int num_types                                   = sizeof( types ) / sizeof( types[0] );
02160 static const unsigned int num_entities[num_types + 1] = { 47, 12, 18, 8, 22, 8, 0 };
02161 
02162 ErrorCode mb_delete_mesh_test()
02163 {
02164     Core moab;
02165     Interface* gMB  = &moab;
02166     ErrorCode error = load_file_one( gMB );
02167     if( MB_SUCCESS != error ) return error;
02168 
02169     // Lets also test the global MB pointer (gMB) here.
02170     error = gMB->delete_mesh();
02171     if( error != MB_SUCCESS ) return error;
02172 
02173     // load the mesh again
02174     error = load_file_one( gMB );
02175     if( error != MB_SUCCESS ) return error;
02176 
02177     // step through each element type
02178     for( EntityType type = MBVERTEX; type != MBENTITYSET; type++ )
02179     {
02180         // There should be entities
02181         Range entities;
02182         error = gMB->get_entities_by_type( 0, type, entities );
02183         if( error != MB_SUCCESS ) return error;
02184 
02185         size_t idx = std::find( types, types + num_types, type ) - types;
02186         if( entities.size() != num_entities[idx] ) return MB_FAILURE;
02187     }
02188 
02189     return MB_SUCCESS;
02190 }
02191 
02192 ErrorCode mb_mesh_set_tracking_test()
02193 {
02194     Core moab;
02195     Interface* MB = &moab;
02196 
02197     // read in a file so you have some data in the database
02198 
02199     ErrorCode error = load_file_one( MB );
02200     if( error != MB_SUCCESS ) return error;
02201 
02202     EntityHandle ms1, ms2, ms3;
02203 
02204     // create meshsets
02205     ErrorCode result = MB->create_meshset( MESHSET_TRACK_OWNER | MESHSET_ORDERED, ms1 );
02206     if( result != MB_SUCCESS ) return result;
02207     result = MB->create_meshset( MESHSET_SET | MESHSET_TRACK_OWNER, ms2 );
02208     if( result != MB_SUCCESS ) return result;
02209     result = MB->create_meshset( MESHSET_SET | MESHSET_TRACK_OWNER, ms3 );
02210     if( result != MB_SUCCESS ) return result;
02211 
02212     // get all hexes
02213     Range hexes;
02214     result = MB->get_entities_by_type( 0, MBHEX, hexes );
02215     if( result != MB_SUCCESS ) return result;
02216 
02217     // get all tris
02218     Range tris;
02219     result = MB->get_entities_by_type( 0, MBTRI, tris );
02220     if( result != MB_SUCCESS ) return result;
02221 
02222     // get all tets
02223     Range temp_range;
02224     result = MB->get_entities_by_type( 0, MBTET, temp_range );
02225     if( result != MB_SUCCESS ) return result;
02226 
02227     // copy all the tets from the range into a vector 'tets'
02228     std::vector< EntityHandle > tets( temp_range.size() );
02229     std::copy( temp_range.begin(), temp_range.end(), tets.begin() );
02230 
02231     // Quick check on 'get_entities_by_dimension()'
02232     Range dim_3_range;
02233     result = MB->get_entities_by_dimension( 0, 3, dim_3_range );
02234     if( result != MB_SUCCESS ) return result;
02235 
02236     // hexes and tets should be only dimension 3 entities
02237     if( hexes.size() + tets.size() != dim_3_range.size() ) return MB_FAILURE;
02238 
02239     // put all hexes in ms1, ms2, ms3
02240     result = MB->add_entities( ms1, hexes );  // add ents in a range
02241     if( result != MB_SUCCESS ) return result;
02242     // to ordered meshset
02243 
02244     result = MB->add_entities( ms2, hexes );  // add ents in a range
02245     if( result != MB_SUCCESS ) return result;
02246     // to unordered meshset
02247 
02248     result = MB->add_entities( ms3, hexes );
02249     if( result != MB_SUCCESS ) return result;
02250 
02251     // put all tets in ms1, ms2
02252     if( MB->add_entities( ms1, &tets[0], tets.size() ) != MB_SUCCESS )  // add ents in a vector
02253         return MB_FAILURE;                                              // to ordered meshset
02254 
02255     if( MB->add_entities( ms2, &tets[0], tets.size() ) != MB_SUCCESS )  // add ents in a vector
02256         return MB_FAILURE;                                              // to unordered meshset
02257 
02258     // put all tris in ms1
02259     result = MB->add_entities( ms1, tris );
02260     if( result != MB_SUCCESS ) return result;
02261 
02262     Range::iterator iter;
02263     iter = tris.begin();
02264 
02265     std::vector< EntityHandle > temp_vec;
02266 
02267     // ask a tri which meshsets it is in
02268     result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
02269     if( result != MB_SUCCESS ) return result;
02270 
02271     // cout<<"tris temp_vec.size() = "<<temp_vec.size()<<endl;
02272     if( temp_vec.size() != 2 ) return MB_FAILURE;
02273 
02274     // ask a tet which meshsets it is in
02275     temp_vec.clear();
02276     std::vector< EntityHandle >::iterator vec_iter = tets.begin();
02277     result                                         = MB->get_adjacencies( &( *vec_iter ), 1, 4, false, temp_vec );
02278     if( result != MB_SUCCESS ) return result;
02279 
02280     // cout<<"tet temp_vec.size() = "<<temp_vec.size()<<endl;
02281     if( temp_vec.size() != 3 ) return MB_FAILURE;
02282 
02283     // ask a hex which meshsets it is in
02284     temp_vec.clear();
02285     iter   = hexes.begin();
02286     result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
02287     if( result != MB_SUCCESS ) return result;
02288 
02289     // should be in 4 temp_vec
02290     if( temp_vec.size() != 4 ) return MB_FAILURE;
02291 
02292     // take this hex out of the ms1, ms2, ms3
02293     if( MB->remove_entities( ms1, &( *iter ), 1 ) != MB_SUCCESS )  // remove ents in a vector
02294         return MB_FAILURE;                                         // from ordered meshset
02295 
02296     if( MB->remove_entities( ms2, &( *iter ), 1 ) != MB_SUCCESS )  // remove ents in a vector
02297         return MB_FAILURE;                                         // from unordered meshset
02298 
02299     temp_range.clear();
02300     temp_range.insert( *iter );
02301     if( MB->remove_entities( ms3, temp_range ) != MB_SUCCESS )  // remove ents in a range
02302         return MB_FAILURE;                                      // from unordered meshset
02303 
02304     // ask the hex how many meshsets it is in
02305     temp_vec.clear();
02306     result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
02307     if( result != MB_SUCCESS ) return result;
02308     if( temp_vec.size() != 1 ) return MB_FAILURE;
02309 
02310     // add the hex back into ms1
02311     result = MB->add_entities( ms1, temp_range );
02312     if( result != MB_SUCCESS ) return result;
02313 
02314     // ask the hex how many meshsets it is in
02315     temp_vec.clear();
02316     result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
02317     if( result != MB_SUCCESS ) return result;
02318     if( temp_vec.size() != 2 ) return MB_FAILURE;
02319 
02320     temp_range.clear();
02321     temp_range.insert( *iter );
02322     if( MB->remove_entities( ms1, temp_range ) != MB_SUCCESS )  // remove ents in a range
02323         return MB_FAILURE;                                      // from an ordered meshset
02324 
02325     // ask the hex how many meshsets it is in
02326     temp_vec.clear();
02327     result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
02328     if( result != MB_SUCCESS ) return result;
02329     if( temp_vec.size() != 1 ) return MB_FAILURE;
02330 
02331     // Deleting a meshset
02332 
02333     iter = tris.begin();
02334     temp_vec.clear();
02335     // ask a tri which meshsets it is in
02336     result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
02337     if( result != MB_SUCCESS ) return result;
02338 
02339     if( temp_vec.size() != 2 ) return MB_FAILURE;
02340 
02341     // Try deleting a meshset
02342     result = MB->delete_entities( &ms1, 1 );
02343     if( result != MB_SUCCESS ) return result;
02344 
02345     temp_vec.clear();
02346     // Query tri again for meshsets it's in
02347     result = MB->get_adjacencies( &( *iter ), 1, 4, false, temp_vec );
02348     if( result != MB_SUCCESS ) return result;
02349 
02350     if( temp_vec.size() != 1 ) return MB_FAILURE;
02351 
02352     // Delete an entitiy from ms2....make sure it's removed out of ms2
02353     int num_before = 0;
02354     MB->get_number_entities_by_handle( ms2, num_before );
02355     vec_iter = tets.begin();
02356     result   = MB->delete_entities( &( *vec_iter ), 1 );
02357     if( result != MB_SUCCESS ) return result;
02358 
02359     int num_after = 0;
02360     MB->get_number_entities_by_handle( ms2, num_after );
02361     if( num_before != num_after + 1 ) return MB_FAILURE;
02362 
02363     return MB_SUCCESS;
02364 }
02365 #endif
02366 
02367 // Compare internal representation of contents for a list (MESHSET_ORDERED)
02368 // set to expected contents.  Assumes expected contents are correctly
02369 // ordered.
02370 static ErrorCode check_list_meshset_internal( const EntityHandle* expected, int num_expected,
02371                                               const EntityHandle* contents, int length )
02372 {
02373     bool okay = true;
02374     for( int i = 0; i < std::min( num_expected, length ); ++i )
02375     {
02376         if( expected[i] != contents[i] )
02377         {
02378             std::cerr << "List set contents differ at index " << i << ": expected " << expected[i] << " but got "
02379                       << contents[i] << std::endl;
02380             okay = false;
02381         }
02382     }
02383     if( num_expected > length )
02384     {
02385         std::cerr << "List set is missing " << num_expected - length << "handles" << std::endl;
02386         okay = false;
02387     }
02388     else if( length > num_expected )
02389     {
02390         std::cerr << "List set has " << num_expected - length << " extra handles" << std::endl;
02391         okay = false;
02392     }
02393 
02394     if( okay ) return MB_SUCCESS;
02395 
02396     std::cerr << "Expected contents: ";
02397     if( !num_expected )
02398         std::cerr << "(empty)";
02399     else
02400         std::cerr << expected[0];
02401     for( int i = 1; i < num_expected; ++i )
02402         std::cerr << ", " << expected[i];
02403     std::cerr << std::endl;
02404 
02405     std::cerr << "Actual contents: ";
02406     if( !length )
02407         std::cerr << "(empty)";
02408     else
02409         std::cerr << contents[0];
02410     for( int i = 1; i < length; ++i )
02411         std::cerr << ", " << contents[i];
02412     std::cerr << std::endl;
02413 
02414     return MB_FAILURE;
02415 }
02416 
02417 // Compare internal representation of contents for a ranged (MESHSET_SET)
02418 // set to expected contents.  Assumes expected contents are correctly
02419 // ordered.
02420 static ErrorCode check_ranged_meshset_internal( const EntityHandle* expected, int num_expected,
02421                                                 const EntityHandle* contents, int length )
02422 {
02423     if( length % 2 )
02424     {
02425         std::cerr << "Range set is corrupt.  Odd number of handles in content list" << std::endl;
02426         std::cerr << "Actual contents: " << contents[0];
02427         for( int i = 1; i < length; ++i )
02428             std::cerr << ", " << contents[i];
02429         std::cerr << std::endl;
02430         return MB_FAILURE;
02431     }
02432     bool okay = true;
02433     // check that all range pairs are valid (first handle less than or
02434     // equal to second)
02435     for( int i = 0; i < length; i += 2 )
02436     {
02437         if( contents[i] > contents[i + 1] )
02438         {
02439             std::cerr << "Range set has invalid range pair at index " << i << ": [" << contents[i] << ','
02440                       << contents[i + 1] << ']' << std::endl;
02441             okay = false;
02442         }
02443     }
02444     // check that all range pairs are sorted and non-overlapping
02445     // (start of a range must be greater than end of previous range)
02446     for( int i = 2; i < length; i += 2 )
02447     {
02448         if( contents[i] < contents[i - 1] )
02449         {
02450             std::cerr << "Range set has incorrectly ordered ranges at index " << i << ": [...," << contents[i - 1]
02451                       << "], [" << contents[i] << ",...]" << std::endl;
02452             okay = false;
02453         }
02454         if( contents[i] == contents[i - 1] + 1 )
02455         {
02456             std::cerr << "Range set has pairs that should have been merged at index " << i << ": [...,"
02457                       << contents[i - 1] << "], [" << contents[i] << ",...]" << std::endl;
02458             okay = false;
02459         }
02460     }
02461     if( !okay )
02462     {
02463         std::cerr << "Actual contents: ";
02464         if( !length )
02465             std::cerr << "(empty)";
02466         else
02467             std::cerr << '[' << contents[0] << ',' << contents[1] << ']';
02468         for( int i = 2; i < length; i += 2 )
02469             std::cerr << ", [" << contents[i] << ',' << contents[i + 1] << ']';
02470         std::cerr << std::endl;
02471         return MB_FAILURE;
02472     }
02473 
02474     int j = 0;
02475     for( int i = 0; i < length; i += 2 )
02476     {
02477         for( ; j < num_expected && expected[j] < contents[i]; ++j )
02478         {
02479             std::cerr << "Range set missing expected handle: " << expected[j] << std::endl;
02480             okay = false;
02481         }
02482         int k = j;
02483         while( k < num_expected && expected[k] <= contents[i + 1] )
02484             ++k;
02485         if( ( EntityHandle )( k - j ) <= ( contents[i + 1] - contents[i] ) )
02486         {
02487             std::cerr << "Handle range [" << contents[i] << ',' << contents[i + 1]
02488                       << "] contains unexpected handles.  Expected handles: ";
02489             if( k == j )
02490                 std::cerr << "(none)" << std::endl;
02491             else
02492             {
02493                 std::cerr << expected[j];
02494                 for( ++j; j < k; ++j )
02495                     std::cerr << ", " << expected[j];
02496                 std::cerr << std::endl;
02497             }
02498             okay = false;
02499         }
02500         j = k;
02501     }
02502 
02503     if( okay ) return MB_SUCCESS;
02504 
02505     std::cerr << "Expected contents: ";
02506     if( !num_expected )
02507         std::cerr << "(empty)";
02508     else
02509         std::cerr << expected[0];
02510     for( int i = 1; i < num_expected; ++i )
02511         std::cerr << ", " << expected[i];
02512     std::cerr << std::endl;
02513 
02514     std::cerr << "Actual contents: ";
02515     if( !length )
02516         std::cerr << "(empty)";
02517     else
02518         std::cerr << '[' << contents[0] << ',' << contents[1] << ']';
02519     for( int i = 2; i < length; i += 2 )
02520         std::cerr << ", [" << contents[i] << ',' << contents[i + 1] << ']';
02521     std::cerr << std::endl;
02522 
02523     return MB_FAILURE;
02524 }
02525 
02526 // Check the internal representation of a meshset
02527 // to verify that it is correct.
02528 static ErrorCode check_meshset_internal( Interface& mb, EntityHandle set, const EntityHandle* expected,
02529                                          int num_expected )
02530 {
02531     ErrorCode rval;
02532     WriteUtilIface* tool = 0;
02533     rval                 = mb.query_interface( tool );MB_CHK_ERR( rval );
02534 
02535     const EntityHandle* contents;
02536     int length;
02537     unsigned char flags;
02538     rval = tool->get_entity_list_pointers( &set, 1, &contents, WriteUtilIface::CONTENTS, &length, &flags );MB_CHK_ERR( rval );
02539     ErrorCode rval1 = mb.release_interface( tool );MB_CHK_ERR( rval1 );
02540 
02541     if( flags & MESHSET_ORDERED )
02542         rval = check_list_meshset_internal( expected, num_expected, contents, length );
02543     else
02544         rval = check_ranged_meshset_internal( expected, num_expected, contents, length );MB_CHK_ERR( rval );
02545     return MB_SUCCESS;
02546 }
02547 
02548 ErrorCode mb_mesh_set_set_add_remove_test()
02549 {
02550     Core core;
02551     Interface& mb = core;
02552     EntityHandle set;
02553     ErrorCode rval = mb.create_meshset( MESHSET_SET, set );MB_CHK_ERR( rval );
02554 
02555     EntityHandle list1[] = { 10, 16, 18, 20, 24, 27 };
02556     size_t len1          = sizeof( list1 ) / sizeof( list1[0] );
02557     EntityHandle list2[] = { 10, 16, 17, 18, 19, 20, 24, 27 };
02558     size_t len2          = sizeof( list2 ) / sizeof( list2[0] );
02559     rval                 = mb.add_entities( set, list1, len1 );MB_CHK_ERR( rval );
02560     rval = check_meshset_internal( mb, set, list1, len1 );MB_CHK_ERR( rval );
02561     rval = mb.add_entities( set, list2, len2 );MB_CHK_ERR( rval );
02562     EntityHandle exp12[] = { 10, 16, 17, 18, 19, 20, 24, 27 };
02563     size_t len12         = sizeof( exp12 ) / sizeof( exp12[0] );
02564     rval                 = check_meshset_internal( mb, set, exp12, len12 );MB_CHK_ERR( rval );
02565 
02566     EntityHandle list3[] = { 15, 16, 18, 20, 21, 24, 28 };
02567     size_t len3          = sizeof( list3 ) / sizeof( list3[0] );
02568     rval                 = mb.remove_entities( set, list3, len3 );MB_CHK_ERR( rval );
02569     EntityHandle exp123[] = { 10, 17, 19, 27 };
02570     size_t len123         = sizeof( exp123 ) / sizeof( exp123[0] );
02571     rval                  = check_meshset_internal( mb, set, exp123, len123 );MB_CHK_ERR( rval );
02572 
02573     EntityHandle list4[] = { 18, 10, 11, 12, 13, 14, 15, 16 };
02574     size_t len4          = sizeof( list4 ) / sizeof( list4[0] );
02575     rval                 = mb.add_entities( set, list4, len4 );MB_CHK_ERR( rval );
02576     EntityHandle exp14[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 27 };
02577     size_t len14         = sizeof( exp14 ) / sizeof( exp14[0] );
02578     rval                 = check_meshset_internal( mb, set, exp14, len14 );MB_CHK_ERR( rval );
02579 
02580     EntityHandle list5[] = { 9, 10, 12, 13, 14, 15, 19, 20 };
02581     rval                 = mb.remove_entities( set, list5, sizeof( list5 ) / sizeof( list5[0] ) );MB_CHK_ERR( rval );
02582     EntityHandle exp5[] = { 11, 16, 17, 18, 27 };
02583     rval                = check_meshset_internal( mb, set, exp5, sizeof( exp5 ) / sizeof( exp5[0] ) );MB_CHK_ERR( rval );
02584 
02585     EntityHandle list6[] = { 9, 10, 15, 16, 18, 19, 28 };
02586     rval                 = mb.add_entities( set, list6, sizeof( list6 ) / sizeof( list6[0] ) );MB_CHK_ERR( rval );
02587     EntityHandle exp6[] = { 9, 10, 11, 15, 16, 17, 18, 19, 27, 28 };
02588     rval                = check_meshset_internal( mb, set, exp6, sizeof( exp6 ) / sizeof( exp6[0] ) );MB_CHK_ERR( rval );
02589 
02590     EntityHandle list7[] = { 13, 19, 27, 28 };
02591     rval                 = mb.add_entities( set, list7, sizeof( list7 ) / sizeof( list7[0] ) );MB_CHK_ERR( rval );
02592     EntityHandle exp7[] = { 9, 10, 11, 13, 15, 16, 17, 18, 19, 27, 28 };
02593     rval                = check_meshset_internal( mb, set, exp7, sizeof( exp7 ) / sizeof( exp7[0] ) );MB_CHK_ERR( rval );
02594 
02595     EntityHandle list8[] = { 12, 14, 33 };
02596     rval                 = mb.add_entities( set, list8, sizeof( list8 ) / sizeof( list8[0] ) );MB_CHK_ERR( rval );
02597     EntityHandle exp8[] = { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 27, 28, 33 };
02598     rval                = check_meshset_internal( mb, set, exp8, sizeof( exp8 ) / sizeof( exp8[0] ) );MB_CHK_ERR( rval );
02599 
02600     EntityHandle list9[] = { 29, 30, 31, 32, 34 };
02601     rval                 = mb.remove_entities( set, list9, sizeof( list9 ) / sizeof( list9[0] ) );MB_CHK_ERR( rval );
02602     rval = check_meshset_internal( mb, set, exp8, sizeof( exp8 ) / sizeof( exp8[0] ) );MB_CHK_ERR( rval );
02603 
02604     EntityHandle list10[] = { 9, 11, 13, 17, 18, 19, 28, 33, 100 };
02605     rval                  = mb.remove_entities( set, list10, sizeof( list10 ) / sizeof( list10[0] ) );MB_CHK_ERR( rval );
02606     EntityHandle exp10[] = { 10, 12, 14, 15, 16, 27 };
02607     rval                 = check_meshset_internal( mb, set, exp10, sizeof( exp10 ) / sizeof( exp10[0] ) );MB_CHK_ERR( rval );
02608 
02609     EntityHandle list11[] = { 11, 12, 13, 14, 27, 28 };
02610     rval                  = mb.remove_entities( set, list11, sizeof( list11 ) / sizeof( list11[0] ) );MB_CHK_ERR( rval );
02611     EntityHandle exp11[] = { 10, 15, 16 };
02612     rval                 = check_meshset_internal( mb, set, exp11, sizeof( exp11 ) / sizeof( exp11[0] ) );MB_CHK_ERR( rval );
02613 
02614     EntityHandle list12[] = { 1, 10, 15, 16 };
02615     rval                  = mb.remove_entities( set, list12, sizeof( list12 ) / sizeof( list12[0] ) );MB_CHK_ERR( rval );
02616     rval = check_meshset_internal( mb, set, 0, 0 );MB_CHK_ERR( rval );
02617 
02618     return MB_SUCCESS;
02619 }
02620 
02621 ErrorCode mb_higher_order_test()
02622 {
02623     Core moab;
02624     Interface* MB = &moab;
02625 
02626     double nodes_array[7][3];
02627 
02628     nodes_array[0][0] = 0;
02629     nodes_array[0][1] = 0;
02630     nodes_array[0][2] = 0;
02631     nodes_array[1][0] = 2;
02632     nodes_array[1][1] = 0;
02633     nodes_array[1][2] = 0;
02634     nodes_array[2][0] = 1;
02635     nodes_array[2][1] = 2;
02636     nodes_array[2][2] = 1;
02637     nodes_array[3][0] = 1;
02638     nodes_array[3][1] = 0;
02639     nodes_array[3][2] = 0;
02640     nodes_array[4][0] = 1.5;
02641     nodes_array[4][1] = 0.5;
02642     nodes_array[4][2] = 0.5;
02643     nodes_array[5][0] = 0.5;
02644     nodes_array[5][1] = 0.5;
02645     nodes_array[5][2] = 0.5;
02646     nodes_array[6][0] = 1;
02647     nodes_array[6][1] = 1;
02648     nodes_array[6][2] = 0.5;
02649 
02650     // create the nodes
02651     std::vector< EntityHandle > connectivity( 8 );
02652     EntityHandle node_handle;
02653     int i;
02654     for( i = 0; i < 7; i++ )
02655     {
02656         if( MB->create_vertex( nodes_array[i], node_handle ) != MB_SUCCESS ) return MB_FAILURE;
02657         connectivity[i] = node_handle;
02658     }
02659 
02660     // create the higher order tri
02661     EntityHandle tri_handle;
02662     ErrorCode result = MB->create_element( MBTRI, &connectivity[0], 6, tri_handle );
02663     if( result != MB_SUCCESS ) return result;
02664 
02665     // create the higher order tri
02666     std::vector< EntityHandle > other_conn( 3 );
02667 
02668     double other_nodes[3][3];
02669     other_nodes[0][0] = 1.999;
02670     other_nodes[0][1] = 1.999;
02671     other_nodes[0][2] = 1.999;
02672     other_nodes[1][0] = 2.999;
02673     other_nodes[1][1] = 2.999;
02674     other_nodes[1][2] = 2.999;
02675     other_nodes[2][0] = 3.999;
02676     other_nodes[2][1] = 3.999;
02677     other_nodes[2][2] = 3.999;
02678 
02679     for( i = 0; i < 3; i++ )
02680     {
02681         if( MB->create_vertex( other_nodes[i], node_handle ) != MB_SUCCESS ) return MB_FAILURE;
02682         other_conn[i] = node_handle;
02683     }
02684 
02685     EntityHandle other_tri_handle;
02686     result = MB->create_element( MBTRI, &other_conn[0], 3, other_tri_handle );
02687     if( result != MB_SUCCESS ) return result;
02688 
02689     // get the connectivity now
02690     std::vector< EntityHandle > retrieved_conn;
02691 
02692     result = MB->get_connectivity( &tri_handle, 1, retrieved_conn );
02693     if( result != MB_SUCCESS ) return result;
02694 
02695     unsigned int k;
02696     for( k = 0; k < retrieved_conn.size(); k++ )
02697         if( connectivity[k] != retrieved_conn[k] ) return MB_FAILURE;
02698 
02699     result = MB->get_connectivity( &other_tri_handle, 1, retrieved_conn );
02700     if( result != MB_SUCCESS ) return result;
02701 
02702     for( k = 0; k < other_conn.size(); k++ )
02703         if( other_conn[k] != retrieved_conn[k] ) return MB_FAILURE;
02704 
02705     // now let's just try getting the topological connectivity (the 3 corner vertices)
02706     std::vector< EntityHandle > topo_conn;
02707     result = MB->get_connectivity( &other_tri_handle, 1, topo_conn, true );
02708     if( result != MB_SUCCESS ) return result;
02709 
02710     if( topo_conn.size() != 3 ) return MB_FAILURE;
02711 
02712     for( k = 0; k < 3; k++ )
02713         if( topo_conn[k] != retrieved_conn[k] ) return MB_FAILURE;
02714 
02715     // short check to make sure that Core::handle_from_id() works
02716     unsigned long handle_id = MB->id_from_handle( node_handle );
02717 
02718     EntityHandle test_handle;
02719     result = MB->handle_from_id( MBVERTEX, handle_id, test_handle );
02720     if( result != MB_SUCCESS ) return result;
02721 
02722     if( test_handle != node_handle ) return MB_FAILURE;
02723 
02724     handle_id = MB->id_from_handle( tri_handle );
02725 
02726     result = MB->handle_from_id( MBTRI, handle_id, test_handle );
02727     if( result != MB_SUCCESS ) return result;
02728 
02729     if( test_handle != tri_handle ) return MB_FAILURE;
02730 
02731     // make up some bogus id
02732     handle_id = 2140824;
02733 
02734     result = MB->handle_from_id( MBTRI, handle_id, test_handle );
02735     if( result != MB_ENTITY_NOT_FOUND ) return MB_FAILURE;
02736 
02737     result = MB->handle_from_id( MBVERTEX, handle_id, test_handle );
02738     if( result != MB_ENTITY_NOT_FOUND ) return MB_FAILURE;
02739 
02740     return MB_SUCCESS;
02741 }
02742 
02743 ErrorCode mb_bit_tags_test()
02744 {
02745     Core moab;
02746     Interface* MB     = &moab;
02747     ErrorCode success = create_some_mesh( MB );
02748     if( MB_SUCCESS != success ) return success;
02749 
02750     Tag bit_tag;
02751     Range entities;
02752     MB->get_entities_by_type( 0, MBVERTEX, entities );
02753 
02754     if( MB->tag_get_handle( "bit on vertex", 3, MB_TYPE_BIT, bit_tag, MB_TAG_CREAT ) != MB_SUCCESS )
02755     {
02756         cout << "couldn't create bit tag" << endl;
02757         return MB_FAILURE;
02758     }
02759 
02760     Range::iterator iter;
02761     unsigned char bits;
02762     for( iter = entities.begin(); iter != entities.end(); ++iter )
02763     {
02764         // tag each vertex with the low 3 bits of the entity handle
02765         bits    = ( ( *iter ) & 0x7 );
02766         success = MB->tag_set_data( bit_tag, &( *iter ), 1, &bits );
02767         if( success != MB_SUCCESS ) return MB_FAILURE;
02768     }
02769 
02770     bits = 0;
02771     for( iter = entities.begin(); iter != entities.end(); ++iter )
02772     {
02773         // tag each vertex with the low 3 bits of the entity handle
02774         success = MB->tag_get_data( bit_tag, &( *iter ), 1, &bits );
02775         if( success != MB_SUCCESS ) return MB_FAILURE;
02776 
02777         if( bits != ( ( *iter ) & 0x7 ) ) return MB_FAILURE;
02778     }
02779 
02780     // test range-based query for all vertices
02781     std::vector< unsigned char > data( entities.size() );
02782     success = MB->tag_get_data( bit_tag, entities, &data[0] );
02783     if( MB_SUCCESS != success ) return success;
02784     std::vector< unsigned char >::iterator i = data.begin();
02785     for( iter = entities.begin(); iter != entities.end(); ++iter, ++i )
02786         if( *i != ( ( *iter ) & 0x7 ) ) return MB_FAILURE;
02787 
02788     // test vector-based query for all vertices
02789     std::vector< EntityHandle > verts( entities.begin(), entities.end() );
02790     success = MB->tag_get_data( bit_tag, &verts[0], verts.size(), &data[0] );
02791     if( MB_SUCCESS != success ) return success;
02792     i = data.begin();
02793     for( iter = entities.begin(); iter != entities.end(); ++iter, ++i )
02794         if( *i != ( ( *iter ) & 0x7 ) ) return MB_FAILURE;
02795 
02796     // test default value
02797     const unsigned char default_bits = '\005';  // 0000 0101
02798     Tag tag2;
02799     success = MB->tag_get_handle( "bit with default", 4, MB_TYPE_BIT, tag2, MB_TAG_CREAT, &default_bits );
02800     if( MB_SUCCESS != success )
02801     {
02802         cout << "Failed to create bit tag with default value" << std::endl;
02803         return success;
02804     }
02805 
02806     // set value to zero on a single vertex
02807     bits            = 0;
02808     EntityHandle zh = verts[verts.size() / 2];
02809     success         = MB->tag_set_data( tag2, &zh, 1, &bits );
02810     if( MB_SUCCESS != success ) return success;
02811 
02812     // get tag values for all entities
02813     data.clear();
02814     data.resize( verts.size(), 0x7A );  // initialize with 0111 1010
02815     success = MB->tag_get_data( tag2, entities, &data[0] );
02816     if( MB_SUCCESS != success ) return success;
02817 
02818     // check values
02819     i = data.begin();
02820     for( iter = entities.begin(); iter != entities.end(); ++iter, ++i )
02821         if( *iter == zh && *i )  // the one we set to zero
02822             return MB_FAILURE;
02823         else if( *iter != zh && *i != default_bits )
02824             return MB_FAILURE;
02825 
02826     return MB_SUCCESS;
02827 }
02828 
02829 #ifdef MOAB_HAVE_NETCDF
02830 ErrorCode mb_tags_test()
02831 {
02832     Core moab;
02833     Interface* MB    = &moab;
02834     ErrorCode result = load_file_one( MB );
02835     if( MB_SUCCESS != result ) return result;
02836 
02837     Tag stale_bits, stale_dense, stale_sparse;
02838     result = MB->tag_get_handle( "stale data", 5, MB_TYPE_BIT, stale_bits, MB_TAG_CREAT );
02839     if( MB_SUCCESS != result ) return result;
02840 
02841     int def_data = 9;
02842     result       = MB->tag_get_handle( "dense stale_data", 1, MB_TYPE_INTEGER, stale_dense, MB_TAG_DENSE | MB_TAG_EXCL,
02843                                  &def_data );
02844     if( MB_SUCCESS != result ) return result;
02845     result = MB->tag_get_handle( "sparse stale data", 1, MB_TYPE_INTEGER, stale_sparse, MB_TAG_SPARSE | MB_TAG_EXCL );
02846     if( MB_SUCCESS != result ) return result;
02847 
02848     double coords[3] = { 0, 0, 0 };
02849     EntityHandle stale_handle1, stale_handle2;
02850     result = MB->create_vertex( coords, stale_handle1 );
02851     if( MB_SUCCESS != result ) return result;
02852 
02853     unsigned char bits = 0x5;
02854     result             = MB->tag_set_data( stale_bits, &stale_handle1, 1, &bits );
02855     if( MB_SUCCESS != result ) return result;
02856     bits   = 0;
02857     result = MB->tag_get_data( stale_bits, &stale_handle1, 1, &bits );
02858     if( MB_SUCCESS != result ) return result;
02859     if( bits != 0x5 ) return MB_FAILURE;
02860 
02861     def_data = 1;
02862     result   = MB->tag_set_data( stale_dense, &stale_handle1, 1, &def_data );
02863     if( MB_SUCCESS != result ) return result;
02864     def_data = 0;
02865     result   = MB->tag_get_data( stale_dense, &stale_handle1, 1, &def_data );
02866     if( MB_SUCCESS != result ) return result;
02867     if( def_data != 1 ) return MB_FAILURE;
02868 
02869     def_data = 100;
02870     result   = MB->tag_set_data( stale_sparse, &stale_handle1, 1, &def_data );
02871     if( MB_SUCCESS != result ) return result;
02872     def_data = 0;
02873     result   = MB->tag_get_data( stale_sparse, &stale_handle1, 1, &def_data );
02874     if( MB_SUCCESS != result ) return result;
02875     if( def_data != 100 ) return MB_FAILURE;
02876 
02877     result = MB->delete_entities( &stale_handle1, 1 );
02878     if( MB_SUCCESS != result ) return result;
02879     result = MB->create_vertex( coords, stale_handle2 );
02880     if( MB_SUCCESS != result ) return result;
02881 
02882     if( stale_handle1 != stale_handle2 )
02883         cout << "Tag test could test stale data" << endl;
02884     else
02885     {
02886         bits   = 0;
02887         result = MB->tag_get_data( stale_bits, &stale_handle2, 1, &bits );
02888         if( MB_SUCCESS != result ) return result;
02889         if( bits != 0 ) return MB_FAILURE;
02890 
02891         def_data = 3;
02892         result   = MB->tag_get_data( stale_dense, &stale_handle2, 1, &def_data );
02893         if( MB_SUCCESS != result ) return result;
02894         if( def_data != 9 ) return MB_FAILURE;
02895 
02896         def_data               = 3;
02897         ErrorCode stale_result = MB->tag_get_data( stale_sparse, &stale_handle2, 1, &def_data );
02898         // we are supposed to fail here
02899         if( stale_result != MB_TAG_NOT_FOUND ) return MB_FAILURE;
02900     }
02901 
02902     result = MB->tag_delete( stale_dense );
02903     if( MB_SUCCESS != result ) return result;
02904 
02905     result = MB->delete_entities( &stale_handle2, 1 );
02906     if( MB_SUCCESS != result ) return result;
02907 
02908     // get all blocks with material tag and with tag_value of 1 (should only be 1)
02909     Range entities;
02910     int value           = 1;
02911     const void* dum_ptr = &value;
02912     Tag material_tag;
02913     result = MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, material_tag );
02914     if( MB_SUCCESS != result ) return result;
02915     if( MB->get_entities_by_type_and_tag( 0, MBENTITYSET, &material_tag, &dum_ptr, 1, entities ) != MB_SUCCESS )
02916         return MB_FAILURE;
02917 
02918     if( entities.size() != 1 ) return MB_FAILURE;
02919 
02920     // add a dense tag to hexes
02921     Tag junk_tag;
02922     if( MB->tag_get_handle( "junk_tag", 1, MB_TYPE_INTEGER, junk_tag, MB_TAG_DENSE | MB_TAG_EXCL ) != MB_SUCCESS )
02923         return MB_FAILURE;
02924 
02925     // Set the dense tag on 5 hexes to 3489
02926     Range test_range;
02927     result = MB->get_entities_by_type( 0, MBHEX, test_range );
02928     if( result != MB_SUCCESS ) return result;
02929 
02930     Range::iterator iter, end_iter;
02931     iter     = test_range.begin();
02932     end_iter = test_range.end();
02933 
02934     int data             = 3489;
02935     const void* ptr_data = &data;
02936 
02937     // mark approxiamtely the first 20% of the hex entities; also put a bit tag on them
02938     unsigned int times   = test_range.size() / 5;
02939     bits                 = 0x5;
02940     const void* ptr_bits = &bits;
02941 
02942     for( unsigned int i = 0; i < times; i++ )
02943     {
02944         if( MB->tag_set_data( junk_tag, &( *iter ), 1, &data ) != MB_SUCCESS ) return MB_FAILURE;
02945         if( MB->tag_set_data( stale_bits, &( *iter ), 1, &bits ) != MB_SUCCESS ) return MB_FAILURE;
02946         ++iter;
02947     }
02948 
02949     entities.clear();
02950     // fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
02951     if( MB->get_entities_by_type_and_tag( 0, MBHEX, &junk_tag, &ptr_data, 1, entities ) != MB_SUCCESS )
02952         return MB_FAILURE;
02953 
02954     if( entities.size() != times )  // should get as many hexes as you perviously marked
02955         return MB_FAILURE;
02956 
02957     // fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
02958     entities.clear();
02959     if( MB->get_entities_by_type_and_tag( 0, MBHEX, &stale_bits, &ptr_bits, 1, entities ) != MB_SUCCESS )
02960         return MB_FAILURE;
02961 
02962     if( entities.size() != times )  // should get as many hexes as you perviously marked
02963         return MB_FAILURE;
02964 
02965     // test fetch by tag value again, this time limiting the results
02966     // to the contents of an entity set
02967     EntityHandle meshset;
02968     result = MB->create_meshset( MESHSET_SET, meshset );
02969     if( MB_SUCCESS != result ) return result;
02970     result = MB->add_entities( meshset, test_range );
02971     if( MB_SUCCESS != result ) return result;
02972 
02973     // fetch the hex entities of type--MBHEX, tag-"junk_tag", and tag value -- 3489
02974     entities.clear();
02975     result = MB->get_entities_by_type_and_tag( meshset, MBHEX, &junk_tag, &ptr_data, 1, entities );
02976     if( MB_SUCCESS != result ) return result;
02977 
02978     if( entities.size() != times )  // should get as many hexes as you perviously marked
02979         return MB_FAILURE;
02980 
02981     // fetch the hex entities of type--MBHEX, tag-"stale_bits", and tag value -- 0x5
02982     entities.clear();
02983     result = MB->get_entities_by_type_and_tag( meshset, MBHEX, &stale_bits, &ptr_bits, 1, entities );
02984     if( MB_SUCCESS != result ) return result;
02985 
02986     if( entities.size() != times )  // should get as many hexes as you perviously marked
02987         return MB_FAILURE;
02988 
02989     // now try the query with an empty meshset, expecting to get back
02990     // an empty Range
02991 
02992     result = MB->create_meshset( MESHSET_SET, meshset );
02993     if( MB_SUCCESS != result ) return result;
02994 
02995     entities.clear();
02996     result = MB->get_entities_by_type_and_tag( meshset, MBHEX, &junk_tag, &ptr_data, 1, entities );
02997     if( MB_SUCCESS != result ) return result;
02998 
02999     if( !entities.empty() ) return MB_FAILURE;
03000 
03001     result = MB->tag_delete( stale_bits );
03002     if( MB_SUCCESS != result ) return result;
03003 
03004     return MB_SUCCESS;
03005 }
03006 #endif
03007 ErrorCode mb_common_tag_test( TagType storage )
03008 {
03009     Core moab;
03010     Interface* mb    = &moab;
03011     ErrorCode result = create_some_mesh( mb );
03012     if( MB_SUCCESS != result ) return result;
03013 
03014     char tagname[64];
03015     sprintf( tagname, "t%d", rand() );
03016 
03017     Tag tag;
03018     const EntityHandle def_val = ~(EntityHandle)0;
03019     ErrorCode rval             = mb->tag_get_handle( tagname, 1, MB_TYPE_HANDLE, tag, storage | MB_TAG_EXCL, &def_val );
03020     if( MB_SUCCESS != rval ) return rval;
03021 
03022     Range entities;
03023     mb->get_entities_by_handle( 0, entities );
03024     if( entities.empty() ) return MB_FAILURE;
03025 
03026     // set tag on every other entity to be the entities handle
03027     Range::const_iterator i;
03028     bool odd = true;
03029     for( i = entities.begin(); i != entities.end(); ++i, odd = !odd )
03030     {
03031         if( odd )
03032         {
03033             const EntityHandle h = *i;
03034             rval                 = mb->tag_set_data( tag, &h, 1, &h );
03035             if( MB_SUCCESS != rval ) return rval;
03036         }
03037     }
03038 
03039     // check values on every entity -- expect default for every other entity
03040     odd = true;
03041     for( i = entities.begin(); i != entities.end(); ++i, odd = !odd )
03042     {
03043         EntityHandle val = 0;
03044         rval             = mb->tag_get_data( tag, &*i, 1, &val );
03045         if( MB_SUCCESS != rval ) return rval;
03046 
03047         if( odd )
03048         {
03049             if( val != *i ) return MB_FAILURE;
03050         }
03051         else
03052         {
03053             if( val != def_val ) return MB_FAILURE;
03054         }
03055     }
03056 
03057     // set tag values on all entities
03058     std::vector< EntityHandle > values( entities.size() );
03059     std::copy( entities.begin(), entities.end(), values.begin() );
03060     rval = mb->tag_set_data( tag, entities, &values[0] );
03061     if( MB_SUCCESS != rval ) return rval;
03062 
03063     // check values on every entity -- expect default for every other entity
03064     for( i = entities.begin(); i != entities.end(); ++i )
03065     {
03066         EntityHandle val = 0;
03067         rval             = mb->tag_get_data( tag, &*i, 1, &val );
03068         if( MB_SUCCESS != rval ) return rval;
03069         if( val != *i ) return MB_FAILURE;
03070     }
03071 
03072     // find each entity by tag value
03073     for( i = entities.begin(); i != entities.end(); ++i )
03074     {
03075         const EntityHandle h         = *i;
03076         const EntityType type        = mb->type_from_handle( h );
03077         const void* const tag_vals[] = { &h };
03078         Range range;
03079         rval = mb->get_entities_by_type_and_tag( 0, type, &tag, tag_vals, 1, range );
03080         if( MB_SUCCESS != rval ) return rval;
03081         if( range.size() != 1 ) return MB_FAILURE;
03082         if( range.front() != h ) return MB_FAILURE;
03083     }
03084 
03085     return MB_SUCCESS;
03086 }
03087 
03088 ErrorCode mb_dense_tag_test()
03089 {
03090     return mb_common_tag_test( MB_TAG_DENSE );
03091 }
03092 
03093 ErrorCode mb_sparse_tag_test()
03094 {
03095     return mb_common_tag_test( MB_TAG_SPARSE );
03096 }
03097 
03098 // class to offset hex center nodes
03099 class OffsetHexCenterNodes : public Interface::HONodeAddedRemoved
03100 {
03101   public:
03102     OffsetHexCenterNodes( Interface* mb, double x, double y, double z ) : gMB( mb )
03103     {
03104         mCoords[0] = 0.0;
03105         mCoords[1] = 0.0;
03106         mCoords[2] = 0.0;
03107         mOffset[0] = x;
03108         mOffset[1] = y;
03109         mOffset[2] = z;
03110     }
03111 
03112     ~OffsetHexCenterNodes() {}
03113 
03114     void node_added( EntityHandle node, EntityHandle )
03115     {
03116         gMB->get_coords( &node, 1, mCoords );
03117         mCoords[0] += mOffset[0];
03118         mCoords[1] += mOffset[1];
03119         mCoords[2] += mOffset[2];
03120         gMB->set_coords( &node, 1, mCoords );
03121     }
03122 
03123     // do nothing
03124     void node_removed( EntityHandle /*node*/ ) {}
03125 
03126   private:
03127     Interface* gMB;
03128     double mCoords[3];
03129     double mOffset[3];
03130 };
03131 #ifdef MOAB_HAVE_NETCDF
03132 ErrorCode mb_entity_conversion_test()
03133 {
03134     ErrorCode error;
03135     Core moab;
03136     Interface* MB = &moab;
03137 
03138     // read in a file so you have some data in the database
03139     std::string file_name = TestDir + "/mbtest3.g";
03140     error                 = MB->load_mesh( file_name.c_str(), NULL, 0 );
03141     if( error != MB_SUCCESS ) return error;
03142 
03143     Range entities;
03144     EntityHandle meshset;
03145     MB->create_meshset( MESHSET_SET, meshset );
03146 
03147     MB->get_entities_by_type( 0, MBHEX, entities );
03148     MB->add_entities( meshset, entities );
03149 
03150     OffsetHexCenterNodes function_object( MB, 0.07, 0.15, 0 );
03151 
03152     MB->convert_entities( meshset, false, false, true, &function_object );
03153     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03154 
03155     file_name = "hex_mid_volume_nodes.g";
03156     error     = MB->write_mesh( file_name.c_str() );
03157     if( error != MB_SUCCESS ) return error;
03158 
03159     error = MB->delete_mesh();
03160     if( error != MB_SUCCESS ) return error;
03161 
03162     error = MB->load_mesh( file_name.c_str(), NULL, 0 );
03163     if( error != MB_SUCCESS ) return error;
03164 
03165     error = MB->delete_mesh();
03166     if( error != MB_SUCCESS ) return error;
03167 
03168     file_name = TestDir + "/mbtest3.g";
03169     error     = MB->load_mesh( file_name.c_str(), NULL, 0 );
03170     if( error != MB_SUCCESS ) return error;
03171 
03172     entities.clear();
03173     MB->get_entities_by_type( 0, MBHEX, entities );
03174 
03175     MB->create_meshset( MESHSET_SET, meshset );
03176     MB->add_entities( meshset, entities );
03177     MB->convert_entities( meshset, true, true, true );
03178     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03179 
03180     file_name = "hex_mid_edge_face_vol_nodes.g";
03181     error     = MB->write_mesh( file_name.c_str() );
03182     if( error != MB_SUCCESS ) return error;
03183 
03184     error = MB->delete_mesh();
03185     if( error != MB_SUCCESS ) return error;
03186 
03187     error = MB->load_mesh( file_name.c_str(), NULL, 0 );
03188     if( error != MB_SUCCESS ) return error;
03189 
03190     error = MB->delete_mesh();
03191     if( error != MB_SUCCESS ) return error;
03192 
03193     file_name = TestDir + "/mbtest3.g";
03194     error     = MB->load_mesh( file_name.c_str(), NULL, 0 );
03195     if( error != MB_SUCCESS ) return error;
03196 
03197     entities.clear();
03198     MB->get_entities_by_type( 0, MBVERTEX, entities );
03199     unsigned int original_num_nodes = entities.size();
03200     entities.clear();
03201     MB->get_entities_by_type( 0, MBHEX, entities );
03202 
03203     MB->create_meshset( MESHSET_SET, meshset );
03204     MB->add_entities( meshset, entities );
03205     MB->convert_entities( meshset, true, false, false );
03206     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03207 
03208     file_name = "hex_mid_edge_nodes.g";
03209     error     = MB->write_mesh( file_name.c_str() );
03210     if( error != MB_SUCCESS ) return error;
03211 
03212     // convert them back to hex8's
03213     MB->convert_entities( meshset, false, false, false );
03214     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03215 
03216     entities.clear();
03217     MB->get_entities_by_type( 0, MBVERTEX, entities );
03218     // make sure the higher order nodes really were deleted
03219     if( entities.size() != original_num_nodes ) return MB_FAILURE;
03220 
03221     error = MB->delete_mesh();
03222     if( error != MB_SUCCESS ) return error;
03223 
03224     error = MB->load_mesh( file_name.c_str(), NULL, 0 );
03225     if( error != MB_SUCCESS ) return error;
03226 
03227     error = MB->delete_mesh();
03228     if( error != MB_SUCCESS ) return error;
03229 
03230     file_name = TestDir + "/mbtest1.g";
03231     error     = MB->load_mesh( file_name.c_str(), NULL, 0 );
03232     if( error != MB_SUCCESS ) return error;
03233 
03234     entities.clear();
03235     MB->get_entities_by_type( 0, MBTET, entities );
03236 
03237     MB->create_meshset( MESHSET_SET, meshset );
03238     MB->add_entities( meshset, entities );
03239     MB->convert_entities( meshset, true, false, false );
03240     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03241 
03242     file_name = "tet_mid_edge_nodes.g";
03243     error     = MB->write_mesh( file_name.c_str() );
03244     if( error != MB_SUCCESS ) return error;
03245 
03246     error = MB->delete_mesh();
03247     if( error != MB_SUCCESS ) return error;
03248 
03249     error = MB->load_mesh( file_name.c_str(), NULL, 0 );
03250     if( error != MB_SUCCESS ) return error;
03251 
03252     error = MB->delete_mesh();
03253     if( error != MB_SUCCESS ) return error;
03254 
03255     file_name = TestDir + "/mbtest1.g";
03256     error     = MB->load_mesh( file_name.c_str(), NULL, 0 );
03257     if( error != MB_SUCCESS ) return error;
03258 
03259     entities.clear();
03260     MB->get_entities_by_type( 0, MBTET, entities );
03261 
03262     MB->create_meshset( MESHSET_SET, meshset );
03263     MB->add_entities( meshset, entities );
03264     MB->convert_entities( meshset, false, true, false );
03265     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03266 
03267     file_name = "tet_mid_face_nodes.g";
03268     error     = MB->write_mesh( file_name.c_str() );
03269     if( error != MB_SUCCESS ) return error;
03270 
03271     error = MB->delete_mesh();
03272     if( error != MB_SUCCESS ) return error;
03273 
03274     error = MB->load_mesh( file_name.c_str(), NULL, 0 );
03275     if( error != MB_SUCCESS ) return error;
03276 
03277     error = MB->delete_mesh();
03278     if( error != MB_SUCCESS ) return error;
03279 
03280     file_name = TestDir + "/mbtest1.g";
03281     error     = MB->load_mesh( file_name.c_str(), NULL, 0 );
03282     if( error != MB_SUCCESS ) return error;
03283 
03284     entities.clear();
03285     MB->get_entities_by_type( 0, MBTET, entities );
03286 
03287     MB->create_meshset( MESHSET_SET, meshset );
03288     MB->add_entities( meshset, entities );
03289     MB->convert_entities( meshset, true, true, false );
03290     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03291 
03292     file_name = "tet_mid_edge_face_nodes.g";
03293     error     = MB->write_mesh( file_name.c_str() );
03294     if( error != MB_SUCCESS ) return error;
03295 
03296     error = MB->delete_mesh();
03297     if( error != MB_SUCCESS ) return error;
03298 
03299     error = MB->load_mesh( file_name.c_str(), NULL, 0 );
03300     if( error != MB_SUCCESS ) return error;
03301 
03302     error = MB->delete_mesh();
03303     if( error != MB_SUCCESS ) return error;
03304 
03305     file_name = TestDir + "/mbtest1.g";
03306     error     = MB->load_mesh( file_name.c_str(), NULL, 0 );
03307     if( error != MB_SUCCESS ) return error;
03308 
03309     // delete all MBTRI's
03310     entities.clear();
03311     error = MB->get_entities_by_type( 0, MBTRI, entities );
03312     if( MB_SUCCESS != error ) return error;
03313     error = MB->delete_entities( entities );
03314     if( MB_SUCCESS != error ) return error;
03315 
03316     entities.clear();
03317     error = MB->get_entities_by_type( 0, MBTET, entities );
03318     if( MB_SUCCESS != error ) return error;
03319 
03320     // skin the model
03321     for( Range::iterator tet_iter = entities.begin(); tet_iter != entities.end(); ++tet_iter )
03322     {
03323         std::vector< EntityHandle > adj;
03324         error = MB->get_adjacencies( &( *tet_iter ), 1, 2, true, adj );
03325         if( MB_SUCCESS != error ) return error;
03326         for( std::vector< EntityHandle >::iterator tri_iter = adj.begin(); tri_iter != adj.end(); ++tri_iter )
03327         {
03328             std::vector< EntityHandle > up_adj;
03329             MB->get_adjacencies( &( *tri_iter ), 1, 3, false, up_adj );
03330             if( up_adj.size() > 1 )
03331             {
03332                 error = MB->delete_entities( &( *tri_iter ), 1 );
03333                 if( MB_SUCCESS != error ) return error;
03334             }
03335         }
03336     }
03337 
03338     // create a meshset of the skin
03339     EntityHandle export_meshset;
03340     MB->create_meshset( MESHSET_SET, export_meshset );
03341     Tag material_tag;
03342     MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, material_tag );
03343     int block_id = 100;
03344     MB->tag_set_data( material_tag, &export_meshset, 1, &block_id );
03345     entities.clear();
03346     MB->get_entities_by_type( 0, MBTRI, entities );
03347     // remove the first few tri's for fun
03348     Range tmp_ents;
03349     tmp_ents.insert( *entities.begin() );
03350     entities.erase( entities.begin() );
03351     tmp_ents.insert( *entities.begin() );
03352     entities.erase( entities.begin() );
03353     tmp_ents.insert( *entities.begin() );
03354     entities.erase( entities.begin() );
03355     tmp_ents.insert( *entities.begin() );
03356     entities.erase( entities.begin() );
03357 
03358     MB->add_entities( export_meshset, entities );
03359 
03360     // convert the skin
03361     MB->convert_entities( export_meshset, true, true, false );
03362     if( MB_SUCCESS != check_valid_connectivity( MB ) ) return MB_FAILURE;
03363 
03364     // make sure our first few tri's were untouched
03365     std::vector< EntityHandle > conn( 3 );
03366     for( Range::iterator kter = tmp_ents.begin(); kter != tmp_ents.end(); ++kter )
03367     {
03368         MB->get_connectivity( &( *kter ), 1, conn );
03369         if( conn.size() != 3 ) return MB_FAILURE;
03370     }
03371 
03372     // output the skin
03373     file_name = "tri_mid_edge_face_nodes.g";
03374     error     = MB->write_mesh( file_name.c_str(), &export_meshset, 1 );
03375     if( error != MB_SUCCESS ) return error;
03376 
03377     MB->delete_entities( &export_meshset, 1 );
03378 
03379     error = MB->delete_mesh();
03380     if( error != MB_SUCCESS ) return error;
03381 
03382     // read the skin back in
03383     error = MB->load_mesh( file_name.c_str(), NULL, 0 );
03384     if( error != MB_SUCCESS ) return error;
03385 
03386     entities.clear();
03387     MB->get_entities_by_type( 0, MBVERTEX, entities );
03388     // must have 101 nodes
03389     if( entities.size() != 101 ) return MB_FAILURE;
03390 
03391     error = MB->delete_mesh();
03392     if( error != MB_SUCCESS ) return error;
03393 
03394     return MB_SUCCESS;
03395 }
03396 #endif
03397 //! Build two Quads with two edges shared between them.  The
03398 //! edges share the same nodes.  We should be able to get
03399 //! adjacencies on the edges and get one (correct) quad.  We
03400 //! should be able to get the edge adjacencies of the quads
03401 //! and only get 4 (not 5) edges.
03402 //!
03403 
03404 ErrorCode mb_forced_adjacencies_test()
03405 {
03406     //! first clean up any existing mesh.
03407     ErrorCode error;
03408     Core moab;
03409     Interface* MB = &moab;
03410 
03411     //! create 6 nodes, 2 quads and 8 edges.  Edge 4 is adjacent
03412     //! to quad 1 and edge 5 is adjacent to quad 2.
03413     //!
03414     //!  4       5       6
03415     //!  o--e7---o--e8---o
03416     //!  |       |       |
03417     //!  e3 q1 e4 e5 q2  e6
03418     //!  |       |       |
03419     //!  o--e1---o--e2---o
03420     //!  1       2       3
03421     //!
03422     double node_coord1[3] = { 0., 0., 0. };
03423     double node_coord2[3] = { 1., 0., 0. };
03424     double node_coord3[3] = { 2., 0., 0. };
03425     double node_coord4[3] = { 0., 1., 0. };
03426     double node_coord5[3] = { 1., 1., 0. };
03427     double node_coord6[3] = { 2., 1., 0. };
03428 
03429     EntityHandle node1, node2, node3, node4, node5, node6;
03430     error = MB->create_vertex( node_coord1, node1 );
03431     if( error != MB_SUCCESS ) return error;
03432 
03433     error = MB->create_vertex( node_coord2, node2 );
03434     if( error != MB_SUCCESS ) return error;
03435 
03436     error = MB->create_vertex( node_coord3, node3 );
03437     if( error != MB_SUCCESS ) return error;
03438 
03439     error = MB->create_vertex( node_coord4, node4 );
03440     if( error != MB_SUCCESS ) return error;
03441 
03442     error = MB->create_vertex( node_coord5, node5 );
03443     if( error != MB_SUCCESS ) return error;
03444 
03445     error = MB->create_vertex( node_coord6, node6 );
03446     if( error != MB_SUCCESS ) return error;
03447 
03448     std::vector< EntityHandle > conn( 4 );
03449     //! create the first quad
03450     EntityHandle quad1;
03451     conn[0] = node1;
03452     conn[1] = node2;
03453     conn[2] = node5;
03454     conn[3] = node4;
03455     error   = MB->create_element( MBQUAD, &conn[0], 4, quad1 );
03456     if( error != MB_SUCCESS ) return error;
03457 
03458     //! create the second quad
03459     EntityHandle quad2;
03460     conn[0] = node2;
03461     conn[1] = node3;
03462     conn[2] = node6;
03463     conn[3] = node5;
03464     error   = MB->create_element( MBQUAD, &conn[0], 4, quad2 );
03465     if( error != MB_SUCCESS ) return error;
03466 
03467     //! create the edges
03468     EntityHandle edge1;
03469     conn.resize( 2 );
03470     conn[0] = node1;
03471     conn[1] = node2;
03472     error   = MB->create_element( MBEDGE, &conn[0], 2, edge1 );
03473     if( error != MB_SUCCESS ) return error;
03474 
03475     EntityHandle edge2;
03476     conn[0] = node2;
03477     conn[1] = node3;
03478     error   = MB->create_element( MBEDGE, &conn[0], 2, edge2 );
03479     if( error != MB_SUCCESS ) return error;
03480 
03481     EntityHandle edge3;
03482     conn[0] = node1;
03483     conn[1] = node4;
03484     error   = MB->create_element( MBEDGE, &conn[0], 2, edge3 );
03485     if( error != MB_SUCCESS ) return error;
03486 
03487     EntityHandle edge4;
03488     conn[0] = node2;
03489     conn[1] = node5;
03490     error   = MB->create_element( MBEDGE, &conn[0], 2, edge4 );
03491     if( error != MB_SUCCESS ) return error;
03492 
03493     EntityHandle edge5;
03494     conn[0] = node2;
03495     conn[1] = node5;
03496     error   = MB->create_element( MBEDGE, &conn[0], 2, edge5 );
03497     if( error != MB_SUCCESS ) return error;
03498 
03499     EntityHandle edge6;
03500     conn[0] = node3;
03501     conn[1] = node6;
03502     error   = MB->create_element( MBEDGE, &conn[0], 2, edge6 );
03503     if( error != MB_SUCCESS ) return error;
03504 
03505     EntityHandle edge7;
03506     conn[0] = node4;
03507     conn[1] = node5;
03508     error   = MB->create_element( MBEDGE, &conn[0], 2, edge7 );
03509     if( error != MB_SUCCESS ) return error;
03510 
03511     EntityHandle edge8;
03512     conn[0] = node5;
03513     conn[1] = node6;
03514     error   = MB->create_element( MBEDGE, &conn[0], 2, edge8 );
03515     if( error != MB_SUCCESS ) return error;
03516 
03517     //! Edge 4 and 5 share the same nodes, but should be different entities
03518     if( edge4 == edge5 ) return MB_FAILURE;
03519 
03520     //! Now that the geometry is created start adding the adjacency information
03521     std::vector< EntityHandle > edge_adjacencies1( 4 );
03522     edge_adjacencies1[0] = edge1;
03523     edge_adjacencies1[1] = edge4;
03524     edge_adjacencies1[2] = edge7;
03525     edge_adjacencies1[3] = edge3;
03526 
03527     //! does this (should this) say anything about order of the edges around the
03528     //! quad?  Also, does this also build the edge->quad adjacency, or is that
03529     //! does with a separate call?
03530     error = MB->add_adjacencies( quad1, &edge_adjacencies1[0], edge_adjacencies1.size(), true );
03531     if( error != MB_SUCCESS ) return error;
03532 
03533     std::vector< EntityHandle > edge_adjacencies2( 4 );
03534     edge_adjacencies2[0] = edge2;
03535     edge_adjacencies2[1] = edge6;
03536     edge_adjacencies2[2] = edge8;
03537     edge_adjacencies2[3] = edge5;
03538     error                = MB->add_adjacencies( quad2, &edge_adjacencies2[0], edge_adjacencies2.size(), true );
03539     if( error != MB_SUCCESS ) return error;
03540 
03541     //! now get the adjacencies of each quad.
03542     std::vector< EntityHandle > quad1_adjacencies;
03543     error = MB->get_adjacencies( &( quad1 ), 1, 1, false, quad1_adjacencies );
03544     if( error != MB_SUCCESS ) return error;
03545 
03546     std::sort( quad1_adjacencies.begin(), quad1_adjacencies.end() );
03547     std::sort( edge_adjacencies1.begin(), edge_adjacencies1.end() );
03548 
03549     if( quad1_adjacencies != edge_adjacencies1 ) return MB_FAILURE;
03550 
03551     std::vector< EntityHandle > quad2_adjacencies;
03552     error = MB->get_adjacencies( &( quad2 ), 1, 1, false, quad2_adjacencies );
03553     if( error != MB_SUCCESS ) return error;
03554 
03555     std::sort( quad2_adjacencies.begin(), quad2_adjacencies.end() );
03556     std::sort( edge_adjacencies2.begin(), edge_adjacencies2.end() );
03557 
03558     if( quad2_adjacencies != edge_adjacencies2 ) return MB_FAILURE;
03559 
03560     //! try getting the adjacency of edge1 (should be quad1)
03561     std::vector< EntityHandle > edge1_adjacencies;
03562     error = MB->get_adjacencies( &( edge1 ), 1, 2, false, edge1_adjacencies );
03563     if( error != MB_SUCCESS ) return error;
03564 
03565     //! there should be only 1 entity adjacent to edge1
03566     if( edge1_adjacencies.size() != 1 ) return MB_FAILURE;
03567 
03568     //! and that entity should be quad1
03569     if( edge1_adjacencies[0] != quad1 ) return MB_FAILURE;
03570 
03571     //! try getting the adjacency of edge6 (should be one)
03572     std::vector< EntityHandle > edge6_adjacencies;
03573     error = MB->get_adjacencies( &( edge6 ), 1, 2, false, edge6_adjacencies );
03574     if( error != MB_SUCCESS ) return error;
03575 
03576     //! there should be only 1 entity adjacent to edge6
03577     if( edge6_adjacencies.size() != 1 ) return MB_FAILURE;
03578 
03579     //! Now seal up the "gap" caused by edges 4 and 5.  Remove edge5
03580     //! from the adjacencies of quad2 and add edge 4 to quad2.
03581 
03582     std::vector< EntityHandle > edge5_adjacencies( 1, edge5 );
03583     error = MB->remove_adjacencies( quad2, &edge5_adjacencies[0], edge5_adjacencies.size() );
03584     if( error != MB_SUCCESS ) return error;
03585 
03586     std::vector< EntityHandle > edge4_adjacencies( 1, edge4 );
03587     error = MB->add_adjacencies( quad2, &edge4_adjacencies[0], edge4_adjacencies.size(), true );
03588     if( error != MB_SUCCESS ) return error;
03589 
03590     //! get the adjacencies of edge4 and it should return both quads.
03591     std::vector< EntityHandle > quad_adjacencies;
03592     error = MB->get_adjacencies( &( edge4 ), 1, 2, false, quad_adjacencies );
03593     if( error != MB_SUCCESS ) return error;
03594 
03595     //! there should be 2 entities adjacent to edge4
03596     if( quad_adjacencies.size() != 2 ) return MB_FAILURE;
03597 
03598     //! and they should be quad1 and quad2.  Note that we are not saying anything
03599     //! about order in the array.
03600     if( ( quad_adjacencies[0] != quad1 || quad_adjacencies[1] != quad2 ) &&
03601         ( quad_adjacencies[0] != quad2 || quad_adjacencies[1] != quad1 ) )
03602         return MB_FAILURE;
03603 
03604     //! clean up on exit
03605     error = MB->delete_mesh();
03606     if( error != MB_SUCCESS ) return error;
03607 
03608     return MB_SUCCESS;
03609 }
03610 
03611 /*bool lessnodesZ(const EntityHandle entity_handle1, const EntityHandle entity_handle2)
03612   {
03613   double coords1[3], coords2[3];
03614   gMB->get_coords(entity_handle1, coords1);
03615   gMB->get_coords(entity_handle2, coords2);
03616 
03617   return coords2[2] < coords1[2];
03618   }*/
03619 
03620 /*void sort_verts(Range vertices)
03621   {
03622   std::vector<EntityHandle> vert_vec(vertices.size());
03623   Range::const_iterator iter;
03624   for (iter = vertices.begin(); iter != vertices.end(); ++iter)
03625   vert_vec.push_back(*iter);
03626   vert_vec.sort(lessnodesZ);
03627   }*/
03628 bool points_are_coincident( const double* first, const double* second )
03629 {
03630     double diff[3];
03631     diff[2] = first[2] - second[2];
03632     //  if (diff[2] > 0.001) return false;
03633 
03634     diff[0] = first[0] - second[0];
03635     diff[1] = first[1] - second[1];
03636 
03637     double length = diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2];
03638     if( fabs( length ) < .001 ) return true;
03639 
03640     return false;
03641 }
03642 ErrorCode find_coincident_nodes( Interface* gMB, const Range& vertices,
03643                                  std::vector< std::pair< EntityHandle, EntityHandle > >& coin_nodes )
03644 {
03645     double first_coords[3], second_coords[3];
03646     Range::const_iterator iter, jter;
03647     std::pair< EntityHandle, EntityHandle > coincident_pair;
03648     ErrorCode result;
03649 
03650     for( iter = vertices.begin(); iter != vertices.end(); ++iter )
03651     {
03652         result = gMB->get_coords( &( *iter ), 1, first_coords );
03653         if( result != MB_SUCCESS ) return result;
03654 
03655         for( jter = iter; jter != vertices.end(); ++jter )
03656         {
03657             if( *iter != *jter )
03658             {
03659                 result = gMB->get_coords( &( *jter ), 1, second_coords );
03660                 if( result != MB_SUCCESS ) return result;
03661 
03662                 if( points_are_coincident( first_coords, second_coords ) )
03663                 {
03664                     coincident_pair.first  = *iter;
03665                     coincident_pair.second = *jter;
03666                     coin_nodes.push_back( coincident_pair );
03667                 }
03668             }
03669         }
03670     }
03671     return MB_SUCCESS;
03672 }
03673 
03674 ErrorCode find_coincident_elements( Interface* gMB, const Range& entities, int num_nodes,
03675                                     std::vector< std::pair< EntityHandle, EntityHandle > >& coin )
03676 {
03677     double coords1[8][3], coords2[8][3];
03678     Range::iterator iter, jter;
03679     std::vector< EntityHandle > conn( 8 );
03680     std::pair< EntityHandle, EntityHandle > coincident_pair;
03681     int i = 0, /* j = 0,*/ ii = 0;
03682 
03683     for( iter = entities.begin(); iter != entities.end(); ++iter )
03684     {
03685         // Get the coordinates for the element corners.
03686         if( gMB->get_connectivity( &( *iter ), 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
03687         for( ii = 0; ii < num_nodes; ii++ )
03688         {
03689             if( gMB->get_coords( &( conn[ii] ), 1, coords1[ii] ) != MB_SUCCESS ) return MB_FAILURE;
03690         }
03691 
03692         for( jter = iter; jter != entities.end(); ++jter )
03693         {
03694             if( *iter != *jter )
03695             {
03696                 // Elements should be the same sense to merge.
03697                 if( gMB->get_connectivity( &( *jter ), 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
03698 
03699                 for( int tq = 0; tq < num_nodes; tq++ )
03700                     if( gMB->get_coords( &( conn[tq] ), 1, coords2[tq] ) != MB_SUCCESS ) return MB_FAILURE;
03701                 //        if(gMB->get_coords(&(conn[0]), 1,  coords2[0]) != MB_SUCCESS)
03702                 //          return MB_FAILURE;
03703 
03704                 // Find if first node is coincident before testing the rest.
03705                 bool first = false;
03706                 for( i = 0; i < num_nodes; i++ )
03707                 {
03708                     if( points_are_coincident( coords1[i], coords2[0] ) )
03709                     {
03710                         /*      cout <<"first("<<i<<",0) - ";
03711                                         cout <<" coords1["<<i<<"] = ("
03712                                         <<coords1[i][0]<<","
03713                                         <<coords1[i][1]<<","
03714                                         <<coords1[i][2]<<") ";
03715                                         cout <<" coords2["<<0<<"] = ("
03716                                         <<coords2[0][0]<<","
03717                                         <<coords2[0][1]<<","
03718                                         <<coords2[0][2]<<")\n";*/
03719                         first = true;
03720                         break;
03721                     }
03722                 }
03723                 // TEST -- Find if second node is coincident before testing the rest.
03724                 bool second = false;
03725                 for( int t2 = 0; t2 < num_nodes; t2++ )
03726                 {
03727                     if( points_are_coincident( coords1[t2], coords2[1] ) )
03728                     {
03729                         /*      cout <<"second("<<t2<<",1) - ";
03730                                         cout <<" coords1["<<t2<<"] = ("
03731                                         <<coords1[t2][0]<<","
03732                                         <<coords1[t2][1]<<","
03733                                         <<coords1[t2][2]<<") ";
03734                                         cout <<" coords2["<<1<<"] = ("
03735                                         <<coords2[1][0]<<","
03736                                         <<coords2[1][1]<<","
03737                                         <<coords2[1][2]<<")\n";*/
03738                         second = true;
03739                         break;
03740                     }
03741                 }
03742                 // TEST -- Find if second node is coincident before testing the rest.
03743                 bool third = false;
03744                 for( int ti = 0; ti < num_nodes; ti++ )
03745                 {
03746                     if( points_are_coincident( coords1[ti], coords2[2] ) )
03747                     {
03748                         /*      cout <<"third("<<ti<<",2) - ";
03749                                         cout <<" coords1["<<ti<<"] = ("
03750                                         <<coords1[ti][0]<<","
03751                                         <<coords1[ti][1]<<","
03752                                         <<coords1[ti][2]<<") ";
03753                                         cout <<" coords2["<<1<<"] = ("
03754                                         <<coords2[2][0]<<","
03755                                         <<coords2[2][1]<<","
03756                                         <<coords2[2][2]<<")\n";*/
03757                         third = true;
03758                         break;
03759                     }
03760                 }
03761                 if( ( first ) && ( second ) && ( third ) )
03762                 {
03763                     cout << "i = " << i << "\n";
03764                     for( int tii = 0; tii < num_nodes; tii++ )
03765                     {
03766                         cout << " coords1[" << tii << "] = (" << coords1[tii][0] << "," << coords1[tii][1] << ","
03767                              << coords1[tii][2] << ") ";
03768                         cout << " coords2[" << tii << "] = (" << coords2[tii][0] << "," << coords2[tii][1] << ","
03769                              << coords2[tii][2] << ")\n";
03770                     }
03771                 }
03772 
03773                 if( i < num_nodes )
03774                 {
03775                     for( ii = 1; ii < num_nodes; ii++ )
03776                     {
03777                         if( gMB->get_coords( &( conn[ii] ), 1, coords2[ii] ) != MB_SUCCESS ) return MB_FAILURE;
03778                     }
03779                     /*
03780                             for(j=1; j<num_nodes; j++)
03781                             {
03782 
03783                             if(!points_are_coincident(coords1[j], coords2[(j+i)%num_nodes]))
03784                             break;
03785                             }
03786                             if(j == num_nodes)*/
03787                     if( ( first ) && ( second ) && ( third ) )
03788                     {
03789                         coincident_pair.first  = *iter;
03790                         coincident_pair.second = *jter;
03791                         coin.push_back( coincident_pair );
03792                     }
03793                 }
03794             }
03795         }
03796     }
03797 
03798     return MB_SUCCESS;
03799 }
03800 
03801 #ifdef MOAB_HAVE_NETCDF
03802 ErrorCode mb_merge_test()
03803 {
03804     Core moab;
03805     Interface* MB = &moab;
03806 
03807     time_t begin_time = clock();
03808     unsigned int i;
03809     ErrorCode result;
03810     Skinner Skinner_Obj( MB );
03811 
03812     std::string test_files[] = { std::string( "cell1.gen" ), std::string( "cell2.gen" ) };
03813     /*                    std::string("cell3.gen"),
03814                       std::string("cell4.gen"),
03815                   std::string("cell5.gen"),
03816                   std::string("cell6.gen"),
03817                   std::string("cell7.gen"),
03818                   std::string("cell8.gen"),
03819                   std::string("cell9.gen"),
03820                   std::string("cell10.gen"),
03821                   std::string("cell11.gen"),
03822                   std::string("cell12.gen"),
03823                   std::string("cell13.gen"),
03824                   std::string("cell14.gen"),
03825                   std::string("cell15.gen"),
03826                   std::string("cell16.gen"),
03827                   std::string("cell17.gen"),
03828                   std::string("cell18.gen"),
03829                   std::string("cell19.gen"),
03830                   std::string("cell20.gen"),
03831                   std::string("cell21.gen"),
03832                   std::string("cell22.gen"),
03833                   std::string("cell23.gen"),
03834                   std::string("cell24.gen")};*/
03835 
03836     /*std::vector<Range> entities(sizeof(test_files));
03837       std::vector<Range> forward_lower(sizeof(test_files));
03838       std::vector<Range> reverse_lower(sizeof(test_files));
03839       std::vector<Range> nodes(sizeof(test_files));*/
03840     Range entities;
03841     Range forward_lower;
03842     Range reverse_lower;
03843     Range faces;
03844     Range nodes;
03845 
03846     cout << "---Starting Merge Tests---" << endl << endl;
03847     for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
03848     {
03849 
03850         cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
03851         result = MB->load_mesh( test_files[i].c_str(), NULL, 0 );
03852         if( result == MB_SUCCESS ) cout << "Loaded " << test_files[i] << "\n";
03853         // get Hexes from model
03854     }
03855     result = MB->get_entities_by_type( 0, MBHEX, entities );
03856     if( MB_SUCCESS != result ) return result;
03857     Skinner_Obj.find_skin( 0, entities, false, forward_lower, &reverse_lower );
03858     // cout <<"num hexes = "<<entities.size()<<"\n";
03859     // cout <<"fl = "<<forward_lower.size()<<" rl = "<<reverse_lower.size()<<"\n";
03860 
03861     //  Range::const_iterator iter;
03862     int dim = 0;
03863     //  int num_ents = 1;
03864     result = MB->get_adjacencies( forward_lower, dim, true, nodes, Interface::UNION );
03865     // cout <<"nodes.size() = "<<nodes.size() <<"\n";
03866 
03867     //  result = MB->get_entities_by_type(0, MBQUAD, faces);
03868     //  cout <<"num faces = "<<faces.size() <<"\n";
03869 
03870     std::vector< std::pair< EntityHandle, EntityHandle > > coin_nodes;
03871     //  cout <<"Begining sort...\n";
03872     //  std::sort(nodes.begin(),nodes.end(),lessnodesZ);
03873     //  cout <<"Ending sort...\n";
03874     result = find_coincident_nodes( MB, nodes, coin_nodes );
03875     cout << "coin_nodes.size() = " << coin_nodes.size() << "\n";
03876     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator n_iter;
03877     for( n_iter = coin_nodes.begin(); n_iter != coin_nodes.end(); ++n_iter )
03878     {
03879         result = MB->merge_entities( ( *n_iter ).first, ( *n_iter ).second, false, true );
03880         if( MB_SUCCESS != result ) return result;
03881     }
03882     /*  std::vector<std::pair<EntityHandle, EntityHandle> > coin_faces;
03883         int nodes_per_elt = 4;
03884         result = find_coincident_elements(forward_lower, nodes_per_elt, coin_faces);
03885         if (result != MB_SUCCESS) cout <<"find_coincident_elements fail!\n";
03886         cout <<"coin_faces.size() = "<<coin_faces.size() <<"\n";
03887         std::vector< std::pair<EntityHandle, EntityHandle> >::iterator f_iter;
03888         for (f_iter=coin_faces.begin(); f_iter != coin_faces.end(); ++f_iter)
03889         MB->merge_entities((*f_iter).first, (*f_iter).second, true, true);*/
03890     /*
03891       std::vector<std::pair<EntityHandle, EntityHandle> > coin_fl;
03892       nodes_per_elt = 4;
03893       result = find_coincident_elements(entities, nodes_per_elt, coin_fl);
03894       cout <<"coin_fl.size() = "<<coin_fl.size() <<"\n";
03895     */
03896     int num_ents;
03897     if( ( MB_SUCCESS == MB->get_number_entities_by_dimension( 0, 3, num_ents ) && 0 != num_ents ) ||
03898         ( MB_SUCCESS == MB->get_number_entities_by_dimension( 0, 2, num_ents ) && 0 != num_ents ) )
03899         result = MB->write_mesh( "merge_test.g" );
03900     ;
03901 
03902     double clocks_per_sec = (double)CLOCKS_PER_SEC;
03903     double real_time      = difftime( time( NULL ), begin_time );
03904     cout << "TIME: " << ( real_time / clocks_per_sec ) << " seconds.\n";
03905     return result;
03906 }
03907 #endif
03908 
03909 ErrorCode mb_merge_update_test()
03910 {
03911     Core moab;
03912     Interface* mb = &moab;
03913     ErrorCode rval;
03914 
03915     // create two quads with a coincident edge pair
03916     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 };
03917     EntityHandle verts[8];
03918     for( int i = 0; i < 8; ++i )
03919         mb->create_vertex( coords + 3 * i, verts[i] );
03920     EntityHandle quad1, quad2, edge1, edge2;
03921     mb->create_element( MBQUAD, verts, 4, quad1 );
03922     mb->create_element( MBQUAD, verts + 4, 4, quad2 );
03923     mb->create_element( MBEDGE, verts + 1, 2, edge1 );
03924     mb->create_element( MBEDGE, verts + 4, 2, edge2 );
03925 
03926     // create two tracking sets containing the vertices
03927     // and edge of each quad
03928     EntityHandle set1, set2;
03929     mb->create_meshset( MESHSET_TRACK_OWNER | MESHSET_SET, set1 );
03930     mb->create_meshset( MESHSET_TRACK_OWNER | MESHSET_ORDERED, set2 );
03931     mb->add_entities( set1, verts, 4 );
03932     mb->add_entities( set2, verts + 4, 4 );
03933     mb->add_entities( set1, &edge1, 1 );
03934     mb->add_entities( set2, &edge2, 1 );
03935 
03936     // now merge the coincident edges
03937     rval = mb->merge_entities( verts[1], verts[5], false, true );
03938     if( MB_SUCCESS != rval )
03939     {
03940         std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
03941         return rval;
03942     }
03943     rval = mb->merge_entities( verts[2], verts[4], false, true );
03944     if( MB_SUCCESS != rval )
03945     {
03946         std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
03947         return rval;
03948     }
03949     rval = mb->merge_entities( edge1, edge2, false, true );
03950     if( MB_SUCCESS != rval )
03951     {
03952         std::cerr << "Merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
03953         return rval;
03954     }
03955 
03956     // check that there is only one edge and that it has the correct connectivity
03957     Range r;
03958     mb->get_entities_by_type( 0, MBEDGE, r );
03959     if( r.size() != 1 || r.front() != edge1 )
03960     {
03961         std::cerr << "Edge merge failed at " << __FILE__ << ":" << __LINE__ << std::endl;
03962         return MB_FAILURE;
03963     }
03964     std::vector< EntityHandle > exp( verts + 1, verts + 3 ), act;
03965     mb->get_connectivity( &edge1, 1, act );
03966     if( exp != act )
03967     {
03968         std::cerr << "Incorrect conn for edge at " << __FILE__ << ":" << __LINE__ << std::endl;
03969         return MB_FAILURE;
03970     }
03971 
03972     // check that quad connectivity is as expected
03973     exp = std::vector< EntityHandle >( verts, verts + 4 );
03974     act.clear();
03975     mb->get_connectivity( &quad1, 1, act );
03976     if( exp != act )
03977     {
03978         std::cerr << "Incorrect conn for quad at " << __FILE__ << ":" << __LINE__ << std::endl;
03979         return MB_FAILURE;
03980     }
03981     exp.resize( 4 );
03982     exp[0] = verts[2];
03983     exp[1] = verts[1];
03984     exp[2] = verts[6];
03985     exp[3] = verts[7];
03986     act.clear();
03987     mb->get_connectivity( &quad2, 1, act );
03988     if( exp != act )
03989     {
03990         std::cerr << "Incorrect conn for quad at " << __FILE__ << ":" << __LINE__ << std::endl;
03991         return MB_FAILURE;
03992     }
03993 
03994     // check that set contents are correctly updated
03995     exp = std::vector< EntityHandle >( verts, verts + 4 );
03996     exp.push_back( edge1 );
03997     act.clear();
03998     mb->get_entities_by_handle( set1, act );
03999     std::sort( exp.begin(), exp.end() );
04000     std::sort( act.begin(), act.end() );
04001     if( exp != act )
04002     {
04003         std::cerr << "Incorrect set contents at " << __FILE__ << ":" << __LINE__ << std::endl;
04004         std::cerr << "  Expected: ";
04005         std::copy( exp.begin(), exp.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
04006         std::cerr << std::endl << "  Actual  : ";
04007         std::copy( act.begin(), act.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
04008         std::cerr << std::endl;
04009         return MB_FAILURE;
04010     }
04011 
04012     exp.resize( 5 );
04013     exp[0] = verts[2];
04014     exp[1] = verts[1];
04015     exp[2] = verts[6];
04016     exp[3] = verts[7];
04017     exp[4] = edge1;
04018     act.clear();
04019     mb->get_entities_by_handle( set2, act );
04020     if( exp != act )
04021     {
04022         std::cerr << "Incorrect set contents at " << __FILE__ << ":" << __LINE__ << std::endl;
04023         std::cerr << "  Expected: ";
04024         std::copy( exp.begin(), exp.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
04025         std::cerr << std::endl << "  Actual  : ";
04026         std::copy( act.begin(), act.end(), std::ostream_iterator< EntityHandle >( std::cerr, " " ) );
04027         std::cerr << std::endl;
04028         return MB_FAILURE;
04029     }
04030 
04031     return MB_SUCCESS;
04032 }
04033 #ifdef MOAB_HAVE_NETCDF
04034 ErrorCode mb_stress_test()
04035 {
04036     ErrorCode error;
04037     Core moab;
04038     Interface* MB = &moab;
04039 
04040     cout << "    Beginning Stress Test . . ." << endl;
04041     cout << "\n        Reading elements" << endl;
04042     clock_t start       = clock();
04043     clock_t total_start = clock();
04044 
04045     // read in a file so you have some data in the database
04046     std::string file_name = "mb_big_test.g";
04047     error                 = MB->load_mesh( file_name.c_str(), NULL, 0 );
04048     if( error != MB_SUCCESS ) return error;
04049 
04050     clock_t stop = clock();
04051 
04052     int num_entities_local;
04053     error = MB->get_number_entities_by_type( 0, MBHEX, num_entities_local );
04054     if( error != MB_SUCCESS ) return error;
04055 
04056     if( num_entities_local != 256000 ) return error;
04057 
04058     float time  = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
04059     float speed = num_entities_local / time;
04060     cout << "        Read " << num_entities_local << " entities"
04061          << " in " << time << " seconds" << endl;
04062     cout << "        at " << speed << " elements per second." << endl;
04063 
04064     cout << "\n        Transforming and copying elements" << endl;
04065     start = clock();
04066 
04067     Range hexes;
04068     error = MB->get_entities_by_type( 0, MBHEX, hexes );
04069     if( error != MB_SUCCESS ) return error;
04070 
04071     std::vector< EntityHandle > conn;
04072     Range::iterator iter;
04073     for( iter = hexes.begin(); iter != hexes.end(); ++iter )
04074     {
04075         error = MB->get_connectivity( &( *iter ), 1, conn );
04076         if( error != MB_SUCCESS ) return error;
04077 
04078         double coords[3];
04079         int i = 0;
04080         std::vector< EntityHandle > vertex_handle( 8 );
04081         EntityHandle element_handle;
04082         std::vector< EntityHandle >::iterator jter;
04083 
04084         for( jter = conn.begin(); jter != conn.end(); ++jter )
04085         {
04086             error = MB->get_coords( &( *jter ), 1, coords );
04087             if( error != MB_SUCCESS ) return error;
04088             coords[2] += 20.0;
04089             error = MB->create_vertex( coords, vertex_handle[i++] );
04090             if( error != MB_SUCCESS ) return error;
04091         }
04092         error = MB->create_element( MBHEX, &vertex_handle[0], 8, element_handle );
04093         if( error != MB_SUCCESS ) return error;
04094     }
04095 
04096     stop = clock();
04097     time = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
04098 
04099     cout << "        Transformed and created " << num_entities_local << " entities"
04100          << " in " << time << " seconds" << endl;
04101 
04102     // Create mesh set
04103     cout << "\n        Creating meshset" << endl;
04104     start = clock();
04105     error = MB->get_entities_by_type( 0, MBHEX, hexes );
04106     if( error != MB_SUCCESS ) return error;
04107 
04108     if( hexes.size() != 512000 ) return MB_FAILURE;
04109 
04110     EntityHandle mesh_set;
04111     error = MB->create_meshset( MESHSET_SET, mesh_set );
04112     if( error != MB_SUCCESS ) return error;
04113 
04114     error = MB->add_entities( mesh_set, hexes );
04115     if( error != MB_SUCCESS ) return error;
04116 
04117     stop = clock();
04118     time = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
04119 
04120     cout << "        Created meshset with " << hexes.size() << " entities"
04121          << " in " << time << " seconds" << endl;
04122 
04123     cout << "\n        Writing 512K element file . . ." << endl;
04124     start = clock();
04125 
04126     // set the block tag
04127     Tag tag_handle;
04128     ErrorCode result = MB->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handle );
04129     if( result != MB_SUCCESS ) return result;
04130 
04131     int id = 1;
04132     result = MB->tag_set_data( tag_handle, &mesh_set, 1, &id );
04133     if( result != MB_SUCCESS ) return result;
04134 
04135     std::vector< EntityHandle > output_list;
04136     output_list.push_back( mesh_set );
04137 
04138     file_name = "mb_stress_out.g";
04139     error     = MB->write_mesh( file_name.c_str(), &output_list[0], output_list.size() );
04140     if( error != MB_SUCCESS ) return error;
04141 
04142     stop = clock();
04143     time = static_cast< float >( stop - start ) / CLOCKS_PER_SEC;
04144 
04145     cout << "        Wrote file with " << hexes.size() << " entities"
04146          << " in " << time << " seconds" << endl;
04147 
04148     clock_t total_stop = clock();
04149     time               = static_cast< float >( total_stop - total_start ) / CLOCKS_PER_SEC;
04150 
04151     cout << "        Total time: " << time << " seconds." << endl;
04152 
04153     MB->delete_mesh();
04154 
04155     return MB_SUCCESS;
04156 }
04157 #endif
04158 
04159 ErrorCode mb_canon_number_test()
04160 {
04161     Core moab;
04162     Interface* MB = &moab;
04163 
04164     // various tests for canonical ordering
04165 
04166     // CN::AdjacentSubEntities
04167     std::vector< int > vec1, vec2;
04168     ErrorCode result;
04169 
04170     EntityType this_type;
04171 
04172     for( this_type = MBEDGE; this_type != MBKNIFE; this_type++ )
04173     {
04174 
04175         for( int i = 0; i < CN::VerticesPerEntity( this_type ); i++ )
04176         {
04177             // test for edges and faces
04178             for( int dim = 1; dim <= CN::Dimension( this_type ); dim++ )
04179             {
04180                 // get the sides adjacent to this vertex
04181                 vec1.clear();
04182                 int temp_result = CN::AdjacentSubEntities( this_type, &i, 1, 0, dim, vec1 );
04183 
04184                 if( 0 != temp_result || vec1.size() > (unsigned int)CN::NumSubEntities( this_type, dim ) )
04185                 {
04186                     cout << "failed getting sides for type " << CN::EntityTypeName( this_type ) << " dimension" << dim
04187                          << endl;
04188                     return MB_FAILURE;
04189                 }
04190 
04191                 // now get the vertices shared by these sides
04192                 vec2.clear();
04193                 temp_result = CN::AdjacentSubEntities( this_type, &vec1[0], vec1.size(), dim, 0, vec2 );
04194 
04195                 // vertex side recovered should be i
04196                 if( 0 != temp_result ||
04197                     // if dimension is same as DIMENSION(this_type), will get back all the
04198                     // vertices in the entity
04199                     ( dim == CN::Dimension( this_type ) &&
04200                       vec2.size() != (unsigned int)CN::VerticesPerEntity( this_type ) ) ||
04201                     // otherwise, we should get back only one vertex, and it should be the one
04202                     // we started with
04203                     ( dim != CN::Dimension( this_type ) && ( vec2.size() != 1 || vec2[0] != i ) ) )
04204                 {
04205                     cout << "traversal from verts to sides to verts failed for " << endl
04206                          << "vertex " << i << " type " << CN::EntityTypeName( this_type ) << " dimension " << dim
04207                          << endl;
04208                     return MB_FAILURE;
04209                 }
04210             }
04211         }
04212     }
04213 
04214     // CN::side_number
04215 
04216     // create vertices to use later
04217     double xyz[3] = { 0.0, 0.0, 0.0 };
04218     EntityHandle vertex_handles[8];
04219     for( int i = 0; i < 8; i++ )
04220     {
04221         result = MB->create_vertex( xyz, vertex_handles[i] );
04222         assert( result == MB_SUCCESS );
04223     }
04224     int side, sense, offset;
04225 
04226     EntityHandle this_entity;
04227 
04228     for( this_type = MBEDGE; this_type != MBKNIFE; this_type++ )
04229     {
04230 
04231         // skip remainder of the loop for MBPOLYGONS and POLYHEDRA, which don't follow
04232         // the standard canonical ordering
04233         if( this_type == MBPOLYGON || this_type == MBPOLYHEDRON ) continue;
04234 
04235         // make an entity of this type
04236         result = MB->create_element( this_type, vertex_handles, CN::VerticesPerEntity( this_type ), this_entity );
04237         if( MB_SUCCESS != result || 0 == this_entity )
04238         {
04239             cout << "failed to create entity of type " << CN::EntityTypeName( this_type ) << endl;
04240             return MB_FAILURE;
04241         }
04242 
04243         // now get the connectivity vector *
04244         const EntityHandle* entity_vertices;
04245         int num_verts;
04246         result = MB->get_connectivity( this_entity, entity_vertices, num_verts );
04247         if( MB_SUCCESS != result || num_verts != CN::VerticesPerEntity( this_type ) )
04248         {
04249             cout << "failed to get connectivity for entity type " << CN::EntityTypeName( this_type ) << endl;
04250             return MB_FAILURE;
04251         }
04252 
04253         // for each dimension
04254         for( int dim = 1; dim <= CN::Dimension( this_type ); dim++ )
04255         {
04256             // for each side of this dimension
04257             const CN::ConnMap& cm = CN::mConnectivityMap[this_type][dim - 1];
04258             int tmp_conn[moab::MAX_SUB_ENTITY_VERTICES];
04259 
04260             for( int side_no = 0; side_no < CN::NumSubEntities( this_type, dim ); side_no++ )
04261             {
04262 
04263                 for( int j = 0; j < moab::MAX_SUB_ENTITY_VERTICES; j++ )
04264                     tmp_conn[j] = cm.conn[side_no][j];
04265                 int temp_result = CN::SideNumber( this_type, tmp_conn,
04266                                                   CN::VerticesPerEntity( CN::SubEntityType( this_type, dim, side_no ) ),
04267                                                   dim, side, sense, offset );
04268                 if( 0 != temp_result )
04269                 {
04270                     cout << "call to CN::side_number failed with non-success result"
04271                          << " for type " << CN::EntityTypeName( this_type ) << " dimension " << dim << " side no "
04272                          << side_no << endl;
04273                     return MB_FAILURE;
04274                 }
04275 
04276                 // side number should be the same as side_no, sense should be forward, offset should
04277                 // be zero
04278                 if( side != side_no || sense != 1 || offset != 0 )
04279                 {
04280                     cout << "call to CN::side_number failed for type " << CN::EntityTypeName( this_type )
04281                          << " dimension " << dim << " side no " << side_no << endl
04282                          << "side, sense, offset = " << side << " " << sense << " " << offset << endl;
04283                     return MB_FAILURE;
04284                 }
04285             }
04286         }
04287 
04288         // destroy the entity of this_type
04289         result = MB->delete_entities( &this_entity, 1 );
04290         if( MB_SUCCESS != result ) return result;
04291     }
04292 
04293     return MB_SUCCESS;
04294 }
04295 ErrorCode mb_side_number_test()
04296 {
04297     ErrorCode rval;
04298     Core moab;
04299     Interface* mb = &moab;
04300 
04301     /* Create faces of a wedge: */
04302     /*
04303             4
04304            /|\
04305           / | \
04306          /  |  \
04307         /   2   \
04308        3.../.\...5
04309        |  /   \  |
04310        | /     \ |
04311        |/       \|      6 // off vertex
04312        0_________1
04313      */
04314 
04315     const double coords[][3] = {
04316         { 0, 0, 0 }, { 2, 0, 0 }, { 1, 0, 1 }, { 0, 2, 0 }, { 2, 2, 0 }, { 1, 2, 1 }, { 3, 1, 0 },
04317     };
04318     EntityHandle verts[7];
04319     for( unsigned i = 0; i < 7; ++i )
04320         mb->create_vertex( coords[i], verts[i] );
04321 
04322     EntityHandle faces[6];
04323     EntityHandle tri[]   = { verts[0], verts[1], verts[2] };
04324     EntityHandle tri2[]  = { verts[3], verts[4], verts[5] };
04325     EntityHandle quad1[] = { verts[0], verts[1], verts[5], verts[3] };
04326     EntityHandle quad2[] = { verts[1], verts[5], verts[4], verts[2] };
04327     EntityHandle quad3[] = { verts[2], verts[4], verts[3], verts[0] };
04328     rval                 = mb->create_element( MBTRI, tri, 3, faces[0] );MB_CHK_ERR( rval );
04329     rval = mb->create_element( MBQUAD, quad1, 4, faces[1] );MB_CHK_ERR( rval );
04330     rval = mb->create_element( MBQUAD, quad2, 4, faces[2] );MB_CHK_ERR( rval );
04331     rval = mb->create_element( MBQUAD, quad3, 4, faces[3] );MB_CHK_ERR( rval );
04332     rval = mb->create_element( MBTRI, tri2, 3, faces[4] );MB_CHK_ERR( rval );
04333 
04334     EntityHandle prism;
04335     rval = mb->create_element( MBPRISM, verts, 6, prism );MB_CHK_ERR( rval );
04336 
04337     /*
04338      * side_number(const EntityHandle parent,
04339                                     const EntityHandle child,
04340                                     int &side_number,
04341                                     int &sense,
04342                                     int &offset)
04343      */
04344     int side_n, sen, ofs;
04345     rval = mb->side_number( prism, faces[0], side_n, sen, ofs );MB_CHK_ERR( rval );
04346     CHECK_EQUAL( side_n, 3 );
04347     CHECK_EQUAL( sen, -1 );
04348     CHECK_EQUAL( ofs, 0 );
04349 
04350     // this diagonal should not be on the prism (not an edge of the prism)
04351     EntityHandle diagonal1;
04352     EntityHandle diag[] = { verts[2], verts[3] };
04353     rval                = mb->create_element( MBEDGE, diag, 2, diagonal1 );MB_CHK_ERR( rval );
04354     rval = mb->side_number( prism, diagonal1, side_n, sen, ofs );
04355     // expected fail
04356     if( rval != MB_FAILURE ) return MB_FAILURE;
04357 
04358     // create another triangle, connected to the  prism, but not on the side
04359     EntityHandle tri3[] = { verts[3], verts[4], verts[6] };
04360     rval                = mb->create_element( MBTRI, tri3, 3, faces[5] );MB_CHK_ERR( rval );
04361     rval = mb->side_number( prism, faces[5], side_n, sen, ofs );
04362     // expected fail
04363     if( rval != MB_FAILURE ) return MB_FAILURE;
04364 
04365     return MB_SUCCESS;
04366 }
04367 
04368 ErrorCode mb_poly_test()
04369 {
04370     Core moab;
04371     Interface* mb = &moab;
04372 
04373     // test polygon and polyhedron representation
04374     // create a couple of polygons; vertices first
04375     const double vert_pos[48] = {
04376         -1, 0, 0, 1,  0,  0, 2,  0,  0, 2,  1,  0, 1, 1,  0, 0, 2,  0, -1, 1,  0, -2,  1,  0,
04377         -2, 0, 0, -2, -1, 0, -1, -1, 0, -1, -2, 0, 1, -2, 0, 1, -1, 0, 2,  -1, 0, 1.5, .5, 1
04378     };
04379 
04380     EntityHandle verts[16];
04381     ErrorCode result;
04382     int i;
04383     for( i = 0; i < 16; i++ )
04384     {
04385         result = mb->create_vertex( &vert_pos[3 * i], verts[i] );
04386         if( MB_SUCCESS != result )
04387         {
04388             std::cout << "Failed to create vertex " << i << " in mb_poly_test." << std::endl;
04389             return result;
04390         }
04391     }
04392 
04393     // then polygons
04394     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,
04395                                 13, 12, 11, 10, 9, 0, 9, 10, 11, 12, 13, 14, 3, 4, 6, 8, 2, 3, 15, 5, 3, 4, 5, 15 };
04396 
04397     int num_connect_idx[] = { 5, 4, 3, 3, 4, 10, 11, 4, 4 };
04398 
04399     EntityHandle polygons[9], temp_connect[12];
04400     int idx = 0, nump = 0;
04401     ErrorCode tmp_result;
04402     while( nump < 9 )
04403     {
04404         for( i = 0; i < num_connect_idx[nump]; i++ )
04405             temp_connect[i] = verts[connect_idx[idx + i]];
04406 
04407         tmp_result = mb->create_element( MBPOLYGON, temp_connect, num_connect_idx[nump], polygons[nump] );
04408         if( MB_SUCCESS != tmp_result )
04409         {
04410             std::cout << "mb_poly_test: create_element failed for polygon " << i << "." << std::endl;
04411             result = tmp_result;
04412             nump++;
04413             continue;
04414         }
04415 
04416         idx += num_connect_idx[nump];
04417         nump++;
04418     }
04419 
04420     if( MB_SUCCESS != result ) return result;
04421 
04422     // ok, made 'em; now get all the vertices and make sure they're the same
04423     const EntityHandle* connect;
04424     int num_connect;
04425     idx = 0;
04426     int j;
04427     for( i = 0; i < 9; i++ )
04428     {
04429         tmp_result = mb->get_connectivity( polygons[i], connect, num_connect );
04430         if( MB_SUCCESS != tmp_result || num_connect != num_connect_idx[i] )
04431         {
04432             std::cout << "mb_poly_test: get_connectivity test failed for polygon " << i << "." << std::endl;
04433             result = ( tmp_result != MB_SUCCESS ? tmp_result : MB_FAILURE );
04434             continue;
04435         }
04436 
04437         for( j = 0; j < num_connect; j++ )
04438         {
04439             if( connect[j] != verts[connect_idx[idx + j]] )
04440             {
04441                 std::cout << "mb_poly_test: get_connectivity test returned wrong vertices for polygon " << i << "."
04442                           << std::endl;
04443                 result = MB_FAILURE;
04444                 continue;
04445             }
04446         }
04447 
04448         idx += num_connect;
04449     }
04450 
04451     if( MB_SUCCESS != result ) return result;
04452 
04453     // check a different way, with ranges
04454     Range vert_range, poly_range;
04455     for( i = 0; i < 9; i++ )
04456         poly_range.insert( polygons[i] );
04457     result = mb->get_adjacencies( poly_range, 0, false, vert_range, Interface::UNION );
04458     if( MB_SUCCESS != result )
04459     {
04460         std::cout << "mb_poly_test: get_adjacencies failed for polygon " << i << "." << std::endl;
04461         return result;
04462     }
04463 
04464     else if( vert_range.size() != 16 )
04465     {
04466         std::cout << "mb_poly_test: get_adjacencies returned wrong # of vertices for polygon " << i << "." << std::endl;
04467         return MB_FAILURE;
04468     }
04469 
04470     // make a couple polyhedra
04471     EntityHandle polyhedra[2];
04472     result = mb->create_element( MBPOLYHEDRON, polygons, 7, polyhedra[0] );
04473     if( MB_SUCCESS != result )
04474     {
04475         std::cout << "mb_poly_test: create_element failed for polyhedron 1." << std::endl;
04476         return result;
04477     }
04478 
04479     temp_connect[0] = polygons[1];
04480     temp_connect[1] = polygons[7];
04481     temp_connect[2] = polygons[8];
04482     result          = mb->create_element( MBPOLYHEDRON, temp_connect, 3, polyhedra[1] );
04483     if( MB_SUCCESS != result )
04484     {
04485         std::cout << "mb_poly_test: create_element failed for polyhedron 2." << std::endl;
04486         return result;
04487     }
04488 
04489     // now look for vertices common to both
04490     std::vector< EntityHandle > temp_verts;
04491     result = mb->get_adjacencies( polyhedra, 2, 0, false, temp_verts );
04492     if( MB_SUCCESS != result )
04493     {
04494         std::cout << "mb_poly_test: get_adjacencies failed for polyhedra." << std::endl;
04495         return result;
04496     }
04497 
04498     if( 4 != temp_verts.size() )
04499     {
04500         std::cout << "mb_poly_test: get_adjacencies for polyhedra returned " << temp_verts.size()
04501                   << " vertices, should be 4." << std::endl;
04502         return MB_FAILURE;
04503     }
04504 
04505     // ok, we're probably fine
04506     return MB_SUCCESS;
04507 }
04508 
04509 ErrorCode mb_topo_util_test()
04510 {
04511     Core moab;
04512     Interface* gMB = &moab;
04513     MeshTopoUtil mtu( gMB );
04514 
04515     // construct a four-hex mesh for testing purposes
04516     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,
04517                                0.0, 2.0, 0.0, 1.0, 2.0, 0.0, 2.0, 2.0, 0.0,
04518                                //
04519                                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,
04520                                0.0, 2.0, 1.0, 1.0, 2.0, 1.0, 2.0, 2.0, 1.0 };
04521 
04522     EntityHandle grid_verts[18], grid_elems[4];
04523     ErrorCode result;
04524 #define RR \
04525     if( result != MB_SUCCESS ) return result
04526     int init_edges, init_faces;
04527     result = gMB->get_number_entities_by_dimension( 0, 1, init_edges );RR;
04528     result = gMB->get_number_entities_by_dimension( 0, 2, init_faces );RR;
04529 
04530     // make vertices
04531     for( int i = 0; i < 18; i++ )
04532     {
04533         result = gMB->create_vertex( &grid_vert_pos[3 * i], grid_verts[i] );RR;
04534     }
04535 
04536     // make hexes
04537     int numv = 3, numv_sq = 9;
04538 #define VINDEX( i, j, k ) ( ( i ) + ( (j)*numv ) + ( (k)*numv_sq ) )
04539     EntityHandle connect[8];
04540     for( int j = 0; j < 2; j++ )
04541     {
04542         for( int i = 0; i < 2; i++ )
04543         {
04544             int vijk   = VINDEX( i, j, 0 );
04545             connect[0] = grid_verts[vijk];
04546             connect[1] = grid_verts[vijk + 1];
04547             connect[2] = grid_verts[vijk + 1 + numv];
04548             connect[3] = grid_verts[vijk + numv];
04549             connect[4] = grid_verts[vijk + numv * numv];
04550             connect[5] = grid_verts[vijk + 1 + numv * numv];
04551             connect[6] = grid_verts[vijk + 1 + numv + numv * numv];
04552             connect[7] = grid_verts[vijk + numv + numv * numv];
04553             result     = gMB->create_element( MBHEX, connect, 8, grid_elems[2 * j + i] );RR;
04554         }
04555     }
04556 
04557     Range vert_range;
04558     std::copy( grid_verts, grid_verts + 18, range_inserter( vert_range ) );
04559 
04560     // generate aentities
04561     result = mtu.construct_aentities( vert_range );RR;
04562 
04563     int this_edges, this_faces;
04564     result = gMB->get_number_entities_by_dimension( 0, 1, this_edges );RR;
04565     result = gMB->get_number_entities_by_dimension( 0, 2, this_faces );RR;
04566 
04567     if( this_edges != init_edges + 33 || this_faces != init_faces + 20 )
04568     {
04569         std::cout << "Wrong number of edges or faces in mb_topo_util test." << std::endl;
04570         //    return MB_FAILURE;
04571     }
04572 
04573     // get average position
04574     double pos[3];
04575     for( int j = 0; j < 2; j++ )
04576     {
04577         for( int i = 0; i < 2; i++ )
04578         {
04579             result = mtu.get_average_position( grid_elems[2 * j + i], pos );RR;
04580             if( pos[0] != .5 + i || pos[1] != .5 + j || pos[2] != .5 )
04581             {
04582                 std::cout << "Wrong position at i = " << i << ", j = " << j << std::endl;
04583                 result = MB_FAILURE;
04584             }
04585         }
04586     }
04587     RR;
04588 
04589     // get star faces
04590     Range all_hexes, middle_edge;
04591     std::copy( grid_elems, grid_elems + 4, range_inserter( all_hexes ) );
04592     // get the shared edge
04593     result = gMB->get_adjacencies( all_hexes, 1, false, middle_edge );
04594     if( MB_SUCCESS != result || 1 != middle_edge.size() )
04595     {
04596         std::cout << "Bad result getting single shared edge." << std::endl;
04597         return MB_FAILURE;
04598     }
04599 
04600     std::vector< EntityHandle > star_faces, star_hexes;
04601     bool bdy_edge;
04602     result = mtu.star_entities( *middle_edge.begin(), star_faces, bdy_edge, 0, &star_hexes );
04603     if( MB_SUCCESS != result || bdy_edge || star_faces.size() != 4 || star_hexes.size() != 4 )
04604     {
04605         std::cout << "Bad result from star_faces for non-bdy edge." << std::endl;
04606         return MB_FAILURE;
04607     }
04608 
04609     // now try for a different edge, which has to be on the bdy
04610     Range other_edges;
04611     all_hexes.clear();
04612     all_hexes.insert( grid_elems[0] );
04613     result = gMB->get_adjacencies( all_hexes, 1, false, other_edges );RR;
04614     other_edges.erase( *middle_edge.begin() );
04615     if( 11 != other_edges.size() )
04616     {
04617         std::cout << "Wrong number of edges in hex." << std::endl;
04618         return MB_FAILURE;
04619     }
04620     star_faces.clear();
04621     star_hexes.clear();
04622     result = mtu.star_entities( *other_edges.begin(), star_faces, bdy_edge, 0, &star_hexes );
04623     if( MB_SUCCESS != result || !bdy_edge || ( star_faces.size() != 2 && star_faces.size() != 3 ) ||
04624         ( star_hexes.size() != 1 && star_hexes.size() != 2 ) )
04625     {
04626         std::cout << "Bad result from star_faces for bdy edge." << std::endl;
04627         return MB_FAILURE;
04628     }
04629 
04630     return MB_SUCCESS;
04631 }
04632 
04633 ErrorCode mb_split_test()
04634 {
04635     Core moab;
04636     Interface* gMB = &moab;
04637     MeshTopoUtil mtu( gMB );
04638 
04639     // construct a four-hex mesh for testing purposes
04640     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,
04641                                0.0, 2.0, 0.0, 1.0, 2.0, 0.0, 2.0, 2.0, 0.0,
04642                                //
04643                                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,
04644                                0.0, 2.0, 1.0, 1.0, 2.0, 1.0, 2.0, 2.0, 1.0,
04645                                //
04646                                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,
04647                                0.0, 2.0, 2.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0 };
04648 
04649     EntityHandle grid_verts[27], grid_elems[8];
04650     ErrorCode result;
04651 #define RR \
04652     if( result != MB_SUCCESS ) return result
04653     int init_edges, init_faces, init_regions;
04654     result = gMB->get_number_entities_by_dimension( 0, 1, init_edges );RR;
04655     result = gMB->get_number_entities_by_dimension( 0, 2, init_faces );RR;
04656     result = gMB->get_number_entities_by_dimension( 0, 3, init_regions );RR;
04657 
04658     // make vertices
04659     for( int i = 0; i < 27; i++ )
04660     {
04661         result = gMB->create_vertex( &grid_vert_pos[3 * i], grid_verts[i] );RR;
04662     }
04663 
04664     // make hexes
04665     int numv = 3, numv_sq = 9;
04666 #define VINDEX( i, j, k ) ( ( i ) + ( (j)*numv ) + ( (k)*numv_sq ) )
04667     EntityHandle connect[8];
04668     for( int k = 0; k < 2; k++ )
04669     {
04670         for( int j = 0; j < 2; j++ )
04671         {
04672             for( int i = 0; i < 2; i++ )
04673             {
04674                 int vijk   = VINDEX( i, j, k );
04675                 connect[0] = grid_verts[vijk];
04676                 connect[1] = grid_verts[vijk + 1];
04677                 connect[2] = grid_verts[vijk + 1 + numv];
04678                 connect[3] = grid_verts[vijk + numv];
04679                 connect[4] = grid_verts[vijk + numv * numv];
04680                 connect[5] = grid_verts[vijk + 1 + numv * numv];
04681                 connect[6] = grid_verts[vijk + 1 + numv + numv * numv];
04682                 connect[7] = grid_verts[vijk + numv + numv * numv];
04683                 result     = gMB->create_element( MBHEX, connect, 8, grid_elems[4 * k + 2 * j + i] );RR;
04684             }
04685         }
04686     }
04687 
04688     Range vert_range;
04689     std::copy( grid_verts, grid_verts + 27, range_inserter( vert_range ) );
04690 
04691     // generate aentities
04692     result = mtu.construct_aentities( vert_range );RR;
04693 
04694     int this_edges, this_faces;
04695     result = gMB->get_number_entities_by_dimension( 0, 1, this_edges );RR;
04696     result = gMB->get_number_entities_by_dimension( 0, 2, this_faces );RR;
04697 
04698     if( this_edges != init_edges + 54 || this_faces != init_faces + 36 )
04699     {
04700         std::cout << "Wrong number of edges or faces in mb_topo_util test." << std::endl;
04701         return MB_FAILURE;
04702     }
04703 
04704     // split the faces between the 2 layers
04705     // first get the faces
04706     Range split_faces, tmp_ents, tmp_faces;
04707     for( int i = 0; i < 4; i++ )
04708     {
04709         tmp_ents.clear();
04710         tmp_ents.insert( grid_elems[i] );
04711         tmp_ents.insert( grid_elems[i + 4] );
04712         tmp_faces.clear();
04713         result = gMB->get_adjacencies( tmp_ents, 2, false, tmp_faces );
04714         if( MB_SUCCESS != result || tmp_faces.size() != 1 )
04715         {
04716             std::cout << "mb_split_test failed to get shared quad." << std::endl;
04717             return MB_FAILURE;
04718         }
04719         split_faces.insert( *tmp_faces.begin() );
04720     }
04721 
04722     Range new_faces, new_regions;
04723 
04724     // NOTE: passing in non-NULL pointer for new_regions requests that region between the
04725     // split entities be filled with an element; in this case, since we're splitting faces,
04726     // the new entities are polyhedra
04727     result = mtu.split_entities_manifold( split_faces, new_faces, &new_regions );
04728     if( MB_SUCCESS != result || new_faces.size() != 4 || new_regions.size() != 4 )
04729     {
04730         std::cout << "mb_split_test failed to split quads." << std::endl;
04731         return MB_FAILURE;
04732     }
04733 
04734     int this_regions;
04735     result = gMB->get_number_entities_by_dimension( 0, 1, this_edges );RR;
04736     result = gMB->get_number_entities_by_dimension( 0, 2, this_faces );RR;
04737     result = gMB->get_number_entities_by_dimension( 0, 3, this_regions );RR;
04738 
04739     if( this_edges != init_edges + 54 || this_faces != init_faces + 40 || this_regions != init_regions + 12 )
04740     {
04741         std::cout << "Wrong number of edges or faces or regions after splitting in mb_topo_util test." << std::endl;
04742         return MB_FAILURE;
04743     }
04744 
04745     return MB_SUCCESS;
04746 }
04747 
04748 ErrorCode mb_range_seq_intersect_test()
04749 {
04750     ErrorCode rval;
04751     SequenceManager sequences;
04752     RangeSeqIntersectIter iter( &sequences );
04753     Range range;
04754 
04755     // create some entity sequences
04756     EntitySequence *ts1, *ts2, *ts3, *qs1;
04757     EntityHandle th1, th2, th3, qh1;
04758     const int nt1 = 100, nt2 = 10, nt3 = 1, nq1 = 20;
04759     rval = sequences.create_entity_sequence( MBTRI, nt1, 3, 5, th1, ts1, -1 );
04760     if( MB_SUCCESS != rval ) return rval;
04761     rval = sequences.create_entity_sequence( MBTRI, nt2, 6, 0, th2, ts2, -1 );
04762     if( MB_SUCCESS != rval ) return rval;
04763     rval = sequences.create_entity_sequence( MBTRI, nt3, 3, MB_END_ID, th3, ts3, -1 );
04764     if( MB_SUCCESS != rval ) return rval;
04765     rval = sequences.create_entity_sequence( MBQUAD, nq1, 4, 0, qh1, qs1, -1 );
04766     if( MB_SUCCESS != rval ) return rval;
04767 
04768     // we're going to assume this below, so verify it now
04769     if( th1 > th2 || th2 > th3 || th3 > qh1 ) return MB_FAILURE;
04770 
04771     // construct an Range containing all valid handles;
04772     range.clear();
04773     range.insert( ts1->start_handle(), ts1->end_handle() );
04774     range.insert( ts2->start_handle(), ts2->end_handle() );
04775     range.insert( ts3->start_handle(), ts3->end_handle() );
04776     range.insert( qs1->start_handle(), qs1->end_handle() );
04777 
04778     // iterate over all and check results
04779 
04780     rval = iter.init( range.begin(), range.end() );
04781     if( MB_SUCCESS != rval ) return rval;
04782     if( ts1 != iter.get_sequence() ) return MB_FAILURE;
04783     if( iter.get_start_handle() != ts1->start_handle() ) return MB_FAILURE;
04784     if( iter.get_end_handle() != ts1->end_handle() ) return MB_FAILURE;
04785 
04786     rval = iter.step();
04787     if( MB_SUCCESS != rval ) return rval;
04788     if( ts2 != iter.get_sequence() ) return MB_FAILURE;
04789     if( iter.get_start_handle() != ts2->start_handle() ) return MB_FAILURE;
04790     if( iter.get_end_handle() != ts2->end_handle() ) return MB_FAILURE;
04791 
04792     rval = iter.step();
04793     if( MB_SUCCESS != rval ) return rval;
04794     if( ts3 != iter.get_sequence() ) return MB_FAILURE;
04795     if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
04796     if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
04797 
04798     rval = iter.step();
04799     if( MB_SUCCESS != rval ) return rval;
04800     if( qs1 != iter.get_sequence() ) return MB_FAILURE;
04801     if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
04802     if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
04803 
04804     if( !iter.is_at_end() ) return MB_FAILURE;
04805     rval = iter.step();
04806     if( MB_FAILURE != rval ) return MB_FAILURE;
04807 
04808     // iterate over just the quads
04809 
04810     rval = iter.init( range.lower_bound( MBQUAD ), range.end() );
04811     if( MB_SUCCESS != rval ) return rval;
04812     if( qs1 != iter.get_sequence() ) return MB_FAILURE;
04813     if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
04814     if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
04815 
04816     if( !iter.is_at_end() ) return MB_FAILURE;
04817     rval = iter.step();
04818     if( MB_FAILURE != rval ) return MB_FAILURE;
04819 
04820     // iterate starting one past the beginning of the
04821     // triangles and stopping one before the end.  The last
04822     // sequence contains only one tri, so should stop and end
04823     // of second-to-last sequence
04824 
04825     rval = iter.init( ++( range.begin() ), --( range.lower_bound( MBQUAD ) ) );
04826     if( MB_SUCCESS != rval ) return rval;
04827     if( ts1 != iter.get_sequence() ) return MB_FAILURE;
04828     if( iter.get_start_handle() != ts1->start_handle() + 1 ) return MB_FAILURE;
04829     if( iter.get_end_handle() != ts1->end_handle() ) return MB_FAILURE;
04830 
04831     rval = iter.step();
04832     if( MB_SUCCESS != rval ) return rval;
04833     if( ts2 != iter.get_sequence() ) return MB_FAILURE;
04834     if( iter.get_start_handle() != ts2->start_handle() ) return MB_FAILURE;
04835     if( iter.get_end_handle() != ts2->end_handle() ) return MB_FAILURE;
04836 
04837     if( !iter.is_at_end() ) return MB_FAILURE;
04838     rval = iter.step();
04839     if( MB_FAILURE != rval ) return MB_FAILURE;
04840 
04841     // Iterate over the quad sequence, starting two past the
04842     // beginning and stopping one before the end
04843 
04844     rval = iter.init( ++( range.lower_bound( MBQUAD ) ), --( range.end() ) );
04845     if( MB_SUCCESS != rval ) return rval;
04846     if( qs1 != iter.get_sequence() ) return MB_FAILURE;
04847     if( iter.get_start_handle() != qs1->start_handle() + 1 ) return MB_FAILURE;
04848     if( iter.get_end_handle() != qs1->end_handle() - 1 ) return MB_FAILURE;
04849 
04850     if( !iter.is_at_end() ) return MB_FAILURE;
04851     rval = iter.step();
04852     if( MB_FAILURE != rval ) return MB_FAILURE;
04853 
04854     // Iterate over two subsets of the quad sequence
04855 
04856     Range quads          = range.subset_by_type( MBQUAD );
04857     EntityHandle removed = qs1->start_handle() + nq1 / 2;
04858     if( quads.erase( removed ) == quads.end() ) return MB_FAILURE;
04859 
04860     rval = iter.init( quads.begin(), quads.end() );
04861     if( MB_SUCCESS != rval ) return rval;
04862     if( qs1 != iter.get_sequence() ) return MB_FAILURE;
04863     if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
04864     if( iter.get_end_handle() != removed - 1 ) return MB_FAILURE;
04865 
04866     rval = iter.step();
04867     if( MB_SUCCESS != rval ) return rval;
04868     if( qs1 != iter.get_sequence() ) return MB_FAILURE;
04869     if( iter.get_start_handle() != removed + 1 ) return MB_FAILURE;
04870     if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
04871 
04872     if( !iter.is_at_end() ) return MB_FAILURE;
04873     rval = iter.step();
04874     if( MB_FAILURE != rval ) return MB_FAILURE;
04875 
04876     // Iterate over everything, including a bunch of
04877     // invalid handles
04878 
04879     Range big;
04880     int junk;
04881     EntityHandle last = CREATE_HANDLE( MBQUAD + 1, 0, junk );
04882     big.insert( ts1->start_handle() - 1, last );
04883 
04884     // first some invalid handles in the beginning of the range
04885     rval = iter.init( big.begin(), big.end() );
04886     if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
04887     if( NULL != iter.get_sequence() ) return MB_FAILURE;
04888     if( iter.get_start_handle() != *big.begin() ) return MB_FAILURE;
04889     if( iter.get_end_handle() != ts1->start_handle() - 1 ) return MB_FAILURE;
04890 
04891     // next the first triangle sequence
04892     rval = iter.step();
04893     if( MB_SUCCESS != rval ) return rval;
04894     if( ts1 != iter.get_sequence() ) return MB_FAILURE;
04895     if( iter.get_start_handle() != ts1->start_handle() ) return MB_FAILURE;
04896     if( iter.get_end_handle() != ts1->end_handle() ) return MB_FAILURE;
04897 
04898     // next the the invalid handles between the first two tri sequences
04899     if( ts1->end_handle() + 1 != ts2->start_handle() )
04900     {
04901         rval = iter.step();
04902         if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
04903         if( NULL != iter.get_sequence() ) return MB_FAILURE;
04904         if( iter.get_start_handle() != ts1->end_handle() + 1 ) return MB_FAILURE;
04905         if( iter.get_end_handle() != ts2->start_handle() - 1 ) return MB_FAILURE;
04906     }
04907 
04908     // next the second triangle sequence
04909     rval = iter.step();
04910     if( MB_SUCCESS != rval ) return rval;
04911     if( ts2 != iter.get_sequence() ) return MB_FAILURE;
04912     if( iter.get_start_handle() != ts2->start_handle() ) return MB_FAILURE;
04913     if( iter.get_end_handle() != ts2->end_handle() ) return MB_FAILURE;
04914 
04915     // next the the invalid handles between the 2nd and 3rd tri sequences
04916     if( ts2->end_handle() + 1 != ts3->start_handle() )
04917     {
04918         rval = iter.step();
04919         if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
04920         if( NULL != iter.get_sequence() ) return MB_FAILURE;
04921         if( iter.get_start_handle() != ts2->end_handle() + 1 ) return MB_FAILURE;
04922         if( iter.get_end_handle() != ts3->start_handle() - 1 ) return MB_FAILURE;
04923     }
04924 
04925     // next the third triangle sequence
04926     rval = iter.step();
04927     if( MB_SUCCESS != rval ) return rval;
04928     if( ts3 != iter.get_sequence() ) return MB_FAILURE;
04929     if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
04930     if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
04931 
04932     // third tri sequence contains the MAX tri handle, so no more
04933     // invalid triangles.
04934     // next 1 invalid quad at the before MB_START_ID
04935     if( ts3->end_handle() + 1 != qs1->start_handle() )
04936     {
04937         rval = iter.step();
04938         if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
04939         if( NULL != iter.get_sequence() ) return MB_FAILURE;
04940         if( iter.get_start_handle() != ts3->end_handle() + 1 ) return MB_FAILURE;
04941         if( iter.get_end_handle() != qs1->start_handle() - 1 ) return MB_FAILURE;
04942     }
04943 
04944     // next the quad sequence
04945     rval = iter.step();
04946     if( MB_SUCCESS != rval ) return rval;
04947     if( qs1 != iter.get_sequence() ) return MB_FAILURE;
04948     if( iter.get_start_handle() != qs1->start_handle() ) return MB_FAILURE;
04949     if( iter.get_end_handle() != qs1->end_handle() ) return MB_FAILURE;
04950 
04951     // next remaining invalid quad handles in the range
04952     rval = iter.step();
04953     if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
04954     if( 0 != iter.get_sequence() ) return MB_FAILURE;
04955     if( iter.get_start_handle() != qs1->end_handle() + 1 ) return MB_FAILURE;
04956     if( iter.get_end_handle() != last - 1 ) return MB_FAILURE;
04957 
04958     // next invalid entity after the last quad in the range
04959     rval = iter.step();
04960     if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
04961     if( 0 != iter.get_sequence() ) return MB_FAILURE;
04962     if( iter.get_start_handle() != last ) return MB_FAILURE;
04963     if( iter.get_end_handle() != last ) return MB_FAILURE;
04964 
04965     // now at the end
04966     if( !iter.is_at_end() ) return MB_FAILURE;
04967     rval = iter.step();
04968     if( MB_FAILURE != rval ) return MB_FAILURE;
04969 
04970     // Create some holes
04971     Error eh;
04972     EntityHandle ts1s  = ts1->start_handle();
04973     EntityHandle dead1 = ts1->start_handle() + 1;
04974     EntityHandle dead2 = ts1->start_handle() + 2;
04975     EntityHandle ts1e  = ts1->end_handle();
04976     EntityHandle dead3 = ts2->start_handle();
04977     EntityHandle dead4 = ts2->end_handle();
04978     EntityHandle qs1s  = qs1->start_handle();
04979     EntityHandle qs1e  = qs1->end_handle();
04980     EntityHandle dead5 = qs1->start_handle() + nq1 / 2;
04981     EntityHandle dead6 = dead5 + 1;
04982     rval               = sequences.delete_entity( &eh, dead1 );
04983     if( MB_SUCCESS != rval ) return rval;
04984     rval = sequences.delete_entity( &eh, dead2 );
04985     if( MB_SUCCESS != rval ) return rval;
04986     rval = sequences.delete_entity( &eh, dead3 );
04987     if( MB_SUCCESS != rval ) return rval;
04988     rval = sequences.delete_entity( &eh, dead4 );
04989     if( MB_SUCCESS != rval ) return rval;
04990     rval = sequences.delete_entity( &eh, dead5 );
04991     if( MB_SUCCESS != rval ) return rval;
04992     rval = sequences.delete_entity( &eh, dead6 );
04993     if( MB_SUCCESS != rval ) return rval;
04994 
04995     // Iterate over sequences w/out removing deleted entities
04996     // from range.
04997 
04998     // first sequence should have one valid handle at beginning
04999     rval = iter.init( range.begin(), range.end() );
05000     if( MB_SUCCESS != rval ) return rval;
05001     if( 0 == iter.get_sequence() || ts1s != iter.get_sequence()->start_handle() ||
05002         dead1 - 1 != iter.get_sequence()->end_handle() )
05003         return MB_FAILURE;
05004     if( iter.get_start_handle() != ts1->start_handle() ) return MB_FAILURE;
05005     if( iter.get_end_handle() != dead1 - 1 ) return MB_FAILURE;
05006 
05007     // next two invalid handles in sequence in first sequence
05008     rval = iter.step();
05009     if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
05010     if( 0 != iter.get_sequence() ) return MB_FAILURE;
05011     if( iter.get_start_handle() != dead1 ) return MB_FAILURE;
05012     if( iter.get_end_handle() != dead2 ) return MB_FAILURE;
05013 
05014     // next the remainder of the fist sequence
05015     rval = iter.step();
05016     if( MB_SUCCESS != rval ) return rval;
05017     if( 0 == iter.get_sequence() || dead2 + 1 != iter.get_sequence()->start_handle() ||
05018         ts1e != iter.get_sequence()->end_handle() )
05019         return MB_FAILURE;
05020     if( iter.get_start_handle() != dead2 + 1 ) return MB_FAILURE;
05021     if( iter.get_end_handle() != ts1e ) return MB_FAILURE;
05022 
05023     // next an invalid handle at the start of the second sequence
05024     rval = iter.step();
05025     if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
05026     if( 0 != iter.get_sequence() ) return MB_FAILURE;
05027     if( iter.get_start_handle() != dead3 ) return MB_FAILURE;
05028     if( iter.get_end_handle() != dead3 ) return MB_FAILURE;
05029 
05030     // next the second sequence up to the invalid handle at the end
05031     rval = iter.step();
05032     if( MB_SUCCESS != rval ) return rval;
05033     if( 0 == iter.get_sequence() || dead3 + 1 != iter.get_sequence()->start_handle() ||
05034         dead4 - 1 != iter.get_sequence()->end_handle() )
05035         return MB_FAILURE;
05036     if( ts2 != iter.get_sequence() ) return MB_FAILURE;
05037     if( iter.get_start_handle() != dead3 + 1 ) return MB_FAILURE;
05038     if( iter.get_end_handle() != dead4 - 1 ) return MB_FAILURE;
05039 
05040     // next invaild handle at the end of the second sequence
05041     rval = iter.step();
05042     if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
05043     if( 0 != iter.get_sequence() ) return MB_FAILURE;
05044     if( iter.get_start_handle() != dead4 ) return MB_FAILURE;
05045     if( iter.get_end_handle() != dead4 ) return MB_FAILURE;
05046 
05047     // next the third sequence
05048     rval = iter.step();
05049     if( MB_SUCCESS != rval ) return rval;
05050     if( ts3 != iter.get_sequence() ) return MB_FAILURE;
05051     if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
05052     if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
05053 
05054     // next the quad sequence up to the invalid handle in the middle
05055     rval = iter.step();
05056     if( MB_SUCCESS != rval ) return rval;
05057     if( 0 == iter.get_sequence() || qs1s != iter.get_sequence()->start_handle() ||
05058         dead5 - 1 != iter.get_sequence()->end_handle() )
05059         return MB_FAILURE;
05060     if( qs1 != iter.get_sequence() ) return MB_FAILURE;
05061     if( iter.get_start_handle() != qs1s ) return MB_FAILURE;
05062     if( iter.get_end_handle() != dead5 - 1 ) return MB_FAILURE;
05063 
05064     // next the two invalid handles in the middle
05065     rval = iter.step();
05066     if( MB_ENTITY_NOT_FOUND != rval ) return MB_FAILURE;
05067     if( 0 != iter.get_sequence() ) return MB_FAILURE;
05068     if( iter.get_start_handle() != dead5 ) return MB_FAILURE;
05069     if( iter.get_end_handle() != dead6 ) return MB_FAILURE;
05070 
05071     // next the remainder of the quad sequence
05072     rval = iter.step();
05073     if( MB_SUCCESS != rval ) return rval;
05074     if( 0 == iter.get_sequence() || dead6 + 1 != iter.get_sequence()->start_handle() ||
05075         qs1e != iter.get_sequence()->end_handle() )
05076         return MB_FAILURE;
05077     if( iter.get_start_handle() != dead6 + 1 ) return MB_FAILURE;
05078     if( iter.get_end_handle() != qs1e ) return MB_FAILURE;
05079 
05080     // now at the end
05081     if( !iter.is_at_end() ) return MB_FAILURE;
05082     rval = iter.step();
05083     if( MB_FAILURE != rval ) return MB_FAILURE;
05084 
05085     // now remove the dead entities from the range and iterate again
05086 
05087     if( range.erase( dead1 ) == quads.end() ) return MB_FAILURE;
05088     if( range.erase( dead2 ) == quads.end() ) return MB_FAILURE;
05089     if( range.erase( dead3 ) == quads.end() ) return MB_FAILURE;
05090     if( range.erase( dead4 ) == quads.end() ) return MB_FAILURE;
05091     if( range.erase( dead5 ) == quads.end() ) return MB_FAILURE;
05092     if( range.erase( dead6 ) == quads.end() ) return MB_FAILURE;
05093 
05094     // first sequence should have one valid handle at beginning
05095     rval = iter.init( range.begin(), range.end() );
05096     if( MB_SUCCESS != rval ) return rval;
05097     if( 0 == iter.get_sequence() || ts1s != iter.get_sequence()->start_handle() ||
05098         dead1 - 1 != iter.get_sequence()->end_handle() )
05099         return MB_FAILURE;
05100     if( iter.get_start_handle() != ts1s ) return MB_FAILURE;
05101     if( iter.get_end_handle() != dead1 - 1 ) return MB_FAILURE;
05102 
05103     // next the remainder of the fist sequence after the hole
05104     rval = iter.step();
05105     if( MB_SUCCESS != rval ) return rval;
05106     if( 0 == iter.get_sequence() || dead2 + 1 != iter.get_sequence()->start_handle() ||
05107         ts1e != iter.get_sequence()->end_handle() )
05108         return MB_FAILURE;
05109     if( iter.get_start_handle() != dead2 + 1 ) return MB_FAILURE;
05110     if( iter.get_end_handle() != ts1e ) return MB_FAILURE;
05111 
05112     // next the second sequence between deleted start and end handles
05113     rval = iter.step();
05114     if( MB_SUCCESS != rval ) return rval;
05115     if( 0 == iter.get_sequence() || dead3 + 1 != iter.get_sequence()->start_handle() ||
05116         dead4 - 1 != iter.get_sequence()->end_handle() )
05117         return MB_FAILURE;
05118     if( iter.get_start_handle() != dead3 + 1 ) return MB_FAILURE;
05119     if( iter.get_end_handle() != dead4 - 1 ) return MB_FAILURE;
05120 
05121     // next the third sequence
05122     rval = iter.step();
05123     if( MB_SUCCESS != rval ) return rval;
05124     if( ts3 != iter.get_sequence() ) return MB_FAILURE;
05125     if( iter.get_start_handle() != ts3->start_handle() ) return MB_FAILURE;
05126     if( iter.get_end_handle() != ts3->end_handle() ) return MB_FAILURE;
05127 
05128     // next the quad sequence up to the hole in the middle
05129     rval = iter.step();
05130     if( MB_SUCCESS != rval ) return rval;
05131     if( 0 == iter.get_sequence() || qs1s != iter.get_sequence()->start_handle() ||
05132         dead5 - 1 != iter.get_sequence()->end_handle() )
05133         return MB_FAILURE;
05134     if( iter.get_start_handle() != qs1s ) return MB_FAILURE;
05135     if( iter.get_end_handle() != dead5 - 1 ) return MB_FAILURE;
05136 
05137     // next the remainder of the quad sequence after the hole
05138     rval = iter.step();
05139     if( MB_SUCCESS != rval ) return rval;
05140     if( 0 == iter.get_sequence() || dead6 + 1 != iter.get_sequence()->start_handle() ||
05141         qs1e != iter.get_sequence()->end_handle() )
05142         return MB_FAILURE;
05143     if( iter.get_start_handle() != dead6 + 1 ) return MB_FAILURE;
05144     if( iter.get_end_handle() != qs1e ) return MB_FAILURE;
05145 
05146     // now at the end
05147     if( !iter.is_at_end() ) return MB_FAILURE;
05148     rval = iter.step();
05149     if( MB_FAILURE != rval ) return MB_FAILURE;
05150 
05151     return MB_SUCCESS;
05152 }
05153 
05154 #define ASSERT_EQUAL( A, B )                                                      \
05155     do                                                                            \
05156     {                                                                             \
05157         if( !_assert_equal( ( A ), ( B ), #A, #B, __LINE__ ) ) return MB_FAILURE; \
05158     } while( false )
05159 
05160 #define ASSERT_NOT_EQUAL( A, B )                                                      \
05161     do                                                                                \
05162     {                                                                                 \
05163         if( !_assert_not_equal( ( A ), ( B ), #A, #B, __LINE__ ) ) return MB_FAILURE; \
05164     } while( false )
05165 
05166 template < typename T1, typename T2 >
05167 bool _assert_equal( T1 a, T2 b, const char* as, const char* bs, int line )
05168 {
05169     if( a == b ) return true;
05170 
05171     std::cout << "Assertion failed at line " << line << std::endl
05172               << "\t" << as << " == " << bs << std::endl
05173               << "\t" << as << " = " << a << std::endl
05174               << "\t" << bs << " = " << b << std::endl;
05175     return false;
05176 }
05177 
05178 template < typename T1, typename T2 >
05179 bool _assert_not_equal( T1 a, T2 b, const char* as, const char* bs, int line )
05180 {
05181     if( a != b ) return true;
05182 
05183     std::cout << "Assertion failed at line " << line << std::endl
05184               << "\t" << as << " != " << bs << std::endl
05185               << "\t" << as << " = " << a << std::endl
05186               << "\t" << bs << " = " << b << std::endl;
05187     return false;
05188 }
05189 
05190 std::ostream& operator<<( std::ostream& s, Range::const_iterator i )
05191 {
05192     return s << *i;
05193 }
05194 
05195 ErrorCode mb_poly_adjacency_test()
05196 {
05197     ErrorCode rval;
05198     Core moab;
05199     Interface* mbImpl = &moab;
05200 
05201     // make a couple polygons and a polyhedron
05202     double coords[3] = { 0, 1, 2 };
05203     EntityHandle verts[10], polygons[2], polyhedron;
05204 
05205     for( int i = 0; i < 10; i++ )
05206     {
05207         rval = mbImpl->create_vertex( coords, verts[i] );
05208         if( MB_SUCCESS != rval ) return rval;
05209     }
05210 
05211     for( int i = 0; i < 2; i++ )
05212     {
05213         rval = mbImpl->create_element( MBPOLYGON, verts, 5, polygons[i] );
05214         if( MB_SUCCESS != rval ) return rval;
05215     }
05216     rval = mbImpl->create_element( MBPOLYHEDRON, polygons, 2, polyhedron );
05217     if( MB_SUCCESS != rval ) return rval;
05218 
05219     // create the aentities
05220     Range dum_range;
05221     for( int dim = 0; dim < 3; dim++ )
05222     {
05223         dum_range.clear();
05224         rval = mbImpl->get_adjacencies( &polyhedron, 1, dim, true, dum_range );
05225         if( MB_SUCCESS != rval ) return rval;
05226     }
05227 
05228     // delete the polyhedron
05229     rval = mbImpl->delete_entities( &polyhedron, 1 );
05230     if( MB_SUCCESS != rval ) return rval;
05231 
05232     // check adjacencies
05233     return moab.check_adjacencies();
05234 }
05235 
05236 ErrorCode mb_poly_adjacency_test2()
05237 {
05238     ErrorCode rval;
05239     Core moab;
05240     Interface* mbImpl = &moab;
05241 
05242     // make a polyhedra in shape of a cube with a corner cut
05243 
05244     /*
05245      *
05246      *             7   -------------   8
05247      *          .  |               .   |
05248      *       .                  .      |  initial cube had 8 vertices; box [000 - 222]
05249      *    5   -------------   6        |   cut a triangle 123 on lower corner
05250      *    |        |          |        |
05251      *    |                   |        |   faces of the polyhedra (pointing outward)
05252      *    |        |          |        |   (123) (24653) (4 10 8 6)
05253      *    3                   |        |   (9 10 4 2 1) (7 8 10 9)  (5687)
05254      *     \       |          |        |   (1 3 5 7 9)
05255      *             9   -  -  -|  -    10
05256      *       \  .             |     .
05257      *        1,              |  .
05258      *  (000)      '2 ----    4
05259      *
05260      */
05261     double coords[] = {
05262         0, 1, 0,                    // vertex 1
05263         1, 0, 0,                    // vertex 2
05264         0, 0, 1,                    // vertex 3
05265         2, 0, 0, 0, 0, 2, 2, 0, 2,  // vertex 6
05266         0, 2, 2, 2, 2, 2,           // vertex 8
05267         0, 2, 0,                    // vertex 9
05268         2, 2, 0                     // vertex 9
05269 
05270     };
05271     EntityHandle verts[10], polygons[7], polyhedron;
05272 
05273     for( int i = 0; i < 10; i++ )
05274     {
05275         rval = mbImpl->create_vertex( &coords[3 * i], verts[i] );
05276         if( MB_SUCCESS != rval ) return rval;
05277     }
05278 
05279     EntityHandle connect[] = {
05280         1, 2,  3,                                               // poly 1
05281         2, 4,  6, 5, 3,                                         // poly 2
05282         4, 10, 8, 6,                                            // polygon 3...
05283         9, 10, 4, 2, 1, 7, 8, 10, 9, 5, 6, 8, 7, 1, 3, 5, 7, 9  // polygon 7
05284     };                                                          // we know the handles directly
05285 
05286     int num_verts[7] = { 3, 5, 4, 5, 4, 4, 5 };
05287     int start_indx[7];
05288     start_indx[0] = 0;
05289     for( int i = 0; i < 6; i++ )
05290         start_indx[i + 1] = start_indx[i] + num_verts[i];
05291     for( int j = 0; j < 7; j++ )
05292     {
05293         rval = mbImpl->create_element( MBPOLYGON, &connect[start_indx[j]], num_verts[j], polygons[j] );
05294         if( MB_SUCCESS != rval ) return rval;
05295     }
05296     rval = mbImpl->create_element( MBPOLYHEDRON, polygons, 7, polyhedron );
05297     if( MB_SUCCESS != rval ) return rval;
05298 
05299     // create the aentities
05300     Range dum_range;
05301     for( int dim = 0; dim < 3; dim++ )
05302     {
05303         dum_range.clear();
05304         rval = mbImpl->get_adjacencies( &polyhedron, 1, dim, true, dum_range, Interface::UNION );
05305         if( MB_SUCCESS != rval ) return rval;
05306         // std::cout << "\n dimension:" << dim << " " << dum_range.size() << " entities";
05307     }
05308     // std::cout << "\n";
05309     /*rval=mbImpl->write_mesh("polyhedra.vtk");
05310     if (MB_SUCCESS != rval)
05311       return rval;*/
05312     // delete the polyhedron
05313     rval = mbImpl->delete_entities( &polyhedron, 1 );
05314     if( MB_SUCCESS != rval ) return rval;
05315 
05316     // check adjacencies
05317     return moab.check_adjacencies();
05318 }
05319 
05320 ErrorCode mb_memory_use_test()
05321 {
05322     Core mb;
05323     unsigned long long init_total, total_with_elem, total_with_tag, total_with_tag_data;
05324     mb.estimated_memory_use( 0, 0, 0, &init_total );
05325 
05326     double coords[12] = { 1, 2, 0, 3, 4, 0, 5, 6, 0, 7, 8, 0 };
05327     EntityHandle verts[4];
05328     for( int i = 0; i < 4; ++i )
05329         if( MB_SUCCESS != mb.create_vertex( coords + 3 * i, verts[i] ) ) return MB_FAILURE;
05330 
05331     EntityHandle elem;
05332     mb.create_element( MBQUAD, verts, 4, elem );
05333 
05334     mb.estimated_memory_use( 0, 0, 0, &total_with_elem );
05335     if( total_with_elem <= init_total ) return MB_FAILURE;
05336 
05337     unsigned long long min, am;
05338     Range r;
05339     r.insert( elem );
05340     mb.estimated_memory_use( r, &min, &am );
05341     if( min != 4 * sizeof( EntityHandle ) ) return MB_FAILURE;
05342 
05343     r.clear();
05344     r.insert( verts[0] );
05345     r.insert( verts[1] );
05346     mb.estimated_memory_use( r, &min, &am );
05347     if( min != 6 * sizeof( double ) ) return MB_FAILURE;
05348 
05349     Tag tag;
05350     if( MB_SUCCESS != mb.tag_get_handle( "TMP_TAG", 1, MB_TYPE_INTEGER, tag, MB_TAG_SPARSE | MB_TAG_EXCL ) )
05351         return MB_FAILURE;
05352     mb.estimated_memory_use( r, &min, &am );
05353     if( min != 6 * sizeof( double ) ) return MB_FAILURE;
05354 
05355     mb.estimated_memory_use( 0, 0, 0, &total_with_tag );
05356     if( total_with_tag <= total_with_elem ) return MB_FAILURE;
05357 
05358     int tag_data[] = { 0xA, 0xB };
05359     if( MB_SUCCESS != mb.tag_set_data( tag, r, &tag_data ) ) return MB_FAILURE;
05360     mb.estimated_memory_use( r, &min, &am );
05361     if( min <= 6 * sizeof( double ) ) return MB_FAILURE;
05362 
05363     mb.estimated_memory_use( 0, 0, 0, &total_with_tag_data );
05364     if( total_with_tag_data <= total_with_tag ) return MB_FAILURE;
05365 
05366     return MB_SUCCESS;
05367 }
05368 
05369 ErrorCode mb_skin_curve_test_common( bool use_adj );
05370 
05371 ErrorCode mb_skin_curve_test()
05372 {
05373     return mb_skin_curve_test_common( false );
05374 }
05375 
05376 ErrorCode mb_skin_curve_adj_test()
05377 {
05378     return mb_skin_curve_test_common( true );
05379 }
05380 
05381 ErrorCode mb_skin_surface_test_common( bool use_adj );
05382 
05383 ErrorCode mb_skin_surface_test()
05384 {
05385     return mb_skin_surface_test_common( false );
05386 }
05387 
05388 ErrorCode mb_skin_surface_adj_test()
05389 {
05390     return mb_skin_surface_test_common( true );
05391 }
05392 
05393 ErrorCode mb_skin_volume_test_common( bool use_adj );
05394 
05395 ErrorCode mb_skin_volume_test()
05396 {
05397     return mb_skin_volume_test_common( false );
05398 }
05399 
05400 ErrorCode mb_skin_volume_adj_test()
05401 {
05402     return mb_skin_volume_test_common( true );
05403 }
05404 
05405 ErrorCode mb_skin_curve_test_common( bool use_adj )
05406 {
05407     ErrorCode rval;
05408     Core moab;
05409     Interface* mb = &moab;
05410 
05411     std::vector< EntityHandle > verts;
05412     for( unsigned i = 0; i < 10; ++i )
05413     {
05414         double coords[] = { static_cast< double >( i ), 0, 0 };
05415         EntityHandle h;
05416         mb->create_vertex( coords, h );
05417         verts.push_back( h );
05418     }
05419     Range edges;
05420     for( unsigned i = 1; i < verts.size(); ++i )
05421     {
05422         EntityHandle conn[] = { verts[i - 1], verts[i] };
05423         EntityHandle h;
05424         mb->create_element( MBEDGE, conn, 2, h );
05425         edges.insert( h );
05426     }
05427 
05428     Range skin;
05429     Skinner tool( mb );
05430     rval = tool.find_skin( 0, edges, 0, skin, use_adj );
05431     if( MB_SUCCESS != rval )
05432     {
05433         std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
05434         return MB_FAILURE;
05435     }
05436     if( skin.size() != 2 )
05437     {
05438         std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
05439         return MB_FAILURE;
05440     }
05441 
05442     if( verts.front() > verts.back() ) std::swap( verts.front(), verts.back() );
05443     if( skin.front() != verts.front() || skin.back() != verts.back() )
05444     {
05445         std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
05446         return MB_FAILURE;
05447     }
05448 
05449     // now test again with only one edge
05450     EntityHandle edge = edges.front();
05451     Range range( edge, edge );
05452     skin.clear();
05453     rval = tool.find_skin( 0, range, 0, skin, use_adj );
05454     if( MB_SUCCESS != rval )
05455     {
05456         std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
05457         return MB_FAILURE;
05458     }
05459     if( skin.size() != 2 )
05460     {
05461         std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
05462         return MB_FAILURE;
05463     }
05464 
05465     Range verts2;
05466     mb->get_connectivity( &edge, 1, verts2 );
05467     if( skin.front() != verts2.front() || skin.back() != verts2.back() )
05468     {
05469         std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
05470         return MB_FAILURE;
05471     }
05472 
05473     return MB_SUCCESS;
05474 }
05475 
05476 ErrorCode mb_skin_surface_test_common( bool use_adj )
05477 {
05478     ErrorCode rval;
05479     Core moab;
05480     Interface* mb = &moab;
05481 
05482     /* Create 4 of 5 faces of a wedge: */
05483     /*
05484             4
05485            /|\
05486           / | \
05487          /  |  \
05488         /   2   \
05489        3.../.\...5
05490        |  /   \  |
05491        | /     \ |
05492        |/       \|
05493        0_________1
05494      */
05495 
05496     const double coords[][3] = { { 0, 0, 0 }, { 2, 0, 0 }, { 1, 0, 1 }, { 0, 2, 0 }, { 2, 2, 0 }, { 1, 2, 1 } };
05497     EntityHandle verts[6];
05498     for( unsigned i = 0; i < 6; ++i )
05499         mb->create_vertex( coords[i], verts[i] );
05500 
05501     EntityHandle faces[4];
05502     EntityHandle tri[]   = { verts[0], verts[1], verts[2] };
05503     EntityHandle quad1[] = { verts[0], verts[1], verts[5], verts[3] };
05504     EntityHandle quad2[] = { verts[1], verts[5], verts[4], verts[2] };
05505     EntityHandle quad3[] = { verts[2], verts[4], verts[3], verts[0] };
05506     mb->create_element( MBTRI, tri, 3, faces[0] );
05507     mb->create_element( MBQUAD, quad1, 4, faces[1] );
05508     mb->create_element( MBQUAD, quad2, 4, faces[2] );
05509     mb->create_element( MBQUAD, quad3, 4, faces[3] );
05510     Range source;
05511     std::copy( faces, faces + 4, range_inserter( source ) );
05512 
05513     // Now skin the mesh.  The only missing face is the
05514     // back triangle (verts 3, 4, & 5) so the skin should
05515     // be the edges bordering that face.
05516 
05517     Range skin;
05518     Skinner tool( mb );
05519     rval = tool.find_skin( 0, source, 1, skin, use_adj );
05520     if( MB_SUCCESS != rval )
05521     {
05522         std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
05523         return MB_FAILURE;
05524     }
05525     if( skin.size() != 3 || !skin.all_of_type( MBEDGE ) )
05526     {
05527         std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
05528         return MB_FAILURE;
05529     }
05530 
05531     // Check each edge
05532     std::vector< EntityHandle > conn[3];
05533     rval = mb->get_connectivity( &skin.front(), 1, conn[0] );
05534     if( MB_SUCCESS != rval ) return rval;
05535     rval = mb->get_connectivity( &*++skin.begin(), 1, conn[1] );
05536     if( MB_SUCCESS != rval ) return rval;
05537     rval = mb->get_connectivity( &skin.back(), 1, conn[2] );
05538     if( MB_SUCCESS != rval ) return rval;
05539     for( int i = 0; i < 3; ++i )
05540         if( conn[i][0] > conn[i][1] ) std::swap( conn[i][0], conn[i][1] );
05541 
05542     for( int i = 0; i < 3; ++i )
05543     {
05544         EntityHandle s = verts[i + 3], e = verts[( i + 1 ) % 3 + 3];
05545         if( s > e ) std::swap( s, e );
05546         int j = 0;
05547         for( j = 0; j < 3; ++j )
05548             if( conn[j][0] == s && conn[j][1] == e ) break;
05549 
05550         if( j == 3 )
05551         {
05552             std::cerr << "Skin does not contain edge [" << s << "," << e << "] at " << __FILE__ ":" << __LINE__
05553                       << std::endl;
05554             return MB_FAILURE;
05555         }
05556     }
05557 
05558     return MB_SUCCESS;
05559 }
05560 
05561 ErrorCode mb_skin_volume_test_common( bool use_adj )
05562 {
05563     ErrorCode rval;
05564     Core moab;
05565     Interface* mb = &moab;
05566 
05567     /* A 2 adjacent hexes hexes */
05568     /*
05569           9-----10----11
05570          /     /     /|
05571         /     /     / |
05572        6-----7-----8..5
05573        | .   | .   | /
05574        |.    |.    |/
05575        0-----1-----2
05576      */
05577 
05578     const double coords[][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 2, 0, 0 }, { 0, 1, 0 }, { 1, 1, 0 }, { 2, 1, 0 },
05579                                  { 0, 0, 1 }, { 1, 0, 1 }, { 2, 0, 1 }, { 0, 1, 1 }, { 1, 1, 1 }, { 2, 1, 1 } };
05580     EntityHandle verts[12];
05581     for( unsigned i = 0; i < 12; ++i )
05582         mb->create_vertex( coords[i], verts[i] );
05583 
05584     EntityHandle hex1c[] = { verts[0], verts[1], verts[4], verts[3], verts[6], verts[7], verts[10], verts[9] };
05585     EntityHandle hex2c[] = { verts[1], verts[2], verts[5], verts[4], verts[7], verts[8], verts[11], verts[10] };
05586     EntityHandle hex1, hex2;
05587     mb->create_element( MBHEX, hex1c, 8, hex1 );
05588     mb->create_element( MBHEX, hex2c, 8, hex2 );
05589     Range source;
05590     source.insert( hex1 );
05591     source.insert( hex2 );
05592 
05593     // get all quads and shared face
05594     Range tmp, all_faces;
05595     mb->get_adjacencies( source, 2, true, all_faces, Interface::UNION );
05596     mb->get_adjacencies( source, 2, true, tmp, Interface::INTERSECT );
05597     assert( tmp.size() == 1 );
05598     Range non_shared = subtract( all_faces, tmp );
05599 
05600     // Now skin the mesh.
05601 
05602     Range skin;
05603     Skinner tool( mb );
05604     rval = tool.find_skin( 0, source, 2, skin, use_adj );
05605     if( MB_SUCCESS != rval )
05606     {
05607         std::cerr << "Skinner failure at " __FILE__ ":" << __LINE__ << std::endl;
05608         return MB_FAILURE;
05609     }
05610     if( skin != non_shared )
05611     {
05612         std::cerr << "Skinner bad result at " __FILE__ ":" << __LINE__ << std::endl;
05613         return MB_FAILURE;
05614     }
05615 
05616     return MB_SUCCESS;
05617 }
05618 
05619 ErrorCode mb_skin_scd_test()
05620 {
05621     // make a 10x10x5 scd mesh
05622     Core moab;
05623     Interface* mb = &moab;
05624     ScdInterface* scdi;
05625     ErrorCode rval = mb->query_interface( scdi );
05626     if( MB_SUCCESS != rval ) return rval;
05627     HomCoord low( 0, 0, 0 ), high( 10, 10, 5 );
05628     ScdBox* this_box;
05629     rval = scdi->construct_box( low, high, NULL, 0, this_box );
05630     if( MB_SUCCESS != rval ) return rval;
05631 
05632     // now skin it with the structured and original method, and compare results
05633     Skinner tool( mb );
05634     Range ents( this_box->start_element(), this_box->start_element() + this_box->num_elements() - 1 ), scd_skin_ents,
05635         skin_ents;
05636     rval = tool.find_skin( 0, ents, false, scd_skin_ents, NULL, true, true, true );
05637     if( MB_SUCCESS != rval ) return rval;
05638 
05639     rval = tool.find_skin( 0, ents, false, skin_ents, NULL, true, true, false );
05640     if( MB_SUCCESS != rval ) return rval;
05641 
05642     // should be same number of entities
05643     if( scd_skin_ents.size() != skin_ents.size() ) return MB_FAILURE;
05644 
05645     skin_ents.clear();
05646     scd_skin_ents.clear();
05647 
05648     // now test getting faces and vertices, also with existing faces now
05649     rval = tool.find_skin( 0, ents, true, scd_skin_ents, NULL, true, true, true );
05650     if( MB_SUCCESS != rval ) return rval;
05651 
05652     rval = tool.find_skin( 0, ents, true, skin_ents, NULL, true, true, false );
05653     if( MB_SUCCESS != rval ) return rval;
05654 
05655     // again, should have same numbers
05656     if( skin_ents.subset_by_type( MBVERTEX ).size() != scd_skin_ents.subset_by_type( MBVERTEX ).size() )
05657         return MB_FAILURE;
05658 
05659     return MB_SUCCESS;
05660 }
05661 
05662 ErrorCode mb_skin_fileset_test()
05663 {
05664     Core moab;
05665     Interface* mb = &moab;
05666     ErrorCode error;
05667     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,
05668                               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 };
05669     const size_t num_vtx  = sizeof( coords ) / sizeof( double ) / 3;
05670 
05671     const int conn[]       = { 0, 1, 4,  5,  6,  7,  10, 11, 1, 2, 3, 4,  7,  8,  9,  10,
05672                          6, 7, 10, 11, 12, 13, 16, 17, 7, 8, 9, 10, 13, 14, 15, 16 };
05673     const size_t num_elems = sizeof( conn ) / sizeof( int ) / 8;
05674 
05675     EntityHandle verts[num_vtx], cells[num_elems];
05676     for( size_t i = 0; i < num_vtx; ++i )
05677     {
05678         error = mb->create_vertex( coords + 3 * i, verts[i] );MB_CHK_ERR( error );
05679     }
05680 
05681     for( size_t i = 0; i < num_elems; ++i )
05682     {
05683         EntityHandle c[8];
05684         for( int j = 0; j < 8; j++ )
05685             c[j] = verts[conn[8 * i + j]];
05686 
05687         error = mb->create_element( MBHEX, c, 8, cells[i] );MB_CHK_ERR( error );
05688     }
05689 
05690     EntityHandle fileset;
05691     error = mb->create_meshset( MESHSET_SET, fileset );MB_CHK_ERR( error );
05692     error = mb->add_entities( fileset, &verts[0], num_vtx );MB_CHK_ERR( error );
05693     error = mb->add_entities( fileset, &cells[0], num_elems );MB_CHK_ERR( error );
05694 
05695     Range fverts, fedges, ffaces, fcells;
05696     error = mb->get_entities_by_dimension( fileset, 0, fverts );MB_CHK_ERR( error );
05697     error = mb->get_entities_by_dimension( fileset, 1, fedges );MB_CHK_ERR( error );
05698     error = mb->get_entities_by_dimension( fileset, 2, ffaces );MB_CHK_ERR( error );
05699     error = mb->get_entities_by_dimension( fileset, 3, fcells );MB_CHK_ERR( error );
05700 
05701     assert( fverts.size() == 18 && fedges.size() == 0 && ffaces.size() == 0 && fcells.size() == 4 );
05702 
05703     Skinner sk( mb );
05704     Range skin_ents;
05705     error = sk.find_skin( fileset, fcells, 2, skin_ents, false, true );MB_CHK_ERR( error );
05706     error = mb->get_entities_by_dimension( fileset, 2, ffaces );MB_CHK_ERR( error );
05707     assert( ffaces.size() == 16 );
05708     error = sk.find_skin( fileset, fcells, 1, skin_ents, false, true );MB_CHK_ERR( error );
05709     error = mb->get_entities_by_dimension( fileset, 1, fedges );MB_CHK_ERR( error );
05710     assert( fedges.size() == 32 );
05711 
05712     const double fcoords[] = { 0, 0, 3, 1, 0, 3, 2, 0, 3, 2, 1, 3, 1, 1, 3, 0, 1, 3 };
05713     const size_t num_fvtx  = sizeof( fcoords ) / sizeof( double ) / 3;
05714 
05715     const int fconn[]      = { 0, 1, 4, 5, 1, 2, 3, 4 };
05716     const size_t num_faces = sizeof( fconn ) / sizeof( int ) / 4;
05717     EntityHandle nwverts[num_fvtx], faces[num_faces];
05718     for( size_t i = 0; i < num_fvtx; ++i )
05719     {
05720         error = mb->create_vertex( fcoords + 3 * i, nwverts[i] );MB_CHK_ERR( error );
05721     }
05722 
05723     for( size_t i = 0; i < num_faces; ++i )
05724     {
05725         EntityHandle c[4];
05726         for( int j = 0; j < 4; j++ )
05727             c[j] = nwverts[fconn[4 * i + j]];
05728 
05729         error = mb->create_element( MBQUAD, c, 4, faces[i] );MB_CHK_ERR( error );
05730     }
05731     EntityHandle fileset1;
05732     error = mb->create_meshset( MESHSET_SET, fileset1 );MB_CHK_ERR( error );
05733     error = mb->add_entities( fileset1, &nwverts[0], num_fvtx );MB_CHK_ERR( error );
05734     error = mb->add_entities( fileset1, &faces[0], num_faces );MB_CHK_ERR( error );
05735 
05736     Range verts1, edges1, faces1;
05737     error = mb->get_entities_by_dimension( fileset1, 0, verts1 );MB_CHK_ERR( error );
05738     error = mb->get_entities_by_dimension( fileset1, 1, edges1 );MB_CHK_ERR( error );
05739     error = mb->get_entities_by_dimension( fileset1, 2, faces1 );MB_CHK_ERR( error );
05740 
05741     assert( verts1.size() == 6 && edges1.size() == 0 && faces1.size() == 2 );
05742 
05743     //  error = sk.find_skin(fileset1, faces1, 1, skin_ents, false, true);MB_CHK_ERR(error);
05744     error = sk.find_skin( fileset1, faces1, false, skin_ents, NULL, true, true, false );MB_CHK_ERR( error );
05745     error = mb->get_entities_by_dimension( fileset1, 1, edges1 );MB_CHK_ERR( error );
05746     assert( edges1.size() == 6 );
05747 
05748     return MB_SUCCESS;
05749 }
05750 
05751 // It is a common problem for readers to incorrectly
05752 // handle invalid/unknown file types and non-existant
05753 // files.  For either case, MOAB will try all readers
05754 // (assuming it doesn't recongnize the file extension),
05755 // so we can test all the readers w/out knowing which
05756 // readers we have.
05757 const char* argv0 = 0;
05758 ErrorCode mb_read_fail_test()
05759 {
05760     Core moab;
05761     Interface* mb = &moab;
05762 
05763     const char BAD_FILE_NAME[] = "non-existant-file.txt";
05764     ErrorCode rval;
05765 
05766     FILE* fptr = fopen( BAD_FILE_NAME, "r" );
05767     if( fptr )
05768     {
05769         fclose( fptr );
05770         std::cout << "Test cannot proceed while file exists: " << BAD_FILE_NAME << std::endl;
05771         return MB_FAILURE;
05772     }
05773 
05774     // try reading a non-existant file
05775 
05776     rval = mb->load_file( BAD_FILE_NAME );
05777     if( MB_FILE_DOES_NOT_EXIST != rval ) return MB_FAILURE;
05778 
05779     // try reading an invalid file
05780     if( !argv0 )  // not set by main, oops!
05781         return MB_FAILURE;
05782     rval = mb->load_file( argv0 );
05783     if( MB_SUCCESS == rval ) return MB_FAILURE;
05784 
05785     return MB_SUCCESS;
05786 }
05787 
05788 #define TEST_ERROR_CODE( E )                                                                                      \
05789     if( mb->get_error_string( E ) != #E )                                                                         \
05790     {                                                                                                             \
05791         std::cerr << "Invalid error string from get_error_string for " << #E << ": " << mb->get_error_string( E ) \
05792                   << std::endl;                                                                                   \
05793         return MB_FAILURE;                                                                                        \
05794     }
05795 
05796 ErrorCode mb_enum_string_test()
05797 {
05798     Core moab;
05799     Interface* mb = &moab;
05800 
05801     TEST_ERROR_CODE( MB_SUCCESS );
05802     TEST_ERROR_CODE( MB_INDEX_OUT_OF_RANGE );
05803     TEST_ERROR_CODE( MB_TYPE_OUT_OF_RANGE );
05804     TEST_ERROR_CODE( MB_MEMORY_ALLOCATION_FAILED );
05805     TEST_ERROR_CODE( MB_ENTITY_NOT_FOUND );
05806     TEST_ERROR_CODE( MB_MULTIPLE_ENTITIES_FOUND );
05807     TEST_ERROR_CODE( MB_TAG_NOT_FOUND );
05808     TEST_ERROR_CODE( MB_FILE_DOES_NOT_EXIST );
05809     TEST_ERROR_CODE( MB_FILE_WRITE_ERROR );
05810     TEST_ERROR_CODE( MB_NOT_IMPLEMENTED );
05811     TEST_ERROR_CODE( MB_ALREADY_ALLOCATED );
05812     TEST_ERROR_CODE( MB_VARIABLE_DATA_LENGTH );
05813     TEST_ERROR_CODE( MB_INVALID_SIZE );
05814     TEST_ERROR_CODE( MB_UNSUPPORTED_OPERATION );
05815     TEST_ERROR_CODE( MB_UNHANDLED_OPTION );
05816     TEST_ERROR_CODE( MB_STRUCTURED_MESH );
05817     TEST_ERROR_CODE( MB_FAILURE );
05818 
05819     return MB_SUCCESS;
05820 }
05821 
05822 // Test basic skinning using vert-to-elem adjacencies
05823 ErrorCode mb_skin_verts_common( unsigned dim, bool skin_elems );
05824 
05825 ErrorCode mb_skin_surf_verts_test()
05826 {
05827     return mb_skin_verts_common( 2, false );
05828 }
05829 
05830 ErrorCode mb_skin_vol_verts_test()
05831 {
05832     return mb_skin_verts_common( 3, false );
05833 }
05834 
05835 ErrorCode mb_skin_surf_verts_elems_test()
05836 {
05837     return mb_skin_verts_common( 2, true );
05838 }
05839 
05840 ErrorCode mb_skin_vol_verts_elems_test()
05841 {
05842     return mb_skin_verts_common( 3, true );
05843 }
05844 
05845 ErrorCode mb_skin_verts_common( unsigned dim, bool skin_elems )
05846 {
05847     const int INT        = 10;  // intervals+1
05848     const char* tmp_file = "structured.vtk";
05849     std::ofstream str( tmp_file );
05850     if( !str )
05851     {
05852         std::cerr << tmp_file << ": filed to create temp file" << std::endl;
05853         return MB_FAILURE;
05854     }
05855     str << "#vtk DataFile Version 2.0" << std::endl
05856         << "mb_skin_verts_common temp file" << std::endl
05857         << "ASCII" << std::endl
05858         << "DATASET STRUCTURED_POINTS" << std::endl
05859         << "DIMENSIONS " << INT << " " << ( dim > 1 ? INT : 1 ) << " " << ( dim > 2 ? INT : 1 ) << std::endl
05860         << "ORIGIN 0 0 0" << std::endl
05861         << "SPACING 1 1 1" << std::endl;
05862     str.close();
05863 
05864     Core moab;
05865     Interface& mb = moab;
05866     ErrorCode rval;
05867 
05868     rval = mb.load_file( tmp_file );
05869     remove( tmp_file );
05870     if( MB_SUCCESS != rval ) return rval;
05871 
05872     Range ents;
05873     rval = mb.get_entities_by_dimension( 0, dim, ents );
05874     if( MB_SUCCESS != rval ) return rval;
05875     if( ents.empty() ) return MB_FAILURE;
05876 
05877     Skinner tool( &mb );
05878 
05879     // mesh is a structured quad/hex mesh, so we can
05880     // determine skin vertices from the number of
05881     // adjacent elements.
05882     unsigned interior_adj = 1;
05883     for( unsigned i = 0; i < dim; ++i )
05884         interior_adj *= 2;
05885     Range expected, verts;
05886     rval = mb.get_entities_by_dimension( 0, 0, verts );
05887     if( MB_SUCCESS != rval ) return rval;
05888     Range::iterator h = expected.begin();
05889     std::vector< EntityHandle > adj;
05890     for( Range::iterator v = verts.begin(); v != verts.end(); ++v )
05891     {
05892         adj.clear();
05893         rval = mb.get_adjacencies( &*v, 1, dim, false, adj );
05894         if( MB_SUCCESS != rval ) return rval;
05895         if( adj.size() < interior_adj ) h = expected.insert( h, *v );
05896     }
05897 
05898     // Get skin vertices using skinner
05899     Range actual;
05900     rval = tool.find_skin( 0, ents, !skin_elems, actual );
05901     if( MB_SUCCESS != rval ) return rval;
05902 
05903     Range extra, missing;
05904     if( !skin_elems )
05905     {
05906         // Check that we got expected result
05907         extra   = subtract( actual, expected );
05908         missing = subtract( expected, actual );
05909         if( !extra.empty() || !missing.empty() )
05910         {
05911             std::cout << "Extra vertices returned: " << extra << std::endl
05912                       << "Missing vertices: " << missing << std::endl;
05913             return MB_FAILURE;
05914         }
05915         return MB_SUCCESS;
05916     }
05917 
05918     // test that no extra elements we're created
05919     extra.clear();
05920     rval = mb.get_entities_by_dimension( 0, dim - 1, extra );
05921     if( MB_SUCCESS != rval ) return rval;
05922     extra = subtract( extra, actual );
05923     if( !extra.empty() )
05924     {
05925         std::cout << "Extra/non-returned elements created: " << extra << std::endl;
05926         return MB_FAILURE;
05927     }
05928 
05929     // check that each skin vertex has the correct number of adjacent quads
05930     missing.clear();
05931     extra.clear();
05932     for( Range::iterator i = expected.begin(); i != expected.end(); ++i )
05933     {
05934         std::vector< EntityHandle > elem, side;
05935         rval = mb.get_adjacencies( &*i, 1, dim, false, elem );
05936         if( MB_SUCCESS != rval ) return rval;
05937         rval = mb.get_adjacencies( &*i, 1, dim - 1, false, side );
05938         if( MB_SUCCESS != rval ) return rval;
05939         if( elem.size() == 1 )
05940         {
05941             if( side.size() < dim )
05942                 missing.insert( *i );
05943             else if( side.size() > dim )
05944                 extra.insert( *i );
05945         }
05946         else if( elem.size() == interior_adj )
05947         {
05948             if( !side.empty() ) extra.insert( *i );
05949         }
05950         else
05951         {
05952             if( side.size() < interior_adj / 2 )
05953                 missing.insert( *i );
05954             else if( side.size() > interior_adj / 2 )
05955                 extra.insert( *i );
05956         }
05957     }
05958     if( !missing.empty() || !extra.empty() )
05959     {
05960         std::cout << "Skin elements missing at vertices: " << missing << std::endl
05961                   << "Extra skin elements at vertices: " << extra << std::endl;
05962         return MB_FAILURE;
05963     }
05964 
05965     // check that all returned elements are actually on the skin
05966     extra.clear();
05967     for( Range::iterator i = actual.begin(); i != actual.end(); ++i )
05968     {
05969         Range verts2;
05970         rval = mb.get_adjacencies( &*i, 1, 0, false, verts2 );
05971         if( MB_SUCCESS != rval ) return rval;
05972         verts2 = subtract( verts2, expected );
05973         if( !verts2.empty() ) extra.insert( *i );
05974     }
05975     if( !extra.empty() )
05976     {
05977         std::cout << "Skinner returned elements not on skin: " << extra << std::endl;
05978         return MB_FAILURE;
05979     }
05980 
05981     return MB_SUCCESS;
05982 }
05983 
05984 // Test that skinning of polyhedra works
05985 ErrorCode mb_skin_poly_test()
05986 {
05987     /* Create a mesh composed of 8 hexagonal prisms and
05988        two hexahedra by extruding the following cross section
05989        two steps in the Z direction.
05990 
05991                0-----1
05992               /  (0)  \
05993          (11)/         \(1)
05994             /           \
05995           11             2
05996           / \     Y     / \
05997      (10)/   \(12)^(13)/   \(2)
05998         /     \   |   /     \
05999       10      12-----13      3
06000        |       |  |  |       |
06001     (9)|       |  +--|-->X   |(3)
06002        |       |     |       |
06003        9      15-----14      4
06004         \     /       \     /
06005       (8)\   /(15) (14)\   /(4)
06006           \ /           \ /
06007            8             5
06008             \           /
06009           (7)\         /(5)
06010               \  (6)  /
06011                7-----6
06012     */
06013 
06014     const double coords2D[][2] = {
06015         { -1, 5 },                                                 // 0
06016         { 1, 5 },  { 3, 3 },   { 5, 1 },   { 5, -1 },  { 3, -3 },  // 5
06017         { 1, -5 }, { -1, -5 }, { -3, -3 }, { -5, -1 }, { -5, 1 },  // 10
06018         { -3, 3 }, { -1, 1 },  { 1, 1 },   { 1, -1 },  { -1, -1 }  // 15
06019     };
06020     const int polyconn[4][6] = {
06021         { 0, 1, 2, 13, 12, 11 }, { 2, 3, 4, 5, 14, 13 }, { 5, 6, 7, 8, 15, 14 }, { 8, 9, 10, 11, 12, 15 }
06022     };
06023     const int polyside[4][6] = {
06024         { 0, 1, 13, 16, 12, 11 }, { 2, 3, 4, 14, 17, 13 }, { 5, 6, 7, 15, 18, 14 }, { 8, 9, 10, 12, 19, 15 }
06025     };
06026 
06027     ErrorCode rval;
06028     Core moab;
06029     Interface& mb = moab;
06030     Range regions, faces, interior_faces;
06031 
06032     // create 48 vertices
06033     EntityHandle verts[3][16];
06034     for( int i = 0; i < 3; ++i )
06035     {
06036         for( int j = 0; j < 16; ++j )
06037         {
06038             double coords[3] = { coords2D[j][0], coords2D[j][1], static_cast< double >( 2 * i ) };
06039             rval             = mb.create_vertex( coords, verts[i][j] );
06040             if( MB_SUCCESS != rval ) return rval;
06041         }
06042     }
06043 
06044     // create two hexahedra
06045     EntityHandle hexes[2];
06046     for( int i = 0; i < 2; ++i )
06047     {
06048         EntityHandle conn[8] = { verts[i][15],     verts[i][14],     verts[i][13],     verts[i][12],
06049                                  verts[i + 1][15], verts[i + 1][14], verts[i + 1][13], verts[i + 1][12] };
06050         rval                 = mb.create_element( MBHEX, conn, 8, hexes[i] );
06051         if( MB_SUCCESS != rval ) return rval;
06052         regions.insert( hexes[i] );
06053     }
06054 
06055     // create hexagonal faces
06056     EntityHandle hexagons[3][4];
06057     for( int i = 0; i < 3; ++i )
06058     {
06059         for( int j = 0; j < 4; ++j )
06060         {
06061             EntityHandle conn[6];
06062             for( int k = 0; k < 6; ++k )
06063                 conn[k] = verts[i][polyconn[j][k]];
06064             rval = mb.create_element( MBPOLYGON, conn, 6, hexagons[i][j] );
06065             if( MB_SUCCESS != rval ) return rval;
06066             faces.insert( hexagons[i][j] );
06067             if( i == 1 ) interior_faces.insert( hexagons[i][j] );
06068         }
06069     }
06070 
06071     // create quadrilateral faces
06072     EntityHandle quads[2][20];
06073     for( int i = 0; i < 2; ++i )
06074     {
06075         for( int j = 0; j < 20; ++j )
06076         {
06077             int c1, c2;
06078             if( j < 12 )
06079             {
06080                 c1 = j;
06081                 c2 = ( j + 1 ) % 12;
06082             }
06083             else if( j < 16 )
06084             {
06085                 c1 = j;
06086                 c2 = 2 + 3 * ( ( j - 9 ) % 4 );
06087             }
06088             else
06089             {
06090                 c1 = j - 4;
06091                 c2 = 12 + ( j - 15 ) % 4;
06092             }
06093             EntityHandle conn[4] = { verts[i][c1], verts[i][c2], verts[i + 1][c2], verts[i + 1][c1] };
06094             rval                 = mb.create_element( MBQUAD, conn, 4, quads[i][j] );
06095             if( MB_SUCCESS != rval ) return rval;
06096             faces.insert( quads[i][j] );
06097             if( j > 11 ) interior_faces.insert( quads[i][j] );
06098         }
06099     }
06100 
06101     // create polyhedra
06102     EntityHandle poly[2][4];
06103     for( int i = 0; i < 2; ++i )
06104     {
06105         for( int j = 0; j < 4; ++j )
06106         {
06107             EntityHandle conn[8];
06108             for( int k = 0; k < 6; ++k )
06109                 conn[k] = quads[i][polyside[j][k]];
06110             conn[6] = hexagons[i][j];
06111             conn[7] = hexagons[i + 1][j];
06112             rval    = mb.create_element( MBPOLYHEDRON, conn, 8, poly[i][j] );
06113             if( MB_SUCCESS != rval ) return rval;
06114             regions.insert( poly[i][j] );
06115         }
06116     }
06117 
06118     Range interior_verts;
06119     interior_verts.insert( verts[1][12] );
06120     interior_verts.insert( verts[1][13] );
06121     interior_verts.insert( verts[1][14] );
06122     interior_verts.insert( verts[1][15] );
06123 
06124     Skinner tool( &mb );
06125     Range skin;
06126     rval = tool.find_skin( 0, regions, true, skin, 0, true, false );
06127     if( MB_SUCCESS != rval )
06128     {
06129         std::cout << "Vertex skinning failed with: " << mb.get_error_string( rval ) << std::endl;
06130         return rval;
06131     }
06132 
06133     Range all_verts, all_faces;
06134     rval = mb.get_entities_by_dimension( 0, 0, all_verts );
06135     if( MB_SUCCESS != rval ) return rval;
06136     rval = mb.get_entities_by_dimension( 0, 2, all_faces );
06137     if( MB_SUCCESS != rval ) return rval;
06138 
06139     Range expected = subtract( all_verts, interior_verts );
06140     if( expected != skin )
06141     {
06142         std::cout << "Skinner returned incorrect vertices." << std::endl;
06143         return MB_FAILURE;
06144     }
06145     if( all_faces != faces )
06146     {
06147         std::cout << "Skinner created/deleted faces for vertex-only skinning" << std::endl;
06148         return MB_FAILURE;
06149     }
06150 
06151     skin.clear();
06152     rval = tool.find_skin( 0, regions, false, skin, 0, true, false );
06153     if( MB_SUCCESS != rval )
06154     {
06155         std::cout << "Non-create face skinning failed with: " << mb.get_error_string( rval ) << std::endl;
06156         return rval;
06157     }
06158     expected = subtract( all_faces, interior_faces );
06159     if( expected != skin )
06160     {
06161         std::cout << "Skinner returned incorrect faces." << std::endl;
06162         return MB_FAILURE;
06163     }
06164     if( all_faces != faces )
06165     {
06166         std::cout << "Skinner created/deleted faces for no-create skinning" << std::endl;
06167         return MB_FAILURE;
06168     }
06169 
06170     skin.clear();
06171     rval = tool.find_skin( 0, regions, false, skin, 0, true, true );
06172     if( MB_SUCCESS != rval )
06173     {
06174         std::cout << "Create face skinning failed with: " << mb.get_error_string( rval ) << std::endl;
06175         return rval;
06176     }
06177     Range all_faces2;
06178     rval = mb.get_entities_by_dimension( 0, 2, all_faces2 );
06179     if( MB_SUCCESS != rval ) return rval;
06180     Range difference = subtract( all_faces2, all_faces );
06181     if( difference.size() != 2 )
06182     {  // should have created two quads for hex top/bottom
06183         std::cout << "Skinner failed to create new quads or created to many." << std::endl;
06184         return MB_FAILURE;
06185     }
06186     expected.merge( difference );
06187     if( expected != skin )
06188     {
06189         std::cout << "Skinner returned incorrect faces." << std::endl;
06190         return MB_FAILURE;
06191     }
06192     // check that new faces are correct
06193     EntityHandle expected_conn[2][4] = { { verts[0][12], verts[0][13], verts[0][14], verts[0][15] },
06194                                          { verts[2][12], verts[2][13], verts[2][14], verts[2][15] } };
06195     EntityHandle nq[2]               = { difference.front(), difference.back() };
06196     for( int i = 0; i < 2; ++i )
06197     {
06198         const EntityHandle* conn;
06199         int len;
06200         bool found = false;
06201         for( int j = 0; !found && j < 2; ++j )
06202         {
06203             rval = mb.get_connectivity( nq[j], conn, len );
06204             if( MB_SUCCESS != rval ) return rval;
06205             int idx1 = std::find( conn, conn + len, expected_conn[i][0] ) - conn;
06206             if( idx1 == len ) continue;
06207             found = true;
06208             for( int k = 1; k < 4; ++k )
06209                 if( conn[( idx1 + k ) % 4] != expected_conn[i][k] ) found = false;
06210             if( !found )
06211             {
06212                 found = true;
06213                 for( int k = 1; k < 4; ++k )
06214                     if( conn[( idx1 + 4 - k ) % 4] != expected_conn[i][k] ) found = false;
06215             }
06216         }
06217         if( !found )
06218         {
06219             std::cerr << "Skinner did not create & return expected quad " << i << std::endl;
06220             return MB_FAILURE;
06221         }
06222     }
06223 
06224     return MB_SUCCESS;
06225 }
06226 
06227 // Test that skinning of higher-order elements works
06228 ErrorCode mb_skin_higher_order_faces_common( bool use_adj )
06229 {
06230     /* Create mesh:
06231 
06232        0---1---2---3---4
06233        |       |      /
06234        |       |     /
06235        5   6   7  8 9
06236        |       |   /
06237        |       |  /
06238        10--11--12
06239     */
06240 
06241     ErrorCode rval;
06242     Core moab;
06243     Interface& mb = moab;
06244 
06245     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 },
06246                              { 4, 2, 0 }, { 5, 2, 0 }, { 6, 2, 0 }, { 0, 0, 0 }, { 2, 0, 0 }, { 4, 0, 0 } };
06247     EntityHandle verts[13];
06248     for( int i = 0; i < 13; ++i )
06249     {
06250         rval = mb.create_vertex( coords[i], verts[i] );
06251         if( MB_SUCCESS != rval ) return rval;
06252     }
06253 
06254     EntityHandle qconn[9] = { verts[0], verts[2],  verts[12], verts[10], verts[1],
06255                               verts[7], verts[11], verts[5],  verts[6] };
06256     EntityHandle tconn[7] = { verts[2], verts[4], verts[12], verts[3], verts[9], verts[7], verts[8] };
06257     EntityHandle quad, tri;
06258     rval = mb.create_element( MBQUAD, qconn, 9, quad );
06259     if( MB_SUCCESS != rval ) return rval;
06260     rval = mb.create_element( MBTRI, tconn, 7, tri );
06261     if( MB_SUCCESS != rval ) return rval;
06262 
06263     Range faces;
06264     faces.insert( quad );
06265     faces.insert( tri );
06266 
06267     Range skin_verts;
06268     const int skin_vert_idx[] = { 0, 1, 2, 3, 4, 5, 9, 10, 11, 12 };
06269     for( size_t i = 0; i < sizeof( skin_vert_idx ) / sizeof( skin_vert_idx[0] ); ++i )
06270         skin_verts.insert( verts[skin_vert_idx[i]] );
06271 
06272     Skinner tool( &mb );
06273     Range skin;
06274 
06275     rval = tool.find_skin( 0, faces, true, skin, 0, use_adj, false );
06276     if( MB_SUCCESS != rval )
06277     {
06278         std::cout << "Vertex skinning failed with: " << mb.get_error_string( rval ) << std::endl;
06279         return rval;
06280     }
06281     if( skin != skin_verts )
06282     {
06283         std::cout << "Skinner returned incorrect vertices." << std::endl;
06284         return MB_FAILURE;
06285     }
06286 
06287     const int skin_edges[5][3] = { { 0, 1, 2 }, { 2, 3, 4 }, { 4, 9, 12 }, { 12, 11, 10 }, { 10, 5, 0 } };
06288     skin.clear();
06289     rval = tool.find_skin( 0, faces, false, skin, 0, use_adj, true );
06290     if( MB_SUCCESS != rval )
06291     {
06292         std::cout << "Edge skinning failed with: " << mb.get_error_string( rval ) << std::endl;
06293         return rval;
06294     }
06295     if( skin.size() != 5u )
06296     {
06297         std::cout << "Skinner returned " << skin.size() << " vertices.  Expected 5" << std::endl;
06298         return MB_FAILURE;
06299     }
06300     int num_quadratic = 0;
06301     const EntityHandle* conn;
06302     int len;
06303     for( Range::iterator i = skin.begin(); i != skin.end(); ++i )
06304     {
06305         rval = mb.get_connectivity( *i, conn, len, false );
06306         if( MB_SUCCESS != rval ) return rval;
06307         if( len == 3 )
06308             num_quadratic++;
06309         else if( len != 2 )
06310         {
06311             std::cerr << "Skinner created edge with " << len << " vertices" << std::endl;
06312             return MB_FAILURE;
06313         }
06314     }
06315     if( num_quadratic != 5 )
06316     {
06317         std::cerr << num_quadratic << " of 5 created edges were quadratic" << std::endl;
06318         return MB_FAILURE;
06319     }
06320 
06321     for( int i = 0; i < 5; ++i )
06322     {
06323         bool found = false;
06324         for( Range::iterator j = skin.begin(); j != skin.end(); ++j )
06325         {
06326             mb.get_connectivity( *j, conn, len, false );
06327             if( conn[2] == verts[skin_edges[i][1]] )
06328             {
06329                 found = true;
06330                 break;
06331             }
06332         }
06333         if( !found )
06334         {
06335             std::cerr << "One or more skin edges is incorrect" << std::endl;
06336             return MB_FAILURE;
06337         }
06338         if( ( conn[0] != verts[skin_edges[i][0]] || conn[1] != verts[skin_edges[i][2]] ) &&
06339             ( conn[0] != verts[skin_edges[i][2]] || conn[1] != verts[skin_edges[i][0]] ) )
06340         {
06341             std::cerr << "Invalid skin edge connectivity" << std::endl;
06342             return MB_FAILURE;
06343         }
06344     }
06345 
06346     return MB_SUCCESS;
06347 }
06348 ErrorCode mb_skin_higher_order_faces_test()
06349 {
06350     return mb_skin_higher_order_faces_common( false );
06351 }
06352 ErrorCode mb_skin_adj_higher_order_faces_test()
06353 {
06354     return mb_skin_higher_order_faces_common( true );
06355 }
06356 
06357 // Test that skinning of higher-order elements works
06358 ErrorCode mb_skin_higher_order_regions_common( bool use_adj )
06359 {
06360     // create mesh containing two 27-node hexes
06361     /*
06362        0,2---1,2---2,2---3,2---4,2
06363         |           |           |
06364         |           |           |
06365        0,1   1,1   2,1   3,1   4,1
06366         |           |           |
06367         |           |           |
06368        0,0---1,0---2,0---3,0---4,0
06369     */
06370 
06371     ErrorCode rval;
06372     Core moab;
06373     Interface& mb = moab;
06374     Range hexes;
06375 
06376     EntityHandle verts[5][3][3];
06377     for( int i = 0; i < 5; ++i )
06378         for( int j = 0; j < 3; ++j )
06379             for( int k = 0; k < 3; ++k )
06380             {
06381                 double coords[] = { static_cast< double >( i ), static_cast< double >( j ),
06382                                     static_cast< double >( k ) };
06383                 rval            = mb.create_vertex( coords, verts[i][j][k] );
06384                 if( MB_SUCCESS != rval ) return rval;
06385             }
06386 
06387     int hex_conn[][3] = { // corners
06388                           { 0, 0, 0 },
06389                           { 2, 0, 0 },
06390                           { 2, 2, 0 },
06391                           { 0, 2, 0 },
06392                           { 0, 0, 2 },
06393                           { 2, 0, 2 },
06394                           { 2, 2, 2 },
06395                           { 0, 2, 2 },
06396                           // mid-edge
06397                           { 1, 0, 0 },
06398                           { 2, 1, 0 },
06399                           { 1, 2, 0 },
06400                           { 0, 1, 0 },
06401                           { 0, 0, 1 },
06402                           { 2, 0, 1 },
06403                           { 2, 2, 1 },
06404                           { 0, 2, 1 },
06405                           { 1, 0, 2 },
06406                           { 2, 1, 2 },
06407                           { 1, 2, 2 },
06408                           { 0, 1, 2 },
06409                           // mid-face
06410                           { 1, 0, 1 },
06411                           { 2, 1, 1 },
06412                           { 1, 2, 1 },
06413                           { 0, 1, 1 },
06414                           { 1, 1, 0 },
06415                           { 1, 1, 2 },
06416                           // mid-volume
06417                           { 1, 1, 1 }
06418     };
06419 
06420     EntityHandle hexverts[2][27];
06421     for( int i = 0; i < 2; ++i )
06422     {
06423         EntityHandle h;
06424         for( int j = 0; j < 27; ++j )
06425             hexverts[i][j] = verts[2 * i + hex_conn[j][0]][hex_conn[j][1]][hex_conn[j][2]];
06426         rval = mb.create_element( MBHEX, hexverts[i], 27, h );
06427         if( MB_SUCCESS != rval ) return rval;
06428         hexes.insert( h );
06429     }
06430 
06431     Range interior_verts;
06432     interior_verts.insert( verts[1][1][1] );  // mid-node of hex 1
06433     interior_verts.insert( verts[3][1][1] );  // mid-node of hex 2
06434     interior_verts.insert( verts[2][1][1] );  // mid-node of shared face
06435 
06436     Skinner tool( &mb );
06437     Range skin;
06438 
06439     rval = tool.find_skin( 0, hexes, true, skin, 0, use_adj, false );
06440     if( MB_SUCCESS != rval )
06441     {
06442         std::cout << "Vertex skinning failed with: " << mb.get_error_string( rval ) << std::endl;
06443         return rval;
06444     }
06445     Range extra = intersect( skin, interior_verts );
06446     if( !extra.empty() )
06447     {
06448         std::cout << "Skinner returned " << extra.size() << " interior vertices" << std::endl;
06449         std::cout << extra << std::endl;
06450         return MB_FAILURE;
06451     }
06452     int num_vtx;
06453     mb.get_number_entities_by_dimension( 0, 0, num_vtx );
06454     size_t num_skin = num_vtx - interior_verts.size();
06455     if( skin.size() != num_skin )
06456     {
06457         std::cout << "Skinner returned " << skin.size() << " of " << num_skin << " skin vertices" << std::endl;
06458         return MB_FAILURE;
06459     }
06460 
06461     skin.clear();
06462     rval = tool.find_skin( 0, hexes, false, skin, 0, use_adj, true );
06463     if( MB_SUCCESS != rval )
06464     {
06465         std::cout << "Element skinning failed with: " << mb.get_error_string( rval ) << std::endl;
06466         return rval;
06467     }
06468 
06469     if( skin.size() > 10u )
06470     {
06471         std::cout << "Skinner created too many faces" << std::endl;
06472         return MB_FAILURE;
06473     }
06474 
06475     bool all_okay    = true;
06476     bool faces[2][6] = { { false, false, false, false, false, false }, { false, false, false, false, false, false } };
06477     const EntityHandle* conn;
06478     int len;
06479     for( Range::iterator it = skin.begin(); it != skin.end(); ++it )
06480     {
06481         rval = mb.get_connectivity( *it, conn, len );
06482         if( MB_SUCCESS != rval ) return rval;
06483         if( len != 9 )
06484         {
06485             std::cout << "Skinner created face with " << len << " nodes" << std::endl;
06486             all_okay = false;
06487             continue;
06488         }
06489 
06490         int valid, side, sense, offset;
06491         for( int h = 0; h < 2; ++h )
06492         {
06493             valid = CN::SideNumber( MBHEX, hexverts[h], conn, 4, 2, side, sense, offset );
06494             if( valid != 0 ) continue;
06495             if( sense != 1 )
06496             {
06497                 std::cout << "Skinner created reversed face for hex " << h << " side " << side << std::endl;
06498                 all_okay = false;
06499                 continue;
06500             }
06501 
06502             int idx[9], len2;
06503             EntityType sidetype;
06504             CN::SubEntityNodeIndices( MBHEX, 27, 2, side, sidetype, len2, idx );
06505             assert( sidetype == MBQUAD );
06506             assert( len2 == 9 );
06507             if( conn[offset] != hexverts[h][idx[0]] || conn[( offset + 1 ) % 4] != hexverts[h][idx[1]] ||
06508                 conn[( offset + 2 ) % 4] != hexverts[h][idx[2]] || conn[( offset + 3 ) % 4] != hexverts[h][idx[3]] ||
06509                 conn[4 + offset] != hexverts[h][idx[4]] || conn[4 + ( offset + 1 ) % 4] != hexverts[h][idx[5]] ||
06510                 conn[4 + ( offset + 2 ) % 4] != hexverts[h][idx[6]] ||
06511                 conn[4 + ( offset + 3 ) % 4] != hexverts[h][idx[7]] || conn[8] != hexverts[h][idx[8]] )
06512             {
06513                 std::cout << "Side " << side << " of hex " << h << " has invalid connectivity" << std::endl;
06514                 all_okay = false;
06515             }
06516 
06517             faces[h][side] = true;
06518         }
06519     }
06520 
06521     for( int h = 0; h < 2; ++h )
06522     {
06523         for( int i = 0; i < 6; ++i )
06524         {
06525             if( ( h == 0 && i == 1 ) || ( h == 1 && i == 3 ) )
06526             {
06527                 if( faces[h][i] )
06528                 {
06529                     std::cout << "Skinner created interior face for side " << i << " of hex " << h << std::endl;
06530                     all_okay = false;
06531                 }
06532             }
06533             else if( !faces[h][i] )
06534             {
06535                 std::cout << "Skinner failed to create side " << i << " of hex " << h << std::endl;
06536                 all_okay = false;
06537             }
06538         }
06539     }
06540 
06541     return all_okay ? MB_SUCCESS : MB_FAILURE;
06542 }
06543 
06544 // Test that skinning of higher-order elements works
06545 ErrorCode mb_skin_higher_order_pyramids()
06546 {
06547     // create mesh containing 13-node pyramid
06548     /*
06549 
06550     */
06551 
06552     ErrorCode rval;
06553     Core moab;
06554     Interface& mb = moab;
06555     Range pyramids;
06556 
06557     // easier to create a 27 node grid, and then pick a 13-node pyramid
06558     EntityHandle verts[3][3][3];
06559     for( int i = 0; i < 3; ++i )
06560         for( int j = 0; j < 3; ++j )
06561             for( int k = 0; k < 3; ++k )
06562             {
06563                 double coords[] = { static_cast< double >( i ), static_cast< double >( j ),
06564                                     static_cast< double >( k ) };
06565                 rval            = mb.create_vertex( coords, verts[i][j][k] );
06566                 if( MB_SUCCESS != rval ) return rval;
06567             }
06568 
06569     EntityHandle piramid1[13] = { 19, 25, 27, 21, 1, 22, 26, 24, 20, 10, 13, 14, 11 };
06570 
06571     EntityHandle h;
06572 
06573     rval = mb.create_element( MBPYRAMID, piramid1, 13, h );
06574     if( MB_SUCCESS != rval ) return rval;
06575     pyramids.insert( h );
06576 
06577     Range faces;
06578     rval = mb.get_adjacencies( pyramids, 2, true, faces, Interface::UNION );
06579     // triangles should have 6 nodes, quads 8 nodes
06580 
06581     if( MB_SUCCESS != rval ) return rval;
06582 
06583     Range tris  = faces.subset_by_type( MBTRI );
06584     Range quads = faces.subset_by_type( MBQUAD );
06585 
06586     for( Range::iterator tit = tris.begin(); tit != tris.end(); tit++ )
06587     {
06588         EntityHandle triangle = *tit;
06589         const EntityHandle* conn;
06590         int num_verts;
06591         rval = mb.get_connectivity( triangle, conn, num_verts );
06592         if( MB_SUCCESS != rval ) return rval;
06593         if( 6 != num_verts ) return MB_FAILURE;
06594     }
06595     for( Range::iterator qit = quads.begin(); qit != quads.end(); qit++ )
06596     {
06597         EntityHandle quad = *qit;
06598         const EntityHandle* conn;
06599         int num_verts;
06600         rval = mb.get_connectivity( quad, conn, num_verts );
06601         if( MB_SUCCESS != rval ) return rval;
06602         if( 8 != num_verts ) return MB_FAILURE;
06603     }
06604 
06605     return MB_SUCCESS;
06606 }
06607 ErrorCode mb_skin_higher_order_regions_test()
06608 {
06609     return mb_skin_higher_order_regions_common( false );
06610 }
06611 ErrorCode mb_skin_adj_higher_order_regions_test()
06612 {
06613     return mb_skin_higher_order_regions_common( true );
06614 }
06615 
06616 ErrorCode mb_skin_reversed_common( int dim, bool use_adj )
06617 {
06618     EntityType type, subtype;
06619     switch( dim )
06620     {
06621         case 2:
06622             type    = MBTRI;
06623             subtype = MBEDGE;
06624             break;
06625         case 3:
06626             type    = MBTET;
06627             subtype = MBTRI;
06628             break;
06629         default:
06630             assert( false );
06631             return MB_FAILURE;
06632     }
06633 
06634     /*      3
06635            /|\
06636           / | \
06637          /  |  \
06638         /   |   \
06639        0----1----2
06640     */
06641 
06642     ErrorCode rval;
06643     Core moab;
06644     Interface& mb = moab;
06645     Range hexes;
06646 
06647     double coords[][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 2, 0, 0 }, { 1, 2, 0 }, { 1, 2, 2 } };
06648     EntityHandle verts[5];
06649     const int nvtx = 2 + dim;
06650     for( int i = 0; i < nvtx; ++i )
06651     {
06652         rval = mb.create_vertex( coords[i], verts[i] );
06653         if( MB_SUCCESS != rval ) return rval;
06654     }
06655     // NOTE: order connectivity such that side 1 is shared!
06656     EntityHandle conn[2][4] = { { verts[0], verts[1], verts[3], verts[4] },
06657                                 { verts[2], verts[3], verts[1], verts[4] } };
06658     const int conn_len      = dim + 1;
06659     Range elems;
06660     for( int i = 0; i < 2; ++i )
06661     {
06662         EntityHandle h;
06663         rval = mb.create_element( type, conn[i], conn_len, h );
06664         if( MB_SUCCESS != rval ) return rval;
06665         elems.insert( h );
06666     }
06667 
06668     // create one reversed side
06669     EntityHandle side_conn[3];
06670     int side_indices[3] = { 0, 0, 0 };
06671     CN::SubEntityVertexIndices( type, dim - 1, 0, side_indices );
06672     side_conn[0] = conn[0][side_indices[1]];
06673     side_conn[1] = conn[0][side_indices[0]];
06674     side_conn[2] = conn[0][side_indices[2]];
06675     EntityHandle side;
06676     rval = mb.create_element( subtype, side_conn, dim, side );
06677     if( MB_SUCCESS != rval ) return rval;
06678 
06679     Range forward, reverse;
06680     Skinner tool( &mb );
06681     rval = tool.find_skin( 0, elems, false, forward, &reverse, use_adj, true );
06682     if( MB_SUCCESS != rval )
06683     {
06684         std::cout << "Skinner failed." << std::endl;
06685         return rval;
06686     }
06687 
06688     // expect all faces created by the skinner to be forward,
06689     // so the only reversed side should be the one created above.
06690     if( reverse.size() != 1 || reverse.front() != side )
06691     {
06692         std::cout << "Expected 1 reversed side, got: " << reverse.size() << std::endl;
06693         return MB_FAILURE;
06694     }
06695 
06696     return MB_SUCCESS;
06697 }
06698 ErrorCode mb_skin_faces_reversed_test()
06699 {
06700     return mb_skin_reversed_common( 2, false );
06701 }
06702 ErrorCode mb_skin_adj_faces_reversed_test()
06703 {
06704     return mb_skin_reversed_common( 2, true );
06705 }
06706 ErrorCode mb_skin_regions_reversed_test()
06707 {
06708     return mb_skin_reversed_common( 3, false );
06709 }
06710 ErrorCode mb_skin_adj_regions_reversed_test()
06711 {
06712     return mb_skin_reversed_common( 3, true );
06713 }
06714 
06715 ErrorCode mb_skin_subset_common( int dimension, bool use_adj )
06716 {
06717     EntityType type;
06718     switch( dimension )
06719     {
06720         case 2:
06721             type = MBTRI;
06722             break;
06723         case 3:
06724             type = MBPRISM;
06725             break;
06726         default:
06727             assert( false );
06728             return MB_FAILURE;
06729     }
06730 
06731     /*      0
06732            /|\
06733           / | \
06734          5  |  1
06735          |\ | /|
06736          | \|/ |
06737          |  6  |
06738          | /|\ |
06739          |/ | \|
06740          4  |  2
06741           \ | /
06742            \|/
06743             3
06744      */
06745 
06746     ErrorCode rval;
06747     Core moab;
06748     Interface& mb = moab;
06749     Range expected_verts;
06750 
06751     const double coords2D[7][2] = { { 0, 2 }, { 1, 1 }, { 1, -1 }, { 0, -2 }, { -1, -1 }, { -1, 1 }, { 0, 0 } };
06752     EntityHandle verts[2][7]    = { { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 } };
06753     for( int d = 1; d < dimension; ++d )
06754     {
06755         for( int i = 0; i < 7; ++i )
06756         {
06757             double coords[3] = { coords2D[i][0], coords2D[i][1], static_cast< double >( d - 1 ) };
06758             rval             = mb.create_vertex( coords, verts[d - 1][i] );
06759             if( MB_SUCCESS != rval ) return rval;
06760             if( i != 4 && i != 5 ) expected_verts.insert( verts[d - 1][i] );
06761         }
06762     }
06763 
06764     EntityHandle elems[6];
06765     for( int i = 0; i < 6; ++i )
06766     {
06767         EntityHandle conn[6] = { verts[0][6], verts[0][( i + 1 ) % 6], verts[0][i],
06768                                  verts[1][6], verts[1][( i + 1 ) % 6], verts[1][i] };
06769         rval                 = mb.create_element( type, conn, CN::VerticesPerEntity( type ), elems[i] );
06770         if( MB_SUCCESS != rval ) return rval;
06771     }
06772 
06773     Range input;
06774     input.insert( elems[0] );
06775     input.insert( elems[1] );
06776     input.insert( elems[2] );
06777 
06778     Range skin;
06779     Skinner tool( &mb );
06780     rval = tool.find_skin( 0, input, true, skin, 0, use_adj, false );
06781     if( MB_SUCCESS != rval )
06782     {
06783         std::cout << "Skinner failed to find skin vertices" << std::endl;
06784         return MB_FAILURE;
06785     }
06786     if( skin != expected_verts )
06787     {
06788         std::cout << "Skinner returned incorrect skin vertices" << std::endl;
06789         return MB_FAILURE;
06790     }
06791     int n = 0;
06792     mb.get_number_entities_by_dimension( 0, dimension - 1, n );
06793     if( n > 0 )
06794     {
06795         std::cout << "Skinner created lower-dimension entities for vertex-only skinning" << std::endl;
06796         return MB_FAILURE;
06797     }
06798 
06799     std::vector< EntityHandle > sv( skin.begin(), skin.end() );
06800     std::vector< int > counts( sv.size(), 0 );
06801     skin.clear();
06802     rval = tool.find_skin( 0, input, false, skin, 0, use_adj, true );
06803     if( MB_SUCCESS != rval )
06804     {
06805         std::cout << "Skinner failed to find skin elements" << std::endl;
06806         return MB_FAILURE;
06807     }
06808     for( Range::iterator i = skin.begin(); i != skin.end(); ++i )
06809     {
06810         const EntityHandle* conn;
06811         int len;
06812         rval = mb.get_connectivity( *i, conn, len );
06813         if( MB_SUCCESS != rval ) return rval;
06814         for( int j = 0; j < len; ++j )
06815         {
06816             size_t idx = std::find( sv.begin(), sv.end(), conn[j] ) - sv.begin();
06817             if( idx == sv.size() )
06818             {
06819                 std::cout << "Skinner returned non-skin element" << std::endl;
06820                 return MB_FAILURE;
06821             }
06822             counts[idx]++;
06823         }
06824     }
06825     for( size_t i = 0; i < counts.size(); ++i )
06826     {
06827         if( counts[i] < dimension )
06828         {  // 2 for dim==2, {3,4,5} for dim==3
06829             std::cout << "Skinner did not return all skin elements" << std::endl;
06830             return MB_FAILURE;
06831         }
06832     }
06833     mb.get_number_entities_by_dimension( 0, dimension - 1, n );
06834     if( (size_t)n != skin.size() )
06835     {
06836         std::cout << "Skinner created extra lower-dimension entities" << std::endl;
06837         return MB_FAILURE;
06838     }
06839 
06840     return MB_SUCCESS;
06841 }
06842 
06843 ErrorCode mb_skin_faces_subset_test()
06844 {
06845     return mb_skin_subset_common( 2, false );
06846 }
06847 ErrorCode mb_skin_adj_faces_subset_test()
06848 {
06849     return mb_skin_subset_common( 2, true );
06850 }
06851 ErrorCode mb_skin_regions_subset_test()
06852 {
06853     return mb_skin_subset_common( 3, false );
06854 }
06855 ErrorCode mb_skin_adj_regions_subset_test()
06856 {
06857     return mb_skin_subset_common( 3, true );
06858 }
06859 
06860 ErrorCode mb_skin_full_common( int dimension, bool use_adj )
06861 {
06862     EntityType type;
06863     switch( dimension )
06864     {
06865         case 2:
06866             type = MBQUAD;
06867             break;
06868         case 3:
06869             type = MBHEX;
06870             break;
06871         default:
06872             assert( false );
06873             return MB_FAILURE;
06874     }
06875 
06876     /*
06877         3----4----5
06878         |    |    |
06879         |    |    |
06880         0----1----2
06881     */
06882 
06883     ErrorCode rval;
06884     Core moab;
06885     Interface& mb = moab;
06886 
06887     // create vertices
06888     const double coords2D[6][2] = { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 } };
06889     EntityHandle v[2][6]        = { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 } };
06890     for( int d = 1; d < dimension; ++d )
06891     {
06892         for( int i = 0; i < 6; ++i )
06893         {
06894             double coords[3] = { coords2D[i][0], coords2D[i][1], static_cast< double >( d - 1 ) };
06895             rval             = mb.create_vertex( coords, v[d - 1][i] );
06896             if( MB_SUCCESS != rval ) return rval;
06897         }
06898     }
06899 
06900     // create elements
06901     Range input;
06902     EntityHandle elems[2], econn[2][8];
06903     ;
06904     for( int i = 0; i < 2; ++i )
06905     {
06906         EntityHandle conn[8] = { v[0][i], v[0][i + 1], v[0][i + 4], v[0][i + 3],
06907                                  v[1][i], v[1][i + 1], v[1][i + 4], v[1][i + 3] };
06908         memcpy( econn[i], conn, sizeof( conn ) );
06909         rval = mb.create_element( type, conn, CN::VerticesPerEntity( type ), elems[i] );
06910         if( MB_SUCCESS != rval ) return rval;
06911         input.insert( elems[i] );
06912     }
06913 
06914     // create sides
06915     // NOTE: Shared side is element 0 side 1 and element 1 side 3
06916     Range expected;
06917     for( int i = 0; i < CN::NumSubEntities( type, dimension - 1 ); ++i )
06918     {
06919         EntityType subtype;
06920         int len;
06921         const short* indices = CN::SubEntityVertexIndices( type, dimension - 1, i, subtype, len );
06922         EntityHandle conn[4];
06923         assert( (size_t)len <= sizeof( conn ) / sizeof( conn[0] ) );
06924         for( int j = 0; j < 2; ++j )
06925         {
06926             if( j == 1 && i == 3 )  // don't create shared face twice
06927                 continue;
06928             for( int k = 0; k < len; ++k )
06929                 conn[k] = econn[j][indices[k]];
06930             EntityHandle h;
06931             rval = mb.create_element( subtype, conn, len, h );
06932             if( MB_SUCCESS != rval ) return rval;
06933             if( j != 0 || i != 1 )  // don't insert shared face
06934                 expected.insert( h );
06935         }
06936     }
06937 
06938     Range skin;
06939     Skinner tool( &mb );
06940     rval = tool.find_skin( 0, input, false, skin, 0, use_adj, true );
06941     if( MB_SUCCESS != rval )
06942     {
06943         std::cout << "Skinner failed to find skin elements" << std::endl;
06944         return MB_FAILURE;
06945     }
06946     if( skin != expected )
06947     {
06948         std::cout << "Skinner returned incorrect skin elements" << std::endl;
06949         return MB_FAILURE;
06950     }
06951 
06952     int n = 0;
06953     mb.get_number_entities_by_dimension( 0, dimension - 1, n );
06954     if( (size_t)n != expected.size() + 1 )
06955     {
06956         std::cout << "Skinner created extra lower-dimension entities" << std::endl;
06957         return MB_FAILURE;
06958     }
06959 
06960     return MB_SUCCESS;
06961 }
06962 
06963 ErrorCode mb_skin_faces_full_test()
06964 {
06965     return mb_skin_full_common( 2, false );
06966 }
06967 ErrorCode mb_skin_adj_faces_full_test()
06968 {
06969     return mb_skin_full_common( 2, true );
06970 }
06971 ErrorCode mb_skin_regions_full_test()
06972 {
06973     return mb_skin_full_common( 3, false );
06974 }
06975 ErrorCode mb_skin_adj_regions_full_test()
06976 {
06977     return mb_skin_full_common( 3, true );
06978 }
06979 
06980 ErrorCode mb_skin_adjacent_surf_patches()
06981 {
06982     Core moab;
06983     Interface& mb = moab;
06984     ErrorCode rval;
06985     Skinner tool( &mb );
06986 
06987     /* Mesh with vertices and quads numbered.
06988        Groups are indicated by letters {A,B,C,D}
06989 
06990        0----1----2----3----4----5
06991        | (0)| (1)| (2)| (3)| (4)|
06992        |  A |  A |  B |  B |  B |
06993        6----7----8----9---10---11
06994        | (5)| (6)| (7)| (8)| (9)|
06995        |  A |  A |  A |  B |  B |
06996       12---13---14---15---16---17
06997        |(10)|(11)|(12)|(13)|(14)|
06998        |  A |  C |  D |  D |  D |
06999       18---19---20---21---22---23
07000        |(15)|(16)|(17)|(18)|(19)|
07001        |  C |  C |  C |  D |  D |
07002       24---25---26---27---28---29
07003     */
07004 
07005     const int num_vtx = 30;
07006     EntityHandle vtx[num_vtx];
07007     for( int i = 0; i < 6; ++i )
07008     {
07009         for( int j = 0; j < 5; ++j )
07010         {
07011             double coords[3] = { static_cast< double >( i ), static_cast< double >( j ), 0 };
07012             rval             = mb.create_vertex( coords, vtx[6 * j + i] );
07013             if( MB_SUCCESS != rval ) return rval;
07014         }
07015     }
07016 
07017     EntityHandle quads[20];
07018     for( int i = 0; i < 5; ++i )
07019     {
07020         for( int j = 0; j < 4; ++j )
07021         {
07022             int v                = 6 * j + i;
07023             EntityHandle conn[4] = { vtx[v + 6], vtx[v + 7], vtx[v + 1], vtx[v + 0] };
07024             rval                 = mb.create_element( MBQUAD, conn, 4, quads[5 * j + i] );
07025             if( MB_SUCCESS != rval ) return rval;
07026         }
07027     }
07028 
07029     // Define four groups of quads (as labeled above)
07030     const int Aquads[]    = { 0, 1, 5, 6, 7, 10 };
07031     const int Aquads_size = sizeof( Aquads ) / sizeof( Aquads[0] );
07032     const int Bquads[]    = { 2, 3, 4, 8, 9 };
07033     const int Bquads_size = sizeof( Bquads ) / sizeof( Bquads[0] );
07034     const int Cquads[]    = { 11, 15, 16, 17 };
07035     const int Cquads_size = sizeof( Cquads ) / sizeof( Cquads[0] );
07036     const int Dquads[]    = { 12, 13, 14, 18, 19 };
07037     const int Dquads_size = sizeof( Dquads ) / sizeof( Dquads[0] );
07038 
07039     // Define the results we expect for each group as a loop
07040     // of vertex indices
07041     const int Askin[]    = { 0, 1, 2, 8, 9, 15, 14, 13, 19, 18, 12, 6 };
07042     const int Ashared[]  = { -1, -1, 1, 1, 1, 3, 2, 2, 2, -1, -1, -1 };
07043     const int Askin_size = sizeof( Askin ) / sizeof( Askin[0] );
07044     const int Bskin[]    = { 2, 3, 4, 5, 11, 17, 16, 15, 9, 8 };
07045     const int Bshared[]  = { -1, -1, -1, -1, -1, 3, 3, 0, 0, 0 };
07046     const int Bskin_size = sizeof( Bskin ) / sizeof( Bskin[0] );
07047     const int Cskin[]    = { 18, 19, 13, 14, 20, 21, 27, 26, 25, 24 };
07048     const int Cshared[]  = { 0, 0, 0, 3, 3, 3, -1, -1, -1, -1 };
07049     const int Cskin_size = sizeof( Cskin ) / sizeof( Cskin[0] );
07050     const int Dskin[]    = { 14, 15, 16, 17, 23, 29, 28, 27, 21, 20 };
07051     const int Dshared[]  = { 0, 1, 1, -1, -1, -1, -1, 2, 2, 2 };
07052     const int Dskin_size = sizeof( Dskin ) / sizeof( Dskin[0] );
07053 
07054     // Make the above stuff indexable for easier looping
07055     const int* const gquads[4] = { Aquads, Bquads, Cquads, Dquads };
07056     const int gquads_size[4]   = { Aquads_size, Bquads_size, Cquads_size, Dquads_size };
07057     const int* const skin[4]   = { Askin, Bskin, Cskin, Dskin };
07058     const int* const shared[4] = { Ashared, Bshared, Cshared, Dshared };
07059     const int skin_size[4]     = { Askin_size, Bskin_size, Cskin_size, Dskin_size };
07060 
07061     // Create an Range for each group of quads
07062     Range ranges[4];
07063     for( int grp = 0; grp < 4; ++grp )
07064         for( int i = 0; i < gquads_size[grp]; ++i )
07065             ranges[grp].insert( quads[gquads[grp][i]] );
07066 
07067     // run test 4 times, one for each of:
07068     // o no adjacencies, no edges
07069     // o no adjacencies, edges
07070     // o adjacencies, edges
07071     // o adjacencies, no edges
07072     //
07073     // Be careful here: once we specify use_adj, we can't
07074     // unspecify it (the adjacencies will exist so the skinner
07075     // will use them, regardless of the passed flag.)
07076     int error_count = 0;
07077     for( int run = 0; run < 4; ++run )
07078     {
07079         const bool use_adj = run > 1;
07080         if( run == 3 )
07081         {
07082             Range dead;
07083             mb.get_entities_by_type( 0, MBEDGE, dead );
07084             mb.delete_entities( dead );
07085         }
07086 
07087         // test each group
07088         Range edges[4];
07089         for( int grp = 0; grp < 4; ++grp )
07090         {
07091             // get the skin edges
07092             rval = tool.find_skin( 0, ranges[grp], 1, edges[grp], use_adj );
07093             if( MB_SUCCESS != rval )
07094             {
07095                 std::cout << "Skinner failed for run " << run << " group " << grp << std::endl;
07096                 return rval;
07097             }
07098 
07099             // check that we have the expected result
07100             std::vector< bool > seen( skin_size[grp], false );
07101             for( Range::iterator e = edges[grp].begin(); e != edges[grp].end(); ++e )
07102             {
07103                 const EntityHandle* conn;
07104                 int len;
07105                 rval = mb.get_connectivity( *e, conn, len );
07106                 if( MB_SUCCESS != rval ) return rval;
07107                 if( len != 2 ) return MB_FAILURE;
07108                 const int idx1 = std::find( vtx, vtx + num_vtx, conn[0] ) - vtx;
07109                 const int idx2 = std::find( vtx, vtx + num_vtx, conn[1] ) - vtx;
07110                 int pos        = std::find( skin[grp], skin[grp] + skin_size[grp], idx1 ) - skin[grp];
07111                 if( pos == skin_size[grp] )
07112                 {
07113                     std::cout << "Non-skin vertex in skin for run " << run << " group " << grp << std::endl;
07114                     std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
07115                     ++error_count;
07116                     continue;
07117                 }
07118 
07119                 if( skin[grp][( pos + skin_size[grp] - 1 ) % skin_size[grp]] == idx2 )
07120                     pos = ( pos + skin_size[grp] - 1 ) % skin_size[grp];
07121                 else if( skin[grp][( pos + 1 ) % skin_size[grp]] != idx2 )
07122                 {
07123                     std::cout << "Non-skin edge in skin for run " << run << " group " << grp << std::endl;
07124                     std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
07125                     ++error_count;
07126                     continue;
07127                 }
07128 
07129                 if( seen[pos] )
07130                 {
07131                     std::cout << "Duplicate edge in skin for run " << run << " group " << grp << std::endl;
07132                     std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << std::endl;
07133                     ++error_count;
07134                 }
07135                 seen[pos] = true;
07136 
07137                 int shared_with = shared[grp][pos];
07138                 if( shared_with < 0 )  // not shared with another group
07139                     continue;
07140                 if( shared_with > grp )  // didn't skin other group yet
07141                     continue;
07142                 if( edges[shared_with].find( *e ) == edges[shared_with].end() )
07143                 {
07144                     std::cout << "Skin edge duplicated for run " << run << " group " << grp << std::endl;
07145                     std::cout << "idx1 = " << idx1 << ", idx2 = " << idx2 << " not in skin for group " << shared_with
07146                               << std::endl;
07147                     ++error_count;
07148                 }
07149             }
07150 
07151             int missing = std::count( seen.begin(), seen.end(), false );
07152             if( missing )
07153             {
07154                 std::cout << "Missking " << missing << " skin edges for run " << run << " group " << grp << std::endl;
07155                 error_count += missing;
07156             }
07157         }
07158     }
07159 
07160     return error_count ? MB_FAILURE : MB_SUCCESS;
07161 }
07162 
07163 static ErrorCode get_by_all_types_and_tag( Interface* mb, EntityHandle meshset, const Tag* tag_handles,
07164                                            const void* const* values, int num_tags, Range& result, int condition,
07165                                            bool recursive )
07166 {
07167     ErrorCode rval;
07168     Range tmp;
07169     const EntityType LAST = recursive ? MBENTITYSET : MBMAXTYPE;
07170     for( EntityType t = MBVERTEX; t < LAST; ++t )
07171     {
07172         tmp.clear();
07173         rval = mb->get_entities_by_type_and_tag( meshset, t, tag_handles, values, num_tags, tmp, condition, recursive );
07174         if( MB_SUCCESS != rval ) return rval;
07175         result.insert( tmp.begin(), tmp.end() );
07176     }
07177     return MB_SUCCESS;
07178 }
07179 
07180 /** Check that functions which accept a type return the
07181  *  result for all types when passed MBMAXTYPE
07182  */
07183 ErrorCode mb_type_is_maxtype_test()
07184 {
07185     Core moab;
07186     Interface* mb  = &moab;
07187     ErrorCode rval = create_some_mesh( mb );
07188     if( MB_SUCCESS != rval ) return rval;
07189 
07190     Range r1, r2;
07191     rval = mb->get_entities_by_type( 0, MBMAXTYPE, r1, false );MB_CHK_ERR( rval );
07192     rval = mb->get_entities_by_handle( 0, r2, false );MB_CHK_ERR( rval );
07193     CHECK( r1 == r2 );
07194 
07195     std::vector< EntityHandle > v1, v2;
07196     rval = mb->get_entities_by_type( 0, MBMAXTYPE, v1, false );MB_CHK_ERR( rval );
07197     rval = mb->get_entities_by_handle( 0, v2, false );MB_CHK_ERR( rval );
07198     CHECK( v1 == v2 );
07199 
07200     int c1, c2;
07201     rval = mb->get_number_entities_by_type( 0, MBMAXTYPE, c1, false );MB_CHK_ERR( rval );
07202     rval = mb->get_number_entities_by_handle( 0, c2, false );MB_CHK_ERR( rval );
07203     CHECK( c1 == c2 );
07204 
07205     Range h1, h2;
07206     Range::iterator it = r1.begin() + r1.size() / 2;
07207     h1.insert( r1.begin(), it );
07208     if( it != r1.end() ) h2.insert( ++it, r1.end() );
07209 
07210     EntityHandle s1, s2;
07211     rval = mb->create_meshset( MESHSET_SET, s1 );MB_CHK_ERR( rval );
07212     rval = mb->create_meshset( MESHSET_ORDERED, s2 );MB_CHK_ERR( rval );
07213     rval = mb->add_entities( s1, r1 );MB_CHK_ERR( rval );
07214     rval = mb->