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, r1.end() );
07228 
07229     EntityHandle s1, s2;
07230     rval = mb->create_meshset( MESHSET_SET, s1 );MB_CHK_ERR( rval );
07231     rval = mb->create_meshset( MESHSET_ORDERED, s2 );MB_CHK_ERR( rval );
07232     rval = mb->add_entities( s1, r1 );MB_CHK_ERR( rval );
07233     rval = mb->add_entities( s2, r2 );MB_CHK_ERR( rval );
07234     rval = mb->add_entities( s2, &s1, 1 );MB_CHK_ERR( rval );
07235 
07236     r1.clear();
07237     r2.clear();
07238     rval = mb->get_entities_by_type( s1, MBMAXTYPE, r1, false );MB_CHK_ERR( rval );
07239     rval = mb->get_entities_by_handle( s1, r2, false );MB_CHK_ERR( rval );
07240     CHECK( r1 == r2 );
07241 
07242     r1.clear();
07243     r2.clear();
07244     rval = mb->get_entities_by_type( s2, MBMAXTYPE, r1, false );MB_CHK_ERR( rval );
07245     rval = mb->get_entities_by_handle( s2, r2, false );MB_CHK_ERR( rval );
07246     CHECK( r1 == r2 );
07247 
07248     r1.clear();
07249     r2.clear();
07250     rval = mb->get_entities_by_type( s2, MBMAXTYPE, r1, true );MB_CHK_ERR( rval );
07251     rval = mb->get_entities_by_handle( s2, r2, true );MB_CHK_ERR( rval );
07252     CHECK( r1 == r2 );
07253 
07254     v1.clear();
07255     v2.clear();
07256     rval = mb->get_entities_by_type( s1, MBMAXTYPE, v1, false );MB_CHK_ERR( rval );
07257     rval = mb->get_entities_by_handle( s1, v2, false );MB_CHK_ERR( rval );
07258     CHECK( v1 == v2 );
07259 
07260     v1.clear();
07261     v2.clear();
07262     rval = mb->get_entities_by_type( s2, MBMAXTYPE, v1, false );MB_CHK_ERR( rval );
07263     rval = mb->get_entities_by_handle( s2, v2, false );MB_CHK_ERR( rval );
07264     CHECK( v1 == v2 );
07265 
07266     v1.clear();
07267     v2.clear();
07268     rval = mb->get_entities_by_type( s2, MBMAXTYPE, v1, true );MB_CHK_ERR( rval );
07269     rval = mb->get_entities_by_handle( s2, v2, true );MB_CHK_ERR( rval );
07270     CHECK( v1 == v2 );
07271 
07272     rval = mb->get_number_entities_by_type( s1, MBMAXTYPE, c1, false );MB_CHK_ERR( rval );
07273     rval = mb->get_number_entities_by_handle( s1, c2, false );MB_CHK_ERR( rval );
07274     CHECK( c1 == c2 );
07275 
07276     rval = mb->get_number_entities_by_type( s2, MBMAXTYPE, c1, false );MB_CHK_ERR( rval );
07277     rval = mb->get_number_entities_by_handle( s2, c2, false );MB_CHK_ERR( rval );
07278     CHECK( c1 == c2 );
07279 
07280     rval = mb->get_number_entities_by_type( s2, MBMAXTYPE, c1, true );MB_CHK_ERR( rval );
07281     rval = mb->get_number_entities_by_handle( s2, c2, true );MB_CHK_ERR( rval );
07282     CHECK( c1 == c2 );
07283 
07284     r1.clear();
07285     rval = mb->get_entities_by_handle( s1, r1 );MB_CHK_ERR( rval );
07286     Tag t1;
07287     rval = mb->tag_get_handle( "maxtype1", 1, MB_TYPE_INTEGER, t1, MB_TAG_SPARSE | MB_TAG_EXCL );MB_CHK_ERR( rval );
07288     std::vector< int > d1( r1.size() );
07289     Range::iterator ri;
07290     std::vector< int >::iterator ii = d1.begin();
07291     for( ri = r1.begin(); ri != r1.end(); ++ri, ++ii )
07292         *ii = ( (int)ID_FROM_HANDLE( *ri ) ) % 20;
07293     rval = mb->tag_set_data( t1, r1, &d1[0] );MB_CHK_ERR( rval );
07294 
07295     r1.clear();
07296     r2.clear();
07297     rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07298     rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07299     rval = get_by_all_types_and_tag( mb, 0, &t1, 0, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07300     CHECK( r1 == r2 );
07301     CHECK( (unsigned)c1 == r2.size() );
07302 
07303     r1.clear();
07304     r2.clear();
07305     rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07306     rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07307     rval = get_by_all_types_and_tag( mb, s1, &t1, 0, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07308     CHECK( r1 == r2 );
07309     CHECK( (unsigned)c1 == r2.size() );
07310 
07311     r1.clear();
07312     r2.clear();
07313     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07314     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07315     rval = get_by_all_types_and_tag( mb, s2, &t1, 0, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07316     CHECK( r1 == r2 );
07317     CHECK( (unsigned)c1 == r2.size() );
07318 
07319     r1.clear();
07320     r2.clear();
07321     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07322     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, 0, 1, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07323     rval = get_by_all_types_and_tag( mb, s2, &t1, 0, 1, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07324     CHECK( r1 == r2 );
07325     CHECK( (unsigned)c1 == r2.size() );
07326 
07327     int value              = 3;
07328     const void* vallist[2] = { &value, 0 };
07329 
07330     r1.clear();
07331     r2.clear();
07332     rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07333     rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07334     rval = get_by_all_types_and_tag( mb, 0, &t1, vallist, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07335     CHECK( r1 == r2 );
07336     CHECK( (unsigned)c1 == r2.size() );
07337 
07338     r1.clear();
07339     r2.clear();
07340     rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07341     rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07342     rval = get_by_all_types_and_tag( mb, s1, &t1, vallist, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07343     CHECK( r1 == r2 );
07344     CHECK( (unsigned)c1 == r2.size() );
07345 
07346     r1.clear();
07347     r2.clear();
07348     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07349     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07350     rval = get_by_all_types_and_tag( mb, s2, &t1, vallist, 1, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07351     CHECK( r1 == r2 );
07352     CHECK( (unsigned)c1 == r2.size() );
07353 
07354     r1.clear();
07355     r2.clear();
07356     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07357     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, &t1, vallist, 1, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07358     rval = get_by_all_types_and_tag( mb, s2, &t1, vallist, 1, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07359     CHECK( r1 == r2 );
07360     CHECK( (unsigned)c1 == r2.size() );
07361 
07362     r1.clear();
07363     r2.clear();
07364     rval = mb->get_entities_by_handle( s1, r1 );MB_CHK_ERR( rval );
07365     r2.insert( r1.back() );
07366     r1.clear();
07367     rval = mb->get_entities_by_handle( s2, r1 );MB_CHK_ERR( rval );
07368     r2.insert( r1.front() );
07369 
07370     Tag t2;
07371     rval = mb->tag_get_handle( "maxtype2", 1, MB_TYPE_INTEGER, t2, MB_TAG_DENSE | MB_TAG_EXCL );MB_CHK_ERR( rval );
07372     d1.resize( r2.size() );
07373     ii = d1.begin();
07374     ;
07375     for( ri = r2.begin(); ri != r2.end(); ++ri, ++ii )
07376         *ii = ( (int)ID_FROM_HANDLE( *ri ) ) % 2;
07377     rval = mb->tag_set_data( t2, r2, &d1[0] );MB_CHK_ERR( rval );
07378 
07379     Tag tags[] = { t1, t2 };
07380 
07381     r1.clear();
07382     r2.clear();
07383     rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07384     rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07385     rval = get_by_all_types_and_tag( mb, 0, tags, 0, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07386     CHECK( r1 == r2 );
07387     CHECK( (unsigned)c1 == r2.size() );
07388 
07389     r1.clear();
07390     r2.clear();
07391     rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07392     rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07393     rval = get_by_all_types_and_tag( mb, s1, tags, 0, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07394     CHECK( r1 == r2 );
07395     CHECK( (unsigned)c1 == r2.size() );
07396 
07397     r1.clear();
07398     r2.clear();
07399     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07400     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07401     rval = get_by_all_types_and_tag( mb, s2, tags, 0, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07402     CHECK( r1 == r2 );
07403     CHECK( (unsigned)c1 == r2.size() );
07404 
07405     r1.clear();
07406     r2.clear();
07407     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07408     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, 0, 2, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07409     rval = get_by_all_types_and_tag( mb, s2, tags, 0, 2, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07410     CHECK( r1 == r2 );
07411     CHECK( (unsigned)c1 == r2.size() );
07412 
07413     int val2   = 1;
07414     vallist[1] = &val2;
07415 
07416     r1.clear();
07417     r2.clear();
07418     rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07419     rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07420     rval = get_by_all_types_and_tag( mb, 0, tags, vallist, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07421     CHECK( r1 == r2 );
07422     CHECK( (unsigned)c1 == r2.size() );
07423 
07424     r1.clear();
07425     r2.clear();
07426     rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07427     rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07428     rval = get_by_all_types_and_tag( mb, s1, tags, vallist, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07429     CHECK( r1 == r2 );
07430     CHECK( (unsigned)c1 == r2.size() );
07431 
07432     r1.clear();
07433     r2.clear();
07434     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07435     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07436     rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::INTERSECT, false );MB_CHK_ERR( rval );
07437     CHECK( r1 == r2 );
07438     CHECK( (unsigned)c1 == r2.size() );
07439 
07440     r1.clear();
07441     r2.clear();
07442     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07443     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07444     rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::INTERSECT, true );MB_CHK_ERR( rval );
07445     CHECK( r1 == r2 );
07446     CHECK( (unsigned)c1 == r2.size() );
07447 
07448     r1.clear();
07449     r2.clear();
07450     rval = mb->get_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false );MB_CHK_ERR( rval );
07451     rval = mb->get_number_entities_by_type_and_tag( 0, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false );MB_CHK_ERR( rval );
07452     rval = get_by_all_types_and_tag( mb, 0, tags, vallist, 2, r2, Interface::UNION, false );MB_CHK_ERR( rval );
07453     CHECK( r1 == r2 );
07454     CHECK( (unsigned)c1 == r2.size() );
07455 
07456     r1.clear();
07457     r2.clear();
07458     rval = mb->get_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false );MB_CHK_ERR( rval );
07459     rval = mb->get_number_entities_by_type_and_tag( s1, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false );MB_CHK_ERR( rval );
07460     rval = get_by_all_types_and_tag( mb, s1, tags, vallist, 2, r2, Interface::UNION, false );MB_CHK_ERR( rval );
07461     CHECK( r1 == r2 );
07462     CHECK( (unsigned)c1 == r2.size() );
07463 
07464     r1.clear();
07465     r2.clear();
07466     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, false );MB_CHK_ERR( rval );
07467     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, false );MB_CHK_ERR( rval );
07468     rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::UNION, false );MB_CHK_ERR( rval );
07469     CHECK( r1 == r2 );
07470     CHECK( (unsigned)c1 == r2.size() );
07471 
07472     r1.clear();
07473     r2.clear();
07474     rval = mb->get_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, r1, Interface::UNION, true );MB_CHK_ERR( rval );
07475     rval = mb->get_number_entities_by_type_and_tag( s2, MBMAXTYPE, tags, vallist, 2, c1, Interface::UNION, true );MB_CHK_ERR( rval );
07476     rval = get_by_all_types_and_tag( mb, s2, tags, vallist, 2, r2, Interface::UNION, true );MB_CHK_ERR( rval );
07477     CHECK( r1 == r2 );
07478     CHECK( (unsigned)c1 == r2.size() );
07479 
07480     return MB_SUCCESS;
07481 }
07482 
07483 /** Test behavior of various functions when passed the root set
07484  */
07485 ErrorCode mb_root_set_test()
07486 {
07487     ErrorCode rval;
07488     Core moab;
07489     Interface* mb   = &moab;
07490     EntityHandle rs = mb->get_root_set();
07491 
07492     // expect root set to have zero handle
07493     CHECK( !rs );
07494 
07495     // check type
07496     EntityType type = mb->type_from_handle( rs );
07497     CHECK( MBENTITYSET == type );
07498 
07499     // Create a set to test with
07500     EntityHandle some_set;
07501     rval = mb->create_meshset( MESHSET_SET, some_set );MB_CHK_ERR( rval );
07502     Range sets;
07503     sets.insert( some_set );
07504 
07505     int exp_dim = mb->dimension_from_handle( some_set );
07506     int dim     = mb->dimension_from_handle( rs );
07507     CHECK( exp_dim == dim );
07508 
07509     // test some stuff that should fail
07510     rval = mb->clear_meshset( &rs, 1 );
07511     CHECK( MB_SUCCESS != rval );
07512     rval = mb->set_meshset_options( rs, MESHSET_ORDERED );
07513     CHECK( MB_SUCCESS != rval );
07514     rval = mb->subtract_meshset( rs, some_set );
07515     CHECK( MB_SUCCESS != rval );
07516     rval = mb->intersect_meshset( rs, some_set );
07517     CHECK( MB_SUCCESS != rval );
07518     rval = mb->unite_meshset( rs, some_set );
07519     CHECK( MB_SUCCESS != rval );
07520 
07521     // add/remove should fail for root set?
07522     rval = mb->add_entities( rs, &some_set, 1 );
07523     CHECK( MB_SUCCESS != rval );
07524     rval = mb->remove_entities( rs, &some_set, 1 );
07525     CHECK( MB_SUCCESS != rval );
07526     rval = mb->replace_entities( rs, &some_set, &some_set, 1 );
07527     CHECK( MB_SUCCESS != rval );
07528 
07529     // check flags
07530     unsigned flags;
07531     rval = mb->get_meshset_options( rs, flags );
07532     CHECK( flags & MESHSET_SET );
07533     CHECK( !( flags & MESHSET_ORDERED ) );
07534     CHECK( flags & MESHSET_TRACK_OWNER );
07535 
07536     // contains tests
07537     bool c = mb->contains_entities( rs, &some_set, 1 );
07538     CHECK( c );
07539 
07540     Range sets2;
07541     rval = mb->get_contained_meshsets( rs, sets2 );MB_CHK_ERR( rval );
07542     CHECK( sets == sets2 );
07543 
07544     int count;
07545     rval = mb->num_contained_meshsets( rs, &count );MB_CHK_ERR( rval );
07546     CHECK( count == (int)sets.size() );
07547 
07548     // The expected behavior for parent/child queries on the root set
07549     // is to return an error.
07550 
07551     rval = mb->get_parent_meshsets( rs, sets2 );
07552     CHECK( MB_SUCCESS != rval );
07553     rval = mb->get_parent_meshsets( rs, sets2, 2 );
07554     CHECK( MB_SUCCESS != rval );
07555 
07556     rval = mb->get_child_meshsets( rs, sets2 );
07557     CHECK( MB_SUCCESS != rval );
07558     rval = mb->get_child_meshsets( rs, sets2, 2 );
07559     CHECK( MB_SUCCESS != rval );
07560 
07561     rval = mb->num_parent_meshsets( rs, &count );
07562     CHECK( MB_SUCCESS != rval );
07563     rval = mb->num_parent_meshsets( rs, &count, 2 );
07564     CHECK( MB_SUCCESS != rval );
07565 
07566     rval = mb->num_child_meshsets( rs, &count );
07567     CHECK( MB_SUCCESS != rval );
07568     rval = mb->num_child_meshsets( rs, &count, 2 );
07569     CHECK( MB_SUCCESS != rval );
07570 
07571     rval = mb->add_parent_meshset( rs, some_set );
07572     CHECK( MB_SUCCESS != rval );
07573     rval = mb->add_parent_meshsets( rs, &some_set, 1 );
07574     CHECK( MB_SUCCESS != rval );
07575     rval = mb->add_child_meshset( rs, some_set );
07576     CHECK( MB_SUCCESS != rval );
07577     rval = mb->add_child_meshsets( rs, &some_set, 1 );
07578     CHECK( MB_SUCCESS != rval );
07579     rval = mb->add_parent_child( rs, some_set );
07580     CHECK( MB_SUCCESS != rval );
07581     rval = mb->remove_parent_child( rs, some_set );
07582     CHECK( MB_SUCCESS != rval );
07583     rval = mb->remove_parent_meshset( rs, some_set );
07584     CHECK( MB_SUCCESS != rval );
07585     rval = mb->remove_child_meshset( rs, some_set );
07586     CHECK( MB_SUCCESS != rval );
07587 
07588     return MB_SUCCESS;
07589 }
07590 
07591 /* Create a regular 2x2x2 hex mesh */
07592 ErrorCode create_some_mesh( Interface* iface )
07593 {
07594     const double coords[] = { 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 1, 0, 1, 1, 0, 2, 1, 0, 0, 2, 0, 1, 2, 0, 2, 2, 0,
07595                               0, 0, 1, 1, 0, 1, 2, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 0, 2, 1, 1, 2, 1, 2, 2, 1,
07596                               0, 0, 2, 1, 0, 2, 2, 0, 2, 0, 1, 2, 1, 1, 2, 2, 1, 2, 0, 2, 2, 1, 2, 2, 2, 2, 2 };
07597     const size_t num_vtx  = sizeof( coords ) / sizeof( double ) / 3;
07598     assert( num_vtx == 27u );
07599 
07600     const int conn[]      = { 0,  1,  4,  3,  9,  10, 13, 12, 1,  2,  5,  4,  10, 11, 14, 13, 3,  4,  7,  6,  12, 13,
07601                          16, 15, 4,  5,  8,  9,  13, 14, 17, 16, 9,  10, 13, 12, 18, 19, 22, 21, 10, 11, 14, 13,
07602                          19, 20, 23, 22, 12, 13, 16, 15, 21, 22, 25, 24, 13, 14, 17, 18, 22, 23, 26, 25 };
07603     const size_t num_elem = sizeof( conn ) / sizeof( conn[0] ) / 8;
07604     assert( num_elem == 8u );
07605 
07606     EntityHandle verts[num_vtx], hexes[num_elem];
07607     for( size_t i = 0; i < num_vtx; ++i )
07608     {
07609         ErrorCode err = iface->create_vertex( coords + 3 * i, verts[i] );
07610         if( MB_SUCCESS != err ) return err;
07611     }
07612 
07613     for( size_t i = 0; i < num_elem; ++i )
07614     {
07615         EntityHandle c[8];
07616         for( int j = 0; j < 8; ++j )
07617         {
07618             assert( conn[8 * i + j] < (int)num_vtx );
07619             c[j] = verts[conn[8 * i + j]];
07620         }
07621         ErrorCode err = iface->create_element( MBHEX, c, 8, hexes[i] );
07622         if( MB_SUCCESS != err ) return err;
07623     }
07624 
07625     return MB_SUCCESS;
07626 }
07627 
07628 inline bool contained( const std::vector< EntityHandle >& list, EntityHandle h )
07629 {
07630     std::vector< EntityHandle >::const_iterator i;
07631     i = std::lower_bound( list.begin(), list.end(), h );
07632     return i != list.end() && *i == h;
07633 }
07634 
07635 ErrorCode check_valid_connectivity( Interface* iface )
07636 {
07637     ErrorCode rval;
07638 
07639     // get sorted array of vertex handles so that we can
07640     // check that all vertices in connectivity are valid
07641     // handles
07642     std::vector< EntityHandle > vertices, storage;
07643     rval = iface->get_entities_by_type( 0, MBVERTEX, vertices );MB_CHK_ERR( rval );
07644     std::sort( vertices.begin(), vertices.end() );
07645 
07646     // get all the elements
07647     Range elements, tmp;
07648     for( int d = 1; d < 4; ++d )
07649     {
07650         tmp.clear();
07651         rval = iface->get_entities_by_dimension( 0, d, tmp );MB_CHK_ERR( rval );
07652         elements.merge( tmp );
07653     }
07654 
07655     // check that all connectivity handles are valid
07656     Range::iterator it;
07657     ErrorCode result = MB_SUCCESS;
07658     for( it = elements.begin(); it != elements.end(); ++it )
07659     {
07660         const EntityHandle* conn;
07661         int len;
07662         rval = iface->get_connectivity( *it, conn, len, false, &storage );MB_CHK_ERR( rval );
07663         for( int i = 0; i < len; ++i )
07664         {
07665             if( !contained( vertices, conn[i] ) )
07666             {
07667                 printf( "Invalid handle (%s %d) in connectivity of %s %d\n",
07668                         CN::EntityTypeName( TYPE_FROM_HANDLE( conn[i] ) ), (int)ID_FROM_HANDLE( conn[i] ),
07669                         CN::EntityTypeName( TYPE_FROM_HANDLE( *it ) ), (int)ID_FROM_HANDLE( *it ) );
07670                 result = MB_FAILURE;
07671             }
07672         }
07673     }
07674 
07675     return result;
07676 }
07677 
07678 static void usage( const char* exe )
07679 {
07680     cerr << "Usage: " << exe << " [-nostress] [-d input_file_dir]\n";
07681     exit( 1 );
07682 }
07683 
07684 int number_tests        = 0;
07685 int number_tests_failed = 0;
07686 #define RUN_TEST_ERR( A ) _run_test( ( A ), #A )
07687 
07688 typedef ErrorCode ( *TestFunc )();
07689 static int _run_test( TestFunc func, const char* func_str )
07690 {
07691     ++number_tests;
07692     return run_test( func, func_str );
07693 }
07694 
07695 /*!
07696   main routine for test harness
07697 */
07698 int main( int argc, char* argv[] )
07699 {
07700 #ifdef MOAB_HAVE_MPI
07701     int fail = MPI_Init( &argc, &argv );
07702     if( fail ) return fail;
07703 #endif
07704 
07705     argv0 = argv[0];
07706 
07707     // Check command line arg to see if we should avoid doing the stress test
07708 #ifdef MOAB_HAVE_NETCDF
07709     bool stress_test = true;
07710 #endif
07711 
07712     std::cout << "Size of mConnMap = " << sizeof( CN::mConnectivityMap ) << std::endl;
07713     std::cout << "Size of mUpConnMap = " << sizeof( CN::mUpConnMap ) << std::endl;
07714     std::cout << "Size of CN = " << sizeof( CN ) << std::endl;
07715 
07716     for( int i = 1; i < argc; ++i )
07717     {
07718 
07719         if( string( argv[i] ) == "-h" || string( argv[i] ) == "--help" ) usage( argv[0] );
07720 #if MOAB_HAVE_NETCDF
07721         else if( string( argv[i] ) == "-nostress" )
07722             stress_test = false;
07723 #endif
07724         else
07725         {
07726             cerr << "Invalid argument: " << argv[i] << endl;
07727             usage( argv[0] );
07728         }
07729     }
07730 
07731     // Print out Header information
07732 
07733     cout << "\n\nMOAB Comprehensive test suite:\n\n";
07734 
07735     number_tests = number_tests_failed = 0;
07736     number_tests_failed += RUN_TEST_ERR( mb_adjacent_vertex_test );
07737     number_tests_failed += RUN_TEST_ERR( mb_adjacencies_create_delete_test );
07738     number_tests_failed += RUN_TEST_ERR( mb_upward_adjacencies_test );
07739     number_tests_failed += RUN_TEST_ERR( mb_adjacent_create_test );
07740     number_tests_failed += RUN_TEST_ERR( mb_vertex_coordinate_test );
07741     number_tests_failed += RUN_TEST_ERR( mb_vertex_tag_test );
07742     number_tests_failed += RUN_TEST_ERR( mb_temporary_test );
07743     number_tests_failed += RUN_TEST_ERR( mb_mesh_sets_set_test );
07744     number_tests_failed += RUN_TEST_ERR( mb_mesh_sets_list_test );
07745     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_parent_child_test );
07746     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_set_appends );
07747     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_list_appends );
07748     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_root_appends );
07749     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_set_replace_test );
07750     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_list_replace_test );
07751     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_flag_test );
07752     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_set_add_remove_test );
07753     number_tests_failed += RUN_TEST_ERR( mb_dense_tag_test );
07754     number_tests_failed += RUN_TEST_ERR( mb_sparse_tag_test );
07755     number_tests_failed += RUN_TEST_ERR( mb_higher_order_test );
07756     number_tests_failed += RUN_TEST_ERR( mb_bit_tags_test );
07757 #if MOAB_HAVE_NETCDF
07758     number_tests_failed += RUN_TEST_ERR( mb_adjacencies_test );
07759     number_tests_failed += RUN_TEST_ERR( mb_tags_test );
07760     number_tests_failed += RUN_TEST_ERR( mb_delete_mesh_test );
07761     number_tests_failed += RUN_TEST_ERR( mb_entity_conversion_test );
07762     number_tests_failed += RUN_TEST_ERR( mb_mesh_set_tracking_test );
07763 #endif
07764     number_tests_failed += RUN_TEST_ERR( mb_forced_adjacencies_test );
07765     number_tests_failed += RUN_TEST_ERR( mb_canon_number_test );
07766     number_tests_failed += RUN_TEST_ERR( mb_side_number_test );
07767     number_tests_failed += RUN_TEST_ERR( mb_poly_test );
07768     number_tests_failed += RUN_TEST_ERR( mb_topo_util_test );
07769     number_tests_failed += RUN_TEST_ERR( mb_split_test );
07770     number_tests_failed += RUN_TEST_ERR( mb_range_seq_intersect_test );
07771     number_tests_failed += RUN_TEST_ERR( mb_poly_adjacency_test );
07772     number_tests_failed += RUN_TEST_ERR( mb_poly_adjacency_test2 );
07773     number_tests_failed += RUN_TEST_ERR( mb_memory_use_test );
07774     number_tests_failed += RUN_TEST_ERR( mb_skin_curve_test );
07775     number_tests_failed += RUN_TEST_ERR( mb_skin_curve_adj_test );
07776     number_tests_failed += RUN_TEST_ERR( mb_skin_surface_test );
07777     number_tests_failed += RUN_TEST_ERR( mb_skin_surface_adj_test );
07778     number_tests_failed += RUN_TEST_ERR( mb_skin_volume_test );
07779     number_tests_failed += RUN_TEST_ERR( mb_skin_volume_adj_test );
07780     number_tests_failed += RUN_TEST_ERR( mb_skin_surf_verts_test );
07781     number_tests_failed += RUN_TEST_ERR( mb_skin_vol_verts_test );
07782     number_tests_failed += RUN_TEST_ERR( mb_skin_surf_verts_elems_test );
07783     number_tests_failed += RUN_TEST_ERR( mb_skin_vol_verts_elems_test );
07784     number_tests_failed += RUN_TEST_ERR( mb_skin_poly_test );
07785     number_tests_failed += RUN_TEST_ERR( mb_skin_higher_order_faces_test );
07786     number_tests_failed += RUN_TEST_ERR( mb_skin_higher_order_regions_test );
07787     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_higher_order_faces_test );
07788     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_higher_order_regions_test );
07789     number_tests_failed += RUN_TEST_ERR( mb_skin_faces_reversed_test );
07790     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_faces_reversed_test );
07791     number_tests_failed += RUN_TEST_ERR( mb_skin_regions_reversed_test );
07792     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_regions_reversed_test );
07793     number_tests_failed += RUN_TEST_ERR( mb_skin_faces_subset_test );
07794     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_faces_subset_test );
07795     number_tests_failed += RUN_TEST_ERR( mb_skin_regions_subset_test );
07796     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_regions_subset_test );
07797     number_tests_failed += RUN_TEST_ERR( mb_skin_faces_full_test );
07798     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_faces_full_test );
07799     number_tests_failed += RUN_TEST_ERR( mb_skin_regions_full_test );
07800     number_tests_failed += RUN_TEST_ERR( mb_skin_adj_regions_full_test );
07801     number_tests_failed += RUN_TEST_ERR( mb_skin_adjacent_surf_patches );
07802     number_tests_failed += RUN_TEST_ERR( mb_skin_scd_test );
07803     number_tests_failed += RUN_TEST_ERR( mb_skin_fileset_test );
07804     number_tests_failed += RUN_TEST_ERR( mb_read_fail_test );
07805     number_tests_failed += RUN_TEST_ERR( mb_enum_string_test );
07806     number_tests_failed += RUN_TEST_ERR( mb_merge_update_test );
07807     number_tests_failed += RUN_TEST_ERR( mb_type_is_maxtype_test );
07808     number_tests_failed += RUN_TEST_ERR( mb_root_set_test );
07809 #if MOAB_HAVE_NETCDF
07810     number_tests_failed += RUN_TEST_ERR( mb_merge_test );
07811     if( stress_test ) number_tests_failed += RUN_TEST_ERR( mb_stress_test );
07812 #endif
07813 
07814     // summary
07815 
07816     cout << "\nMB TEST SUMMARY: \n"
07817          << "   Number Tests:           " << number_tests << "\n"
07818          << "   Number Successful:      " << number_tests - number_tests_failed << "\n"
07819          << "   Number Failed:          " << number_tests_failed << "\n\n";
07820 
07821 #ifdef MOAB_HAVE_MPI
07822     fail = MPI_Finalize();
07823     if( fail ) return fail;
07824 #endif
07825 
07826     return number_tests_failed;
07827 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines