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