MOAB: Mesh Oriented datABase  (version 5.3.0)
Core.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 #ifdef WIN32
00017 // turn off warnings that say they debugging identifier has been truncated
00018 // this warning comes up when using some STL containers
00019 #pragma warning( disable : 4786 )
00020 #endif
00021 
00022 #define MOAB_MPE_LOG "moab.mpe"
00023 
00024 #include <iostream>
00025 #include <sstream>
00026 #include <vector>
00027 #include <string>
00028 #include <algorithm>
00029 #include "moab/Core.hpp"
00030 #include "MeshSetSequence.hpp"
00031 #include "ElementSequence.hpp"
00032 #include "VertexSequence.hpp"
00033 #include <cassert>
00034 #include "AEntityFactory.hpp"
00035 #include "ReadUtil.hpp"
00036 #include "WriteUtil.hpp"
00037 #include "moab/CN.hpp"
00038 #include "moab/HigherOrderFactory.hpp"
00039 #include "SequenceManager.hpp"
00040 #include "moab/Error.hpp"
00041 #include "moab/ReaderWriterSet.hpp"
00042 #include "moab/ReaderIface.hpp"
00043 #include "moab/WriterIface.hpp"
00044 #include "moab/ScdInterface.hpp"
00045 #include "moab/SetIterator.hpp"
00046 
00047 #include "BitTag.hpp"
00048 #include "DenseTag.hpp"
00049 #include "MeshTag.hpp"
00050 #include "SparseTag.hpp"
00051 #include "VarLenDenseTag.hpp"
00052 #include "VarLenSparseTag.hpp"
00053 
00054 #include <sys/stat.h>
00055 #include <cerrno>
00056 #include <cstring>
00057 
00058 #ifdef MOAB_HAVE_AHF
00059 #include "moab/HalfFacetRep.hpp"
00060 #endif
00061 
00062 #ifdef MOAB_HAVE_MPI
00063 /* Leave ParallelComm.hpp before mpi.h or MPICH2 will fail
00064  * because its C++ headers do not like SEEK_* macros.
00065  */
00066 #include "moab/ParallelComm.hpp"
00067 #include "moab_mpi.h"
00068 #include "ReadParallel.hpp"
00069 #endif
00070 
00071 #ifdef MOAB_HAVE_HDF5
00072 #ifdef MOAB_HAVE_HDF5_PARALLEL
00073 #include "WriteHDF5Parallel.hpp"
00074 typedef moab::WriteHDF5Parallel DefaultWriter;
00075 #define DefaultWriterName "WriteHDF5Parallel"
00076 #else
00077 #include "WriteHDF5.hpp"
00078 typedef moab::WriteHDF5 DefaultWriter;
00079 #define DefaultWriterName "WriteHDF5"
00080 #endif
00081 #elif defined( MOAB_HAVE_NETCDF )
00082 #include "WriteNCDF.hpp"
00083 typedef moab::WriteNCDF DefaultWriter;
00084 #define DefaultWriterName "WriteNCDF"
00085 #else
00086 #include "WriteVtk.hpp"
00087 typedef moab::WriteVtk DefaultWriter;
00088 #define DefaultWriterName "WriteVtk"
00089 #endif
00090 #include "MBTagConventions.hpp"
00091 #include "ExoIIUtil.hpp"
00092 #include "EntitySequence.hpp"
00093 #include "moab/FileOptions.hpp"
00094 #ifdef LINUX
00095 #include <dlfcn.h>
00096 #include <dirent.h>
00097 #endif
00098 
00099 #ifdef MOAB_HAVE_MPI
00100 #include "moab_mpe.h"
00101 #endif
00102 
00103 // MOAB used to use a NULL handle list and a zero handle count
00104 // to indicate that tag functions are to operate on the global/mesh
00105 // value of the tag.  For the 3.0 release MOAB also accepted a handle
00106 // with a value of 0 to indicate the same.  Now we want to drop the
00107 // old NULL list method because a) it is one less special case that
00108 // must be handled in the tag get/set paths and b) it aviods unexpected
00109 // segfaults when applications requested tag data with an empty list
00110 // of handles.
00111 //
00112 // Define this constant to revert to the old behavior, but also print
00113 // a warning.
00114 #define ALLOW_NULL_FOR_MESH_TAG
00115 //
00116 // Define this to print an error and abort() when a NULL handle list
00117 // is passed.  This is intended as an interim solution to help catch
00118 // spots in code that haven't been updated for the change.
00119 #undef DISALLOW_EMPTY_HANDLE_LIST_FOR_TAGS
00120 //
00121 // The eventual goal is to define neither of the above, eliminating the
00122 // check and allowing applications to safely request tag data for no
00123 // entities.
00124 
00125 static void warn_null_array_mesh_tag()
00126 {
00127     std::cerr << "WARNING: Accepting empty array to indicate mesh tag" << std::endl;
00128 }
00129 
00130 #ifdef ALLOW_NULL_FOR_MESH_TAG
00131 #define CHECK_MESH_NULL                               \
00132     EntityHandle root = 0;                            \
00133     if( NULL == entity_handles && 0 == num_entities ) \
00134     {                                                 \
00135         entity_handles = &root;                       \
00136         num_entities   = 1;                           \
00137         warn_null_array_mesh_tag();                   \
00138     }
00139 #elif defined( DISALLOW_EMPTY_HANDLE_LIST_FOR_TAGS )
00140 #define CHECK_MESH_NULL                                                                              \
00141     if( NULL == entity_handles )                                                                     \
00142     {                                                                                                \
00143         std::cerr << "ERROR: Deprecated NULL handle list at " __FILE__ ":" << __LINE__ << std::endl; \
00144         abort();                                                                                     \
00145     }
00146 #else
00147 #define CHECK_MESH_NULL
00148 #endif
00149 
00150 namespace moab
00151 {
00152 
00153 using namespace std;
00154 
00155 static inline const MeshSet* get_mesh_set( const SequenceManager* sm, EntityHandle h )
00156 {
00157     const EntitySequence* seq;
00158     if( MBENTITYSET != TYPE_FROM_HANDLE( h ) || MB_SUCCESS != sm->find( h, seq ) ) return 0;
00159     return reinterpret_cast< const MeshSetSequence* >( seq )->get_set( h );
00160 }
00161 
00162 static inline MeshSet* get_mesh_set( SequenceManager* sm, EntityHandle h )
00163 {
00164     EntitySequence* seq;
00165     if( MBENTITYSET != TYPE_FROM_HANDLE( h ) || MB_SUCCESS != sm->find( h, seq ) ) return 0;
00166     return reinterpret_cast< MeshSetSequence* >( seq )->get_set( h );
00167 }
00168 
00169 //! Constructor
00170 Core::Core()
00171 {
00172     if( initialize() != MB_SUCCESS )
00173     {
00174         printf( "Error initializing moab::Core\n" );
00175         exit( 1 );
00176     }
00177 }
00178 
00179 //! destructor
00180 Core::~Core()
00181 {
00182     if( mMBWriteUtil ) delete mMBWriteUtil;
00183     if( mMBReadUtil ) delete mMBReadUtil;
00184     if( scdInterface ) delete scdInterface;
00185 
00186     mMBWriteUtil = NULL;
00187     mMBReadUtil  = NULL;
00188     scdInterface = NULL;
00189 
00190     deinitialize();
00191 }
00192 
00193 ErrorCode Core::initialize()
00194 {
00195 #ifdef MOAB_HAVE_MPI
00196     int flag;
00197     if( MPI_SUCCESS == MPI_Initialized( &flag ) )
00198     {
00199         if( flag )
00200         {
00201             writeMPELog = !MPE_Initialized_logging();
00202             if( writeMPELog ) (void)MPE_Init_log();
00203         }
00204     }
00205 #endif
00206 
00207     initErrorHandlerInCore = false;
00208     if( !MBErrorHandler_Initialized() )
00209     {
00210         MBErrorHandler_Init();
00211         initErrorHandlerInCore = true;
00212     }
00213 
00214     geometricDimension = 3;
00215     materialTag        = 0;
00216     neumannBCTag       = 0;
00217     dirichletBCTag     = 0;
00218     geomDimensionTag   = 0;
00219     globalIdTag        = 0;
00220 
00221     sequenceManager = new( std::nothrow ) SequenceManager;
00222     if( !sequenceManager ) return MB_MEMORY_ALLOCATION_FAILED;
00223 
00224     aEntityFactory = new( std::nothrow ) AEntityFactory( this );
00225     if( !aEntityFactory ) return MB_MEMORY_ALLOCATION_FAILED;
00226 
00227     mError = new( std::nothrow ) Error;
00228     if( !mError ) return MB_MEMORY_ALLOCATION_FAILED;
00229 
00230     mMBWriteUtil = NULL;
00231     mMBReadUtil  = NULL;
00232     scdInterface = NULL;
00233 
00234     // Readers and writers try to get pointers to above utils.
00235     // Do this after pointers are initialized. (Pointers should
00236     // really be initialized in constructor to avoid this kind
00237     // of thing -- j.kraftcheck.)
00238     readerWriterSet = new( std::nothrow ) ReaderWriterSet( this );
00239     if( !readerWriterSet ) return MB_MEMORY_ALLOCATION_FAILED;
00240 
00241     material_tag();
00242     neumannBC_tag();
00243     dirichletBC_tag();
00244     geom_dimension_tag();
00245     globalId_tag();
00246 
00247 #ifdef MOAB_HAVE_AHF
00248     ahfRep = new HalfFacetRep( this );
00249     if( !ahfRep ) return MB_MEMORY_ALLOCATION_FAILED;
00250     mesh_modified = false;
00251 #endif
00252 
00253     return MB_SUCCESS;
00254 }
00255 
00256 EntityHandle Core::get_root_set()
00257 {
00258     return 0;
00259 }
00260 
00261 void Core::deinitialize()
00262 {
00263 
00264 #ifdef MOAB_HAVE_MPI
00265     std::vector< ParallelComm* > pc_list;
00266     ParallelComm::get_all_pcomm( this, pc_list );
00267     for( std::vector< ParallelComm* >::iterator vit = pc_list.begin(); vit != pc_list.end(); ++vit )
00268         delete *vit;
00269 #endif
00270 
00271 #ifdef MOAB_HAVE_AHF
00272     delete ahfRep;
00273     ahfRep = 0;
00274 #endif
00275 
00276     if( aEntityFactory ) delete aEntityFactory;
00277 
00278     aEntityFactory = 0;
00279 
00280     while( !tagList.empty() )
00281         tag_delete( tagList.front() );
00282 
00283     if( sequenceManager ) delete sequenceManager;
00284 
00285     sequenceManager = 0;
00286 
00287     delete readerWriterSet;
00288     readerWriterSet = 0;
00289 
00290     if( mError ) delete mError;
00291     mError = 0;
00292 
00293 #ifdef MOAB_HAVE_MPI
00294     if( writeMPELog )
00295     {
00296         const char* default_log = MOAB_MPE_LOG;
00297         const char* logfile     = getenv( "MPE_LOG_FILE" );
00298         if( !logfile ) logfile = default_log;
00299         MPE_Finish_log( logfile );
00300     }
00301 #endif
00302 
00303     if( initErrorHandlerInCore ) MBErrorHandler_Finalize();
00304 }
00305 
00306 ErrorCode Core::query_interface_type( const std::type_info& interface_type, void*& ptr )
00307 {
00308     if( interface_type == typeid( ReadUtilIface ) )
00309     {
00310         if( !mMBReadUtil ) mMBReadUtil = new ReadUtil( this, mError );
00311         ptr = static_cast< ReadUtilIface* >( mMBReadUtil );
00312     }
00313     else if( interface_type == typeid( WriteUtilIface ) )
00314     {
00315         if( !mMBWriteUtil ) mMBWriteUtil = new WriteUtil( this );
00316         ptr = static_cast< WriteUtilIface* >( mMBWriteUtil );
00317     }
00318     else if( interface_type == typeid( ReaderWriterSet ) )
00319     {
00320         ptr = reader_writer_set();
00321     }
00322     else if( interface_type == typeid( Error ) )
00323     {
00324         ptr = mError;
00325     }
00326     else if( interface_type == typeid( ExoIIInterface ) )
00327     {
00328         ptr = static_cast< ExoIIInterface* >( new ExoIIUtil( this ) );
00329     }
00330     else if( interface_type == typeid( ScdInterface ) )
00331     {
00332         if( !scdInterface ) scdInterface = new ScdInterface( this );
00333         ptr = scdInterface;
00334     }
00335     else
00336     {
00337         ptr = 0;
00338         return MB_FAILURE;
00339     }
00340     return MB_SUCCESS;
00341 }
00342 
00343 ErrorCode Core::release_interface_type( const std::type_info& interface_type, void* iface )
00344 {
00345     if( interface_type == typeid( ExoIIInterface ) )
00346         delete static_cast< ExoIIInterface* >( iface );
00347     else if( interface_type != typeid( ReadUtilIface ) && interface_type != typeid( WriteUtilIface ) &&
00348              interface_type != typeid( ReaderWriterSet ) && interface_type != typeid( Error ) &&
00349              interface_type != typeid( ScdInterface ) )
00350         return MB_FAILURE;
00351 
00352     return MB_SUCCESS;
00353 }
00354 
00355 int Core::QueryInterface( const MBuuid& uuid, UnknownInterface** iface )
00356 {
00357     *iface = 0;
00358     if( uuid == IDD_MBUnknown ) *iface = this;
00359     if( uuid == IDD_MBCore )
00360         *iface = this;
00361     else
00362         return 0;
00363     return 1;
00364 }
00365 
00366 float Core::impl_version( std::string* version_string )
00367 {
00368     if( version_string ) *version_string = MOAB_VERSION_STRING;
00369 
00370     return MOAB_VERSION_MAJOR + MOAB_VERSION_MINOR / 100.0f;
00371 }
00372 
00373 //! get the type from a handle, returns type
00374 EntityType Core::type_from_handle( const EntityHandle handle ) const
00375 {
00376     if( !handle )  // root set
00377         return MBENTITYSET;
00378     else
00379         return TYPE_FROM_HANDLE( handle );
00380 }
00381 
00382 //! get the id from a handle, returns id
00383 EntityID Core::id_from_handle( const EntityHandle handle ) const
00384 {
00385     return ID_FROM_HANDLE( handle );
00386 }
00387 
00388 //! get a handle from an id and type
00389 ErrorCode Core::handle_from_id( const EntityType entity_type, const EntityID id, EntityHandle& handle ) const
00390 {
00391     int err;
00392     handle = CREATE_HANDLE( entity_type, id, err );
00393 
00394     // check to see if handle exists
00395     const EntitySequence* dummy_seq = 0;
00396     ErrorCode error_code            = sequence_manager()->find( handle, dummy_seq );
00397     return error_code;
00398 }
00399 
00400 int Core::dimension_from_handle( const EntityHandle handle ) const
00401 {
00402     if( !handle )  // root set
00403         return 4;
00404     else
00405         return CN::Dimension( TYPE_FROM_HANDLE( handle ) );
00406 }
00407 
00408 //! load mesh from data in file
00409 //! NOTE: if there is mesh already present, the new mesh will be added
00410 ErrorCode Core::load_mesh( const char* file_name, const int* block_id_list, const int num_blocks )
00411 {
00412     const char* name = block_id_list ? MATERIAL_SET_TAG_NAME : 0;
00413     return load_file( file_name, 0, 0, name, block_id_list, num_blocks );
00414 }
00415 
00416 ErrorCode Core::load_file( const char* file_name, const EntityHandle* file_set, const char* setoptions,
00417                            const char* set_tag_name, const int* set_tag_vals, int num_set_tag_vals )
00418 {
00419     FileOptions opts( setoptions );
00420     ErrorCode rval;
00421     ReaderIface::IDTag t       = { set_tag_name, set_tag_vals, num_set_tag_vals };
00422     ReaderIface::SubsetList sl = { &t, 1, 0, 0 };
00423 
00424     assert( !file_set || ( *file_set && is_valid( *file_set ) ) );
00425     if( file_set && !*file_set )
00426     {
00427         MB_SET_GLB_ERR( MB_FAILURE, "Non-NULL file set pointer should point to non-NULL set" );
00428     }
00429 
00430     // if reading in parallel, call a different reader
00431     std::string parallel_opt;
00432     rval = opts.get_option( "PARALLEL", parallel_opt );
00433     if( MB_SUCCESS == rval )
00434     {
00435 #ifdef MOAB_HAVE_MPI
00436         ParallelComm* pcomm = 0;
00437         int pcomm_id;
00438         rval = opts.get_int_option( "PARALLEL_COMM", pcomm_id );
00439         if( MB_ENTITY_NOT_FOUND == rval ) rval = opts.get_int_option( "PCOMM", pcomm_id );
00440         if( rval == MB_SUCCESS )
00441         {
00442             pcomm = ParallelComm::get_pcomm( this, pcomm_id );
00443             if( !pcomm ) return MB_ENTITY_NOT_FOUND;
00444         }
00445         else if( rval != MB_ENTITY_NOT_FOUND )
00446             return rval;
00447         if( set_tag_name && num_set_tag_vals )
00448         {
00449             rval = ReadParallel( this, pcomm ).load_file( file_name, file_set, opts, &sl );MB_CHK_ERR( rval );
00450         }
00451         else
00452         {
00453             rval = ReadParallel( this, pcomm ).load_file( file_name, file_set, opts );MB_CHK_ERR( rval );
00454         }
00455 #else
00456         MB_SET_GLB_ERR( MB_FAILURE, "PARALLEL option not valid, this instance compiled for serial execution" );
00457 #endif
00458     }
00459     else
00460     {
00461         if( set_tag_name && num_set_tag_vals )
00462         {
00463             rval = serial_load_file( file_name, file_set, opts, &sl );MB_CHK_ERR( rval );
00464         }
00465         else
00466         {
00467             rval = serial_load_file( file_name, file_set, opts );MB_CHK_ERR( rval );
00468         }
00469     }
00470 
00471     if( MB_SUCCESS == rval && !opts.all_seen() )
00472     {
00473         std::string bad_opt;
00474         if( MB_SUCCESS == opts.get_unseen_option( bad_opt ) )
00475         {
00476             MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option: \"" << bad_opt << "\"" );
00477         }
00478         else
00479         {
00480             MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option" );
00481         }
00482     }
00483 
00484     return MB_SUCCESS;
00485 }
00486 
00487 void Core::clean_up_failed_read( const Range& initial_ents, std::vector< Tag > initial_tags )
00488 {
00489     Range new_ents;
00490     get_entities_by_handle( 0, new_ents );
00491     new_ents = subtract( new_ents, initial_ents );
00492     delete_entities( new_ents );
00493 
00494     std::vector< Tag > all_tags, new_tags;
00495     tag_get_tags( all_tags );
00496     std::sort( initial_tags.begin(), initial_tags.end() );
00497     std::sort( all_tags.begin(), all_tags.end() );
00498     std::set_difference( all_tags.begin(), all_tags.end(), initial_tags.begin(), initial_tags.end(),
00499                          std::back_inserter( new_tags ) );
00500     while( !new_tags.empty() )
00501     {
00502         tag_delete( new_tags.back() );
00503         new_tags.pop_back();
00504     }
00505 }
00506 
00507 ErrorCode Core::serial_load_file( const char* file_name, const EntityHandle* file_set, const FileOptions& opts,
00508                                   const ReaderIface::SubsetList* subsets, const Tag* id_tag )
00509 {
00510     int status;
00511 #if defined( WIN32 ) || defined( WIN64 ) || defined( MSC_VER )
00512     struct _stat stat_data;
00513     status = _stat( file_name, &stat_data );
00514 #else
00515     struct stat stat_data;
00516     status = stat( file_name, &stat_data );
00517 #endif
00518     if( status ) { MB_SET_GLB_ERR( MB_FILE_DOES_NOT_EXIST, file_name << ": " << strerror( errno ) ); }
00519 #if defined( WIN32 ) || defined( WIN64 ) || defined( MSC_VER )
00520     else if( stat_data.st_mode & _S_IFDIR )
00521     {
00522 #else
00523     else if( S_ISDIR( stat_data.st_mode ) )
00524     {
00525 #endif
00526         MB_SET_GLB_ERR( MB_FILE_DOES_NOT_EXIST, file_name << ": Cannot read directory/folder" );
00527     }
00528 
00529     const ReaderWriterSet* set = reader_writer_set();
00530 
00531     Range initial_ents;
00532     ErrorCode rval = get_entities_by_handle( 0, initial_ents );MB_CHK_ERR( rval );
00533 
00534     std::vector< Tag > initial_tags;
00535     rval = tag_get_tags( initial_tags );MB_CHK_ERR( rval );
00536 
00537     // otherwise try using the file extension to select a reader
00538     std::string ext = set->extension_from_filename( file_name );
00539 
00540     // Try all the readers
00541     ReaderWriterSet::iterator iter;
00542     rval           = MB_FAILURE;
00543     bool tried_one = false;
00544     for( iter = set->begin(); iter != set->end(); ++iter )
00545     {
00546         if( !iter->reads_extension( ext.c_str() ) ) continue;
00547 
00548         ReaderIface* reader = iter->make_reader( this );
00549         if( NULL != reader )
00550         {
00551             tried_one = true;
00552             rval      = reader->load_file( file_name, file_set, opts, subsets, id_tag );
00553             delete reader;
00554             if( MB_SUCCESS == rval ) break;
00555             clean_up_failed_read( initial_ents, initial_tags );
00556         }
00557     }
00558 
00559     if( MB_SUCCESS != rval && !tried_one )
00560     {
00561         // didn't recognize the extension; try all of them now
00562         for( iter = set->begin(); iter != set->end(); ++iter )
00563         {
00564             ReaderIface* reader = iter->make_reader( this );
00565             if( !reader ) continue;
00566             rval = reader->load_file( file_name, file_set, opts, subsets, id_tag );
00567             delete reader;
00568             if( MB_SUCCESS == rval )
00569                 break;
00570             else
00571                 clean_up_failed_read( initial_ents, initial_tags );
00572         }
00573     }
00574 
00575     if( MB_SUCCESS != rval )
00576     {
00577         clean_up_failed_read( initial_ents, initial_tags );
00578         MB_SET_ERR( rval, "Failed to load file after trying all possible readers" );
00579     }
00580     else if( file_set )
00581     {
00582         Range new_ents;
00583         get_entities_by_handle( 0, new_ents );
00584         new_ents = subtract( new_ents, initial_ents );
00585 
00586         // Check if gather set exists
00587         EntityHandle gather_set;
00588         rval = mMBReadUtil->get_gather_set( gather_set );
00589         if( MB_SUCCESS == rval )
00590         {
00591             // Exclude gather set itself
00592             new_ents.erase( gather_set );
00593 
00594             // Exclude gather set entities
00595             Range gather_ents;
00596             rval = get_entities_by_handle( gather_set, gather_ents );
00597             if( MB_SUCCESS == rval ) new_ents = subtract( new_ents, gather_ents );
00598         }
00599 
00600         rval = add_entities( *file_set, new_ents );
00601     }
00602 
00603     return rval;
00604 }  // namespace moab
00605 
00606 ErrorCode Core::serial_read_tag( const char* file_name, const char* tag_name, const FileOptions& opts,
00607                                  std::vector< int >& vals, const ReaderIface::SubsetList* subsets )
00608 {
00609     ErrorCode rval             = MB_FAILURE;
00610     const ReaderWriterSet* set = reader_writer_set();
00611 
00612     // otherwise try using the file extension to select a reader
00613     ReaderIface* reader = set->get_file_extension_reader( file_name );
00614     if( reader )
00615     {
00616         rval = reader->read_tag_values( file_name, tag_name, opts, vals, subsets );
00617         delete reader;
00618     }
00619     else
00620     {
00621         // Try all the readers
00622         ReaderWriterSet::iterator iter;
00623         for( iter = set->begin(); iter != set->end(); ++iter )
00624         {
00625             reader = iter->make_reader( this );
00626             if( NULL != reader )
00627             {
00628                 rval = reader->read_tag_values( file_name, tag_name, opts, vals, subsets );
00629                 delete reader;
00630                 if( MB_SUCCESS == rval ) break;
00631             }
00632         }
00633     }
00634 
00635     return rval;
00636 }
00637 
00638 ErrorCode Core::write_mesh( const char* file_name, const EntityHandle* output_list, const int num_sets )
00639 {
00640     return write_file( file_name, 0, 0, output_list, num_sets );
00641 }
00642 
00643 ErrorCode Core::write_file( const char* file_name, const char* file_type, const char* options_string,
00644                             const EntityHandle* output_sets, int num_output_sets, const Tag* tag_list, int num_tags )
00645 {
00646     Range range;
00647     std::copy( output_sets, output_sets + num_output_sets, range_inserter( range ) );
00648     return write_file( file_name, file_type, options_string, range, tag_list, num_tags );
00649 }
00650 
00651 ErrorCode Core::write_file( const char* file_name, const char* file_type, const char* options_string,
00652                             const Range& output_sets, const Tag* tag_list, int num_tags )
00653 {
00654     // convert range to vector
00655     std::vector< EntityHandle > list( output_sets.size() );
00656     std::copy( output_sets.begin(), output_sets.end(), list.begin() );
00657 
00658     // parse some options
00659     FileOptions opts( options_string );
00660     ErrorCode rval;
00661 
00662     rval = opts.get_null_option( "CREATE" );
00663     if( rval == MB_TYPE_OUT_OF_RANGE ) { MB_SET_GLB_ERR( MB_FAILURE, "Unexpected value for CREATE option" ); }
00664     bool overwrite = ( rval == MB_ENTITY_NOT_FOUND );
00665 
00666     // Get the file writer
00667     std::string ext = ReaderWriterSet::extension_from_filename( file_name );
00668     std::vector< std::string > qa_records;
00669     const EntityHandle* list_ptr = list.empty() ? (EntityHandle*)0 : &list[0];
00670 
00671     rval = MB_TYPE_OUT_OF_RANGE;
00672 
00673     // Try all possible writers
00674     for( ReaderWriterSet::iterator i = reader_writer_set()->begin(); i != reader_writer_set()->end(); ++i )
00675     {
00676 
00677         if( ( file_type && !i->name().compare( file_type ) ) || i->writes_extension( ext.c_str() ) )
00678         {
00679 
00680             WriterIface* writer = i->make_writer( this );
00681 
00682             // write the file
00683             rval =
00684                 writer->write_file( file_name, overwrite, opts, list_ptr, list.size(), qa_records, tag_list, num_tags );
00685             delete writer;
00686             if( MB_SUCCESS == rval ) break;
00687             printf( "Writer with name %s for file %s using extension %s (file type \"%s\") was "
00688                     "unsuccessful\n",
00689                     i->name().c_str(), file_name, ext.c_str(), file_type );
00690         }
00691     }
00692 
00693     if( file_type && rval == MB_TYPE_OUT_OF_RANGE )
00694     {
00695         MB_SET_ERR( rval, "Unrecognized file type \"" << file_type << "\"" );
00696     }
00697     // Should we use default writer (e.g. HDF5)?
00698     else if( MB_SUCCESS != rval )
00699     {
00700         DefaultWriter writer( this );
00701         printf( "Using default writer %s for file %s \n", DefaultWriterName, file_name );
00702         rval = writer.write_file( file_name, overwrite, opts, list_ptr, list.size(), qa_records, tag_list, num_tags );
00703     }
00704 
00705     if( MB_SUCCESS == rval && !opts.all_seen() )
00706     {
00707         std::string bad_opt;
00708         if( MB_SUCCESS == opts.get_unseen_option( bad_opt ) )
00709         {
00710             MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option: \"" << bad_opt << "\"" );
00711         }
00712         else
00713         {
00714             MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option" );
00715         }
00716     }
00717 
00718     return MB_SUCCESS;
00719 }
00720 
00721 //! deletes all mesh entities from this datastore
00722 ErrorCode Core::delete_mesh()
00723 {
00724 
00725     ErrorCode result = MB_SUCCESS;
00726 
00727     // perform all deinitialization procedures to clean up
00728     if( aEntityFactory ) delete aEntityFactory;
00729     aEntityFactory = new AEntityFactory( this );
00730 
00731     for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i )
00732     {
00733         result = ( *i )->release_all_data( sequenceManager, mError, false );MB_CHK_ERR( result );
00734     }
00735 
00736     sequenceManager->clear();
00737 
00738     return MB_SUCCESS;
00739 }
00740 
00741 //! get overall geometric dimension
00742 ErrorCode Core::get_dimension( int& dim ) const
00743 {
00744     dim = geometricDimension;
00745     return MB_SUCCESS;
00746 }
00747 
00748 //! set overall geometric dimension
00749 /** Returns error if setting to 3 dimensions, mesh has been created, and
00750  *  there are only 2 dimensions on that mesh
00751  */
00752 ErrorCode Core::set_dimension( const int dim )
00753 {
00754     // check to see if current dimension is smaller
00755     if( geometricDimension < dim )
00756     {
00757         // need to check the number of entities
00758         int num;
00759         /*ErrorCode result = */ get_number_entities_by_dimension( 0, geometricDimension, num );
00760 
00761         // test written to be more readable but possibly less efficient
00762         // if (MB_SUCCESS != result) return MB_FAILURE;
00763         // else if (0 != num && dim == 2 && ycoordTag == 0) return MB_FAILURE;
00764         // else if (0 != num && dim == 3 && (ycoordTag == 0 || zcoordTag == 0)) return MB_FAILURE;
00765         // TODO -- replace this with not using xcoordTag, etc...
00766     }
00767 
00768     // if we got here, it's ok to set dimension
00769     geometricDimension = dim;
00770     return MB_SUCCESS;
00771 }
00772 
00773 //! get blocked vertex coordinates for all vertices
00774 /** Blocked = all x, then all y, etc.
00775  */
00776 ErrorCode Core::get_vertex_coordinates( std::vector< double >& coords ) const
00777 {
00778     // INEFFICIENT implementation for now, until we get blocked tag access
00779     Range vertices;
00780     ErrorCode result = get_entities_by_type( 0, MBVERTEX, vertices );MB_CHK_ERR( result );
00781 
00782     // the least we can do is resize the vector and only go through the
00783     // vertex list once
00784     int num_verts = vertices.size();
00785     int vec_pos   = 0;
00786     double xyz[3];
00787     coords.resize( geometricDimension * num_verts );
00788     for( Range::iterator it = vertices.begin(); it != vertices.end(); ++it )
00789     {
00790         result = get_coords( &( *it ), 1, xyz );MB_CHK_ERR( result );
00791 
00792         coords[vec_pos]                 = xyz[0];
00793         coords[num_verts + vec_pos]     = xyz[1];
00794         coords[2 * num_verts + vec_pos] = xyz[2];
00795 
00796         vec_pos++;
00797     }
00798 
00799     return MB_SUCCESS;
00800 }
00801 
00802 ErrorCode Core::coords_iterate( Range::const_iterator iter, Range::const_iterator end, double*& xcoords_ptr,
00803                                 double*& ycoords_ptr, double*& zcoords_ptr, int& count )
00804 {
00805     EntitySequence* seq;
00806     ErrorCode rval = sequence_manager()->find( *iter, seq );
00807     if( MB_SUCCESS != rval )
00808     {
00809         xcoords_ptr = ycoords_ptr = zcoords_ptr = NULL;
00810         MB_SET_ERR( rval, "Couldn't find sequence for start handle" );
00811     }
00812     VertexSequence* vseq = dynamic_cast< VertexSequence* >( seq );
00813     if( !vseq ) { MB_SET_ERR( MB_ENTITY_NOT_FOUND, "Couldn't find sequence for start handle" ); }
00814 
00815     unsigned int offset = *iter - vseq->data()->start_handle();
00816     xcoords_ptr         = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 0 ) ) + offset;
00817     ycoords_ptr         = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 1 ) ) + offset;
00818     zcoords_ptr         = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 2 ) ) + offset;
00819 
00820     EntityHandle real_end = std::min( seq->end_handle(), *( iter.end_of_block() ) );
00821     if( *end ) real_end = std::min( real_end, *end );
00822     count = real_end - *iter + 1;
00823 
00824     return MB_SUCCESS;
00825 }
00826 
00827 ErrorCode Core::get_coords( const Range& entities, double* coords ) const
00828 {
00829     const TypeSequenceManager& vert_data = sequence_manager()->entity_map( MBVERTEX );
00830     TypeSequenceManager::const_iterator seq_iter;
00831 
00832     Range::const_pair_iterator i = entities.const_pair_begin();
00833     EntityHandle first           = i->first;
00834     while( i != entities.const_pair_end() && TYPE_FROM_HANDLE( i->first ) == MBVERTEX )
00835     {
00836 
00837         seq_iter = vert_data.lower_bound( first );
00838         if( seq_iter == vert_data.end() || first < ( *seq_iter )->start_handle() ) return MB_ENTITY_NOT_FOUND;
00839         const VertexSequence* vseq = reinterpret_cast< const VertexSequence* >( *seq_iter );
00840 
00841         EntityID offset = first - vseq->start_handle();
00842         EntityID count;
00843         if( i->second <= vseq->end_handle() )
00844         {
00845             count = i->second - first + 1;
00846             ++i;
00847             if( i != entities.const_pair_end() ) first = i->first;
00848         }
00849         else
00850         {
00851             count = vseq->end_handle() - first + 1;
00852             first = vseq->end_handle() + 1;
00853         }
00854 
00855         double const *x, *y, *z;
00856         ErrorCode rval = vseq->get_coordinate_arrays( x, y, z );MB_CHK_ERR( rval );
00857         x += offset;
00858         y += offset;
00859         z += offset;
00860         for( EntityID j = 0; j < count; ++j )
00861         {
00862             coords[3 * j]     = x[j];
00863             coords[3 * j + 1] = y[j];
00864             coords[3 * j + 2] = z[j];
00865         }
00866         coords = &coords[3 * count];
00867     }
00868 
00869     // for non-vertices...
00870     ErrorCode rval = MB_SUCCESS;
00871     for( Range::const_iterator rit( &( *i ), i->first ); rit != entities.end(); ++rit )
00872     {
00873         rval = get_coords( &( *rit ), 1, coords );MB_CHK_ERR( rval );
00874         coords += 3;
00875     }
00876 
00877     return rval;
00878 }
00879 
00880 /**\author Jason Kraftcheck <kraftche@cae.wisc.edu> - 2007-5-15 */
00881 ErrorCode Core::get_coords( const Range& entities, double* x_coords, double* y_coords, double* z_coords ) const
00882 {
00883     const TypeSequenceManager& vert_data = sequence_manager()->entity_map( MBVERTEX );
00884     TypeSequenceManager::const_iterator seq_iter;
00885 
00886     Range::const_pair_iterator i = entities.const_pair_begin();
00887     EntityHandle first           = i->first;
00888     while( i != entities.const_pair_end() && TYPE_FROM_HANDLE( i->first ) == MBVERTEX )
00889     {
00890 
00891         seq_iter = vert_data.lower_bound( first );
00892         if( seq_iter == vert_data.end() || first < ( *seq_iter )->start_handle() ) return MB_ENTITY_NOT_FOUND;
00893         const VertexSequence* vseq = reinterpret_cast< const VertexSequence* >( *seq_iter );
00894 
00895         EntityID offset = first - vseq->start_handle();
00896         EntityID count;
00897         if( i->second <= vseq->end_handle() )
00898         {
00899             count = i->second - first + 1;
00900             ++i;
00901             if( i != entities.const_pair_end() ) first = i->first;
00902         }
00903         else
00904         {
00905             count = vseq->end_handle() - first + 1;
00906             first = vseq->end_handle() + 1;
00907         }
00908 
00909         double const *x, *y, *z;
00910         ErrorCode rval = vseq->get_coordinate_arrays( x, y, z );MB_CHK_ERR( rval );
00911         if( x_coords )
00912         {
00913             memcpy( x_coords, x + offset, count * sizeof( double ) );
00914             x_coords += count;
00915         }
00916         if( y_coords )
00917         {
00918             memcpy( y_coords, y + offset, count * sizeof( double ) );
00919             y_coords += count;
00920         }
00921         if( z_coords )
00922         {
00923             memcpy( z_coords, z + offset, count * sizeof( double ) );
00924             z_coords += count;
00925         }
00926     }
00927 
00928     // for non-vertices...
00929     ErrorCode rval = MB_SUCCESS;
00930     double xyz[3];
00931     for( Range::const_iterator rit( &( *i ), i->first ); rit != entities.end(); ++rit )
00932     {
00933         rval = get_coords( &( *rit ), 1, xyz );MB_CHK_ERR( rval );
00934         *x_coords++ = xyz[0];
00935         *y_coords++ = xyz[1];
00936         *z_coords++ = xyz[2];
00937     }
00938 
00939     return rval;
00940 }
00941 
00942 ErrorCode Core::get_coords( const EntityHandle* entities, const int num_entities, double* coords ) const
00943 {
00944     const EntitySequence* seq     = NULL;
00945     const VertexSequence* vseq    = NULL;
00946     const EntityHandle* const end = entities + num_entities;
00947     const EntityHandle* iter      = entities;
00948     ErrorCode status              = MB_SUCCESS;
00949 
00950     while( iter != end )
00951     {
00952         if( TYPE_FROM_HANDLE( *iter ) == MBVERTEX )
00953         {
00954             if( !seq )
00955             {
00956                 seq  = sequence_manager()->get_last_accessed_sequence( MBVERTEX );
00957                 vseq = static_cast< const VertexSequence* >( seq );
00958             }
00959             if( !vseq )
00960                 return MB_ENTITY_NOT_FOUND;
00961             else if( vseq->start_handle() > *iter || vseq->end_handle() < *iter )
00962             {
00963                 if( MB_SUCCESS != sequence_manager()->find( *iter, seq ) ) return MB_ENTITY_NOT_FOUND;
00964                 vseq = static_cast< const VertexSequence* >( seq );
00965             }
00966             vseq->get_coordinates( *iter, coords );
00967         }
00968         else
00969         {
00970             static std::vector< EntityHandle > dum_conn( CN::MAX_NODES_PER_ELEMENT );
00971             static std::vector< double > dum_pos( 3 * CN::MAX_NODES_PER_ELEMENT );
00972             static const EntityHandle* conn;
00973             static int num_conn;
00974             status = get_connectivity( *iter, conn, num_conn, false, &dum_conn );MB_CHK_ERR( status );
00975             status = get_coords( conn, num_conn, &dum_pos[0] );MB_CHK_ERR( status );
00976             coords[0] = coords[1] = coords[2] = 0.0;
00977             for( int i = 0; i < num_conn; i++ )
00978             {
00979                 coords[0] += dum_pos[3 * i];
00980                 coords[1] += dum_pos[3 * i + 1];
00981                 coords[2] += dum_pos[3 * i + 2];
00982             }
00983             coords[0] /= num_conn;
00984             coords[1] /= num_conn;
00985             coords[2] /= num_conn;
00986         }
00987         coords += 3;
00988         ++iter;
00989     }
00990 
00991     return status;
00992 }
00993 
00994 ErrorCode Core::get_coords( const EntityHandle entity_handle, const double*& x, const double*& y,
00995                             const double*& z ) const
00996 {
00997     ErrorCode status = MB_TYPE_OUT_OF_RANGE;
00998 
00999     if( TYPE_FROM_HANDLE( entity_handle ) == MBVERTEX )
01000     {
01001         const EntitySequence* seq = 0;
01002         status                    = sequence_manager()->find( entity_handle, seq );
01003 
01004         if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
01005 
01006         status = static_cast< const VertexSequence* >( seq )->get_coordinates_ref( entity_handle, x, y, z );
01007     }
01008 
01009     return status;
01010 }
01011 
01012 //! set the coordinate information for this handle if it is of type Vertex
01013 //! otherwise, return an error
01014 ErrorCode Core::set_coords( const EntityHandle* entity_handles, const int num_entities, const double* coords )
01015 {
01016 
01017     ErrorCode status = MB_SUCCESS;
01018 
01019     int i, j = 0;
01020 
01021     for( i = 0; i < num_entities; i++ )
01022     {
01023         if( TYPE_FROM_HANDLE( entity_handles[i] ) == MBVERTEX )
01024         {
01025             EntitySequence* seq = 0;
01026             status              = sequence_manager()->find( entity_handles[i], seq );
01027 
01028             if( seq != 0 && status == MB_SUCCESS )
01029             {
01030                 status = static_cast< VertexSequence* >( seq )->set_coordinates( entity_handles[i], coords[j],
01031                                                                                  coords[j + 1], coords[j + 2] );
01032                 j += 3;
01033             }
01034         }
01035         else if( status == MB_SUCCESS )
01036             status = MB_TYPE_OUT_OF_RANGE;
01037     }
01038 
01039     return status;
01040 }
01041 
01042 //! set the coordinate information for this handle if it is of type Vertex
01043 //! otherwise, return an error
01044 ErrorCode Core::set_coords( Range entity_handles, const double* coords )
01045 {
01046 
01047     ErrorCode status = MB_SUCCESS;
01048 
01049     int j = 0;
01050 
01051     for( Range::iterator rit = entity_handles.begin(); rit != entity_handles.end(); ++rit )
01052     {
01053         if( TYPE_FROM_HANDLE( *rit ) == MBVERTEX )
01054         {
01055             EntitySequence* seq = 0;
01056             status              = sequence_manager()->find( *rit, seq );
01057 
01058             if( seq != 0 && status == MB_SUCCESS )
01059             {
01060                 status = static_cast< VertexSequence* >( seq )->set_coordinates( *rit, coords[j], coords[j + 1],
01061                                                                                  coords[j + 2] );
01062                 j += 3;
01063             }
01064         }
01065         else if( status == MB_SUCCESS )
01066             status = MB_TYPE_OUT_OF_RANGE;
01067     }
01068 
01069     return status;
01070 }
01071 
01072 double Core::get_sequence_multiplier() const
01073 {
01074     return sequenceManager->get_sequence_multiplier();
01075 }
01076 
01077 void Core::set_sequence_multiplier( double factor )
01078 {
01079     assert( factor >= 1.0 );
01080     sequenceManager->set_sequence_multiplier( factor );
01081 }
01082 
01083 //! get global connectivity array for specified entity type
01084 /**  Assumes just vertices, no higher order nodes
01085  */
01086 ErrorCode Core::get_connectivity_by_type( const EntityType entity_type, std::vector< EntityHandle >& connect ) const
01087 {
01088     // inefficient implementation until we get blocked tag access
01089 
01090     // get the range of entities of this type
01091     Range this_range;
01092     ErrorCode result = get_entities_by_type( 0, entity_type, this_range );
01093 
01094     int num_ents = this_range.size();
01095     connect.reserve( num_ents * CN::VerticesPerEntity( entity_type ) );
01096 
01097     // now loop over these entities, getting connectivity for each
01098     for( Range::iterator this_it = this_range.begin(); this_it != this_range.end(); ++this_it )
01099     {
01100         const EntityHandle* connect_vec = NULL;
01101         result                          = get_connectivity( *this_it, connect_vec, num_ents, true );MB_CHK_ERR( result );
01102         connect.insert( connect.end(), &connect_vec[0], &connect_vec[num_ents] );
01103     }
01104 
01105     return MB_SUCCESS;
01106 }
01107 
01108 //! get the connectivity for element /handles.  For non-element handles, return an error
01109 ErrorCode Core::get_connectivity( const EntityHandle* entity_handles, const int num_handles, Range& connectivity,
01110                                   bool corners_only ) const
01111 {
01112     std::vector< EntityHandle > tmp_connect;
01113     ErrorCode result = get_connectivity( entity_handles, num_handles, tmp_connect, corners_only );MB_CHK_ERR( result );
01114 
01115     std::sort( tmp_connect.begin(), tmp_connect.end() );
01116     std::copy( tmp_connect.rbegin(), tmp_connect.rend(), range_inserter( connectivity ) );
01117     return result;
01118 }
01119 
01120 //! get the connectivity for element /handles.  For non-element handles, return an error
01121 ErrorCode Core::get_connectivity( const EntityHandle* entity_handles, const int num_handles,
01122                                   std::vector< EntityHandle >& connectivity, bool corners_only,
01123                                   std::vector< int >* offsets ) const
01124 {
01125     connectivity.clear();  // this seems wrong as compared to other API functions,
01126                            // but changing it breaks lost of code, so I'm leaving
01127                            // it in.  - j.kraftcheck 2009-11-06
01128 
01129     ErrorCode rval;
01130     std::vector< EntityHandle > tmp_storage;  // used only for structured mesh
01131     const EntityHandle* conn;
01132     int len;
01133     if( offsets ) offsets->push_back( 0 );
01134     for( int i = 0; i < num_handles; ++i )
01135     {
01136         rval = get_connectivity( entity_handles[i], conn, len, corners_only, &tmp_storage );MB_CHK_ERR( rval );
01137         connectivity.insert( connectivity.end(), conn, conn + len );
01138         if( offsets ) offsets->push_back( connectivity.size() );
01139     }
01140     return MB_SUCCESS;
01141 }
01142 
01143 //! get the connectivity for element handles.  For non-element handles, return an error
01144 ErrorCode Core::get_connectivity( const EntityHandle entity_handle, const EntityHandle*& connectivity,
01145                                   int& number_nodes, bool corners_only, std::vector< EntityHandle >* storage ) const
01146 {
01147     ErrorCode status;
01148 
01149     // Make sure the entity should have a connectivity.
01150     EntityType entity_type = TYPE_FROM_HANDLE( entity_handle );
01151 
01152     // WARNING: This is very dependent on the ordering of the EntityType enum
01153     if( entity_type < MBVERTEX || entity_type >= MBENTITYSET )
01154         return MB_TYPE_OUT_OF_RANGE;
01155 
01156     else if( entity_type == MBVERTEX )
01157     {
01158         return MB_FAILURE;
01159     }
01160 
01161     const EntitySequence* seq = 0;
01162 
01163     // We know that connectivity is stored in an EntitySequence so jump straight
01164     // to the entity sequence
01165     status = sequence_manager()->find( entity_handle, seq );
01166     if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
01167 
01168     return static_cast< const ElementSequence* >( seq )->get_connectivity( entity_handle, connectivity, number_nodes,
01169                                                                            corners_only, storage );
01170 }
01171 
01172 //! set the connectivity for element handles.  For non-element handles, return an error
01173 ErrorCode Core::set_connectivity( const EntityHandle entity_handle, EntityHandle* connect, const int num_connect )
01174 {
01175     ErrorCode status = MB_FAILURE;
01176 
01177     // Make sure the entity should have a connectivity.
01178     // WARNING: This is very dependent on the ordering of the EntityType enum
01179     EntityType entity_type = TYPE_FROM_HANDLE( entity_handle );
01180 
01181     EntitySequence* seq = 0;
01182 
01183     if( entity_type < MBVERTEX || entity_type > MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
01184 
01185     status = sequence_manager()->find( entity_handle, seq );
01186     if( seq == 0 || status != MB_SUCCESS ) return ( status != MB_SUCCESS ? status : MB_ENTITY_NOT_FOUND );
01187 
01188     const EntityHandle* old_conn;
01189     int len;
01190     status = static_cast< ElementSequence* >( seq )->get_connectivity( entity_handle, old_conn, len );MB_CHK_ERR( status );
01191 
01192     aEntityFactory->notify_change_connectivity( entity_handle, old_conn, connect, num_connect );
01193 
01194     status = static_cast< ElementSequence* >( seq )->set_connectivity( entity_handle, connect, num_connect );
01195     if( status != MB_SUCCESS )
01196         aEntityFactory->notify_change_connectivity( entity_handle, connect, old_conn, num_connect );
01197 
01198     return status;
01199 }
01200 
01201 template < typename ITER >
01202 static inline ErrorCode get_adjacencies_union( Core* gMB, ITER begin, ITER end, int to_dimension,
01203                                                bool create_if_missing, Range& adj_entities )
01204 {
01205     const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000;
01206     const size_t MAX_OUTER_ITERATIONS    = 100;
01207 
01208     std::vector< EntityHandle > temp_vec, storage;
01209     std::vector< EntityHandle >::const_iterator ti;
01210     ErrorCode result = MB_SUCCESS, tmp_result;
01211     ITER i           = begin;
01212     Range::iterator ins;
01213     const EntityHandle* conn;
01214     int conn_len;
01215 
01216     // Just copy any vertices from the input range into the output
01217     size_t remaining = end - begin;
01218     assert( begin + remaining == end );
01219 
01220     // How many entities to work with at once? 2000 or so shouldn't require
01221     // too much memory, but don't iterate in outer loop more than a
01222     // 1000 times (make it bigger if many input entiites.)
01223     const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining / MAX_OUTER_ITERATIONS );
01224     while( remaining > 0 )
01225     {
01226         const size_t count = remaining > block_size ? block_size : remaining;
01227         remaining -= count;
01228         temp_vec.clear();
01229         for( size_t j = 0; j < count; ++i, ++j )
01230         {
01231             if( CN::Dimension( TYPE_FROM_HANDLE( *i ) ) == to_dimension ) { temp_vec.push_back( *i ); }
01232             else if( to_dimension == 0 && TYPE_FROM_HANDLE( *i ) != MBPOLYHEDRON )
01233             {
01234                 tmp_result = gMB->get_connectivity( *i, conn, conn_len, false, &storage );
01235                 if( MB_SUCCESS != tmp_result )
01236                 {
01237                     result = tmp_result;
01238                     continue;
01239                 }
01240                 temp_vec.insert( temp_vec.end(), conn, conn + conn_len );
01241             }
01242             else
01243             {
01244                 tmp_result = gMB->a_entity_factory()->get_adjacencies( *i, to_dimension, create_if_missing, temp_vec );
01245                 if( MB_SUCCESS != tmp_result )
01246                 {
01247                     result = tmp_result;
01248                     continue;
01249                 }
01250             }
01251         }
01252 
01253         std::sort( temp_vec.begin(), temp_vec.end() );
01254         ins = adj_entities.begin();
01255         ti  = temp_vec.begin();
01256         while( ti != temp_vec.end() )
01257         {
01258             EntityHandle first  = *ti;
01259             EntityHandle second = *ti;
01260             for( ++ti; ti != temp_vec.end() && ( *ti - second <= 1 ); ++ti )
01261                 second = *ti;
01262             ins = adj_entities.insert( ins, first, second );
01263         }
01264     }
01265     return result;
01266 }
01267 
01268 template < typename ITER >
01269 static inline ErrorCode get_adjacencies_intersection( Core* mb, ITER begin, ITER end, const int to_dimension,
01270                                                       const bool create_if_missing,
01271                                                       std::vector< EntityHandle >& adj_entities )
01272 {
01273     const size_t SORT_THRESHOLD = 200;
01274     std::vector< EntityHandle > temp_vec;
01275     std::vector< EntityHandle >::iterator adj_it, w_it;
01276     ErrorCode result = MB_SUCCESS;
01277 
01278     if( begin == end )
01279     {
01280         adj_entities.clear();  // intersection
01281         return MB_SUCCESS;
01282     }
01283 
01284     // First iteration is a special case if input list is empty.
01285     // Rather than returning nothing (intersecting with empty
01286     // input list), we begin with the adjacencies for the first entity.
01287     if( adj_entities.empty() )
01288     {
01289         EntityType entity_type = TYPE_FROM_HANDLE( *begin );
01290         if( to_dimension == CN::Dimension( entity_type ) )
01291             adj_entities.push_back( *begin );
01292         else if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
01293         {
01294             result = mb->get_connectivity( &( *begin ), 1, adj_entities );MB_CHK_ERR( result );
01295         }
01296         else
01297         {
01298             result = mb->a_entity_factory()->get_adjacencies( *begin, to_dimension, create_if_missing, adj_entities );MB_CHK_ERR( result );
01299         }
01300         ++begin;
01301     }
01302 
01303     for( ITER from_it = begin; from_it != end; ++from_it )
01304     {
01305         // running results kept in adj_entities; clear temp_vec, which is working space
01306         temp_vec.clear();
01307 
01308         // get the next set of adjacencies
01309         EntityType entity_type = TYPE_FROM_HANDLE( *from_it );
01310         if( to_dimension == CN::Dimension( entity_type ) )
01311             temp_vec.push_back( *from_it );
01312         else if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
01313         {
01314             result = mb->get_connectivity( &( *from_it ), 1, temp_vec );MB_CHK_ERR( result );
01315         }
01316         else
01317         {
01318             result = mb->a_entity_factory()->get_adjacencies( *from_it, to_dimension, create_if_missing, temp_vec );MB_CHK_ERR( result );
01319         }
01320 
01321         // otherwise intersect with the current set of results
01322         w_it = adj_it = adj_entities.begin();
01323         if( temp_vec.size() * adj_entities.size() < SORT_THRESHOLD )
01324         {
01325             for( ; adj_it != adj_entities.end(); ++adj_it )
01326                 if( std::find( temp_vec.begin(), temp_vec.end(), *adj_it ) != temp_vec.end() )
01327                 {
01328                     *w_it = *adj_it;
01329                     ++w_it;
01330                 }
01331         }
01332         else
01333         {
01334             std::sort( temp_vec.begin(), temp_vec.end() );
01335             for( ; adj_it != adj_entities.end(); ++adj_it )
01336                 if( std::binary_search( temp_vec.begin(), temp_vec.end(), *adj_it ) )
01337                 {
01338                     *w_it = *adj_it;
01339                     ++w_it;
01340                 }
01341         }
01342         adj_entities.erase( w_it, adj_entities.end() );
01343 
01344         // we're intersecting, so if there are no more results, we're done
01345         if( adj_entities.empty() ) break;
01346     }
01347 
01348     return MB_SUCCESS;
01349 }
01350 
01351 template < typename ITER >
01352 static inline ErrorCode get_adjacencies_intersection( Core* mb, ITER begin, ITER end, const int to_dimension,
01353                                                       const bool create_if_missing, Range& adj_entities )
01354 {
01355     std::vector< EntityHandle > results;
01356     ErrorCode rval = moab::get_adjacencies_intersection( mb, begin, end, to_dimension, create_if_missing, results );MB_CHK_ERR( rval );
01357 
01358     if( adj_entities.empty() )
01359     {
01360         std::copy( results.begin(), results.end(), range_inserter( adj_entities ) );
01361         return MB_SUCCESS;
01362     }
01363 
01364     Range::iterator it = adj_entities.begin();
01365     while( it != adj_entities.end() )
01366     {
01367         if( std::find( results.begin(), results.end(), *it ) == results.end() )
01368             it = adj_entities.erase( it );
01369         else
01370             ++it;
01371     }
01372     return MB_SUCCESS;
01373 }
01374 
01375 ///////////////////////////////////////////////////////////////////
01376 //////////////////////////////////////////
01377 #ifdef MOAB_HAVE_AHF
01378 
01379 template < typename ITER >
01380 static inline ErrorCode get_adjacencies_intersection_ahf( Core* mb, ITER begin, ITER end, const int to_dimension,
01381                                                           std::vector< EntityHandle >& adj_entities )
01382 {
01383     const size_t SORT_THRESHOLD = 200;
01384     std::vector< EntityHandle > temp_vec;
01385     std::vector< EntityHandle >::iterator adj_it, w_it;
01386     ErrorCode result = MB_SUCCESS;
01387 
01388     if( begin == end )
01389     {
01390         adj_entities.clear();  // intersection
01391         return MB_SUCCESS;
01392     }
01393 
01394     // First iteration is a special case if input list is empty.
01395     // Rather than returning nothing (intersecting with empty
01396     // input list), we begin with the adjacencies for the first entity.
01397     if( adj_entities.empty() )
01398     {
01399         EntityType entity_type = TYPE_FROM_HANDLE( *begin );
01400 
01401         if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
01402             result = mb->get_connectivity( &( *begin ), 1, adj_entities );
01403         else
01404             result = mb->a_half_facet_rep()->get_adjacencies( *begin, to_dimension, adj_entities );
01405         if( MB_SUCCESS != result ) return result;
01406         ++begin;
01407     }
01408 
01409     for( ITER from_it = begin; from_it != end; ++from_it )
01410     {
01411         // running results kept in adj_entities; clear temp_vec, which is working space
01412         temp_vec.clear();
01413 
01414         // get the next set of adjacencies
01415         EntityType entity_type = TYPE_FROM_HANDLE( *from_it );
01416         if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
01417             result = mb->get_connectivity( &( *from_it ), 1, temp_vec );
01418         else
01419             result = mb->a_half_facet_rep()->get_adjacencies( *from_it, to_dimension, temp_vec );
01420         if( MB_SUCCESS != result ) return result;
01421 
01422         // otherwise intersect with the current set of results
01423         w_it = adj_it = adj_entities.begin();
01424         if( temp_vec.size() * adj_entities.size() < SORT_THRESHOLD )
01425         {
01426             for( ; adj_it != adj_entities.end(); ++adj_it )
01427                 if( std::find( temp_vec.begin(), temp_vec.end(), *adj_it ) != temp_vec.end() )
01428                 {
01429                     *w_it = *adj_it;
01430                     ++w_it;
01431                 }
01432         }
01433         else
01434         {
01435             std::sort( temp_vec.begin(), temp_vec.end() );
01436             for( ; adj_it != adj_entities.end(); ++adj_it )
01437                 if( std::binary_search( temp_vec.begin(), temp_vec.end(), *adj_it ) )
01438                 {
01439                     *w_it = *adj_it;
01440                     ++w_it;
01441                 }
01442         }
01443         adj_entities.erase( w_it, adj_entities.end() );
01444 
01445         // we're intersecting, so if there are no more results, we're done
01446         if( adj_entities.empty() ) break;
01447     }
01448 
01449     return MB_SUCCESS;
01450 }
01451 #endif
01452 
01453 ///////////////////////////////////////////
01454 
01455 ErrorCode Core::get_adjacencies( const EntityHandle* from_entities, const int num_entities, const int to_dimension,
01456                                  const bool create_if_missing, std::vector< EntityHandle >& adj_entities,
01457                                  const int operation_type )
01458 {
01459 
01460 #ifdef MOAB_HAVE_AHF
01461     bool can_handle = true;
01462 
01463     if( to_dimension == 4 )
01464         can_handle = false;  // NOT SUPPORTED: meshsets
01465     else if( create_if_missing )
01466         can_handle = false;  // NOT SUPPORTED: create_if_missing
01467 
01468     bool mixed = ahfRep->check_mixed_entity_type();  // NOT SUPPORTED: mixed entity types or
01469                                                      // polygonal/hedrals types
01470     if( mixed ) can_handle = false;
01471 
01472     if( mesh_modified )  // NOT SUPPORTED: modified mesh
01473         can_handle = false;
01474 
01475     if( can_handle )
01476     {
01477         ErrorCode result;
01478         if( operation_type == Interface::INTERSECT )
01479             return get_adjacencies_intersection_ahf( this, from_entities, from_entities + num_entities, to_dimension,
01480                                                      adj_entities );
01481         else if( operation_type != Interface::UNION )
01482             return MB_FAILURE;
01483 
01484         // do union
01485 
01486         std::vector< EntityHandle > tmp_storage;
01487         const EntityHandle* conn;
01488         int len;
01489         for( int i = 0; i < num_entities; ++i )
01490         {
01491             if( to_dimension == 0 && TYPE_FROM_HANDLE( from_entities[0] ) != MBPOLYHEDRON )
01492             {
01493                 result = get_connectivity( from_entities[i], conn, len, false, &tmp_storage );
01494                 adj_entities.insert( adj_entities.end(), conn, conn + len );
01495                 if( MB_SUCCESS != result ) return result;
01496             }
01497             else
01498             {
01499                 result = ahfRep->get_adjacencies( from_entities[i], to_dimension, adj_entities );
01500                 if( MB_SUCCESS != result ) return result;
01501             }
01502         }
01503         std::sort( adj_entities.begin(), adj_entities.end() );
01504         adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() );
01505     }
01506     else
01507     {
01508 
01509 #endif
01510 
01511         if( operation_type == Interface::INTERSECT )
01512             return get_adjacencies_intersection( this, from_entities, from_entities + num_entities, to_dimension,
01513                                                  create_if_missing, adj_entities );
01514         else if( operation_type != Interface::UNION )
01515             return MB_FAILURE;
01516 
01517         // do union
01518         ErrorCode result;
01519         std::vector< EntityHandle > tmp_storage;
01520         const EntityHandle* conn;
01521         int len;
01522         for( int i = 0; i < num_entities; ++i )
01523         {
01524             if( to_dimension == 0 && TYPE_FROM_HANDLE( from_entities[0] ) != MBPOLYHEDRON )
01525             {
01526                 result = get_connectivity( from_entities[i], conn, len, false, &tmp_storage );MB_CHK_ERR( result );
01527                 adj_entities.insert( adj_entities.end(), conn, conn + len );
01528             }
01529             else
01530             {
01531                 result =
01532                     aEntityFactory->get_adjacencies( from_entities[i], to_dimension, create_if_missing, adj_entities );MB_CHK_ERR( result );
01533             }
01534         }
01535         std::sort( adj_entities.begin(), adj_entities.end() );
01536         adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() );
01537 
01538         // return MB_SUCCESS;
01539 
01540 #ifdef MOAB_HAVE_AHF
01541     }
01542 #endif
01543 
01544     return MB_SUCCESS;
01545 }
01546 
01547 ErrorCode Core::get_adjacencies( const EntityHandle* from_entities, const int num_entities, const int to_dimension,
01548                                  const bool create_if_missing, Range& adj_entities, const int operation_type )
01549 {
01550     if( operation_type == Interface::INTERSECT )
01551         return get_adjacencies_intersection( this, from_entities, from_entities + num_entities, to_dimension,
01552                                              create_if_missing, adj_entities );
01553     else if( operation_type == Interface::UNION )
01554         return get_adjacencies_union( this, from_entities, from_entities + num_entities, to_dimension,
01555                                       create_if_missing, adj_entities );
01556     else
01557         return MB_FAILURE;
01558 }
01559 
01560 ErrorCode Core::get_connectivity( const Range& from_entities, Range& adj_entities, bool corners_only ) const
01561 {
01562     const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000;
01563     const size_t MAX_OUTER_ITERATIONS    = 100;
01564 
01565     std::vector< EntityHandle > temp_vec, storage;
01566     std::vector< EntityHandle >::const_iterator ti;
01567     ErrorCode result        = MB_SUCCESS, tmp_result;
01568     Range::const_iterator i = from_entities.begin();
01569     Range::iterator ins;
01570     const EntityHandle* conn;
01571     int conn_len;
01572 
01573     // Just copy any vertices from the input range into the output
01574     size_t remaining = from_entities.size();
01575     for( ; i != from_entities.end() && TYPE_FROM_HANDLE( *i ) == MBVERTEX; ++i )
01576         --remaining;
01577     adj_entities.merge( from_entities.begin(), i );
01578 
01579     // How many entities to work with at once? 2000 or so shouldn't require
01580     // too much memory, but don't iterate in outer loop more than a
01581     // 1000 times (make it bigger if many input entiites.)
01582     const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining / MAX_OUTER_ITERATIONS );
01583     while( remaining > 0 )
01584     {
01585         const size_t count = remaining > block_size ? block_size : remaining;
01586         remaining -= count;
01587         temp_vec.clear();
01588         for( size_t j = 0; j < count; ++i, ++j )
01589         {
01590             tmp_result = get_connectivity( *i, conn, conn_len, corners_only, &storage );
01591             if( MB_SUCCESS != tmp_result )
01592             {
01593                 result = tmp_result;
01594                 continue;
01595             }
01596 
01597             const size_t oldsize = temp_vec.size();
01598             temp_vec.resize( oldsize + conn_len );
01599             memcpy( &temp_vec[oldsize], conn, sizeof( EntityHandle ) * conn_len );
01600         }
01601 
01602         std::sort( temp_vec.begin(), temp_vec.end() );
01603         ins = adj_entities.begin();
01604         ti  = temp_vec.begin();
01605         while( ti != temp_vec.end() )
01606         {
01607             EntityHandle first  = *ti;
01608             EntityHandle second = *ti;
01609             for( ++ti; ti != temp_vec.end() && ( *ti - second <= 1 ); ++ti )
01610                 second = *ti;
01611             ins = adj_entities.insert( ins, first, second );
01612         }
01613     }
01614     return result;
01615 }
01616 
01617 ErrorCode Core::connect_iterate( Range::const_iterator iter, Range::const_iterator end, EntityHandle*& connect,
01618                                  int& verts_per_entity, int& count )
01619 {
01620     // Make sure the entity should have a connectivity.
01621     EntityType entity_type = TYPE_FROM_HANDLE( *iter );
01622 
01623     // WARNING: This is very dependent on the ordering of the EntityType enum
01624     if( entity_type <= MBVERTEX || entity_type >= MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
01625 
01626     EntitySequence* seq = NULL;
01627 
01628     // We know that connectivity is stored in an EntitySequence so jump straight
01629     // to the entity sequence
01630     ErrorCode rval = sequence_manager()->find( *iter, seq );
01631     if( !seq || rval != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
01632 
01633     ElementSequence* eseq = dynamic_cast< ElementSequence* >( seq );
01634     assert( eseq != NULL );
01635 
01636     connect = eseq->get_connectivity_array();
01637     if( !connect ) { MB_SET_ERR( MB_FAILURE, "Couldn't find connectivity array for start handle" ); }
01638 
01639     connect += eseq->nodes_per_element() * ( *iter - eseq->start_handle() );
01640 
01641     EntityHandle real_end = std::min( eseq->end_handle(), *( iter.end_of_block() ) );
01642     if( *end ) real_end = std::min( real_end, *end );
01643     count = real_end - *iter + 1;
01644 
01645     verts_per_entity = eseq->nodes_per_element();
01646 
01647     return MB_SUCCESS;
01648 }
01649 
01650 ErrorCode Core::get_vertices( const Range& from_entities, Range& vertices )
01651 {
01652     Range range;
01653     ErrorCode rval = get_connectivity( from_entities, range );MB_CHK_ERR( rval );
01654 
01655     // If input contained polyhedra, connectivity will contain faces.
01656     // Get vertices from faces.
01657     if( !range.all_of_dimension( 0 ) )
01658     {
01659         Range::iterator it = range.upper_bound( MBVERTEX );
01660         Range polygons;
01661         polygons.merge( it, range.end() );
01662         range.erase( it, range.end() );
01663         rval = get_connectivity( polygons, range );MB_CHK_ERR( rval );
01664     }
01665 
01666     if( vertices.empty() )
01667         vertices.swap( range );
01668     else
01669         vertices.merge( range );
01670     return MB_SUCCESS;
01671 }
01672 
01673 ErrorCode Core::get_adjacencies( const Range& from_entities, const int to_dimension, const bool create_if_missing,
01674                                  Range& adj_entities, const int operation_type )
01675 {
01676     if( operation_type == Interface::INTERSECT )
01677         return get_adjacencies_intersection( this, from_entities.begin(), from_entities.end(), to_dimension,
01678                                              create_if_missing, adj_entities );
01679     else if( operation_type != Interface::UNION )
01680         return MB_FAILURE;
01681     else if( to_dimension == 0 )
01682         return get_vertices( from_entities, adj_entities );
01683     else
01684         return get_adjacencies_union( this, from_entities.begin(), from_entities.end(), to_dimension, create_if_missing,
01685                                       adj_entities );
01686 }
01687 
01688 ErrorCode Core::add_adjacencies( const EntityHandle entity_handle, const EntityHandle* adjacencies,
01689                                  const int num_handles, bool both_ways )
01690 {
01691     ErrorCode result = MB_SUCCESS;
01692 
01693     for( const EntityHandle* it = adjacencies; it != adjacencies + num_handles; it++ )
01694     {
01695         result = aEntityFactory->add_adjacency( entity_handle, *it, both_ways );MB_CHK_ERR( result );
01696     }
01697 
01698     return MB_SUCCESS;
01699 }
01700 
01701 ErrorCode Core::add_adjacencies( const EntityHandle entity_handle, Range& adjacencies, bool both_ways )
01702 {
01703     ErrorCode result = MB_SUCCESS;
01704 
01705     for( Range::iterator rit = adjacencies.begin(); rit != adjacencies.end(); ++rit )
01706     {
01707         result = aEntityFactory->add_adjacency( entity_handle, *rit, both_ways );MB_CHK_ERR( result );
01708     }
01709 
01710     return MB_SUCCESS;
01711 }
01712 
01713 ErrorCode Core::remove_adjacencies( const EntityHandle entity_handle, const EntityHandle* adjacencies,
01714                                     const int num_handles )
01715 {
01716     ErrorCode result = MB_SUCCESS;
01717 
01718     for( const EntityHandle* it = adjacencies; it != adjacencies + num_handles; it++ )
01719     {
01720         result = aEntityFactory->remove_adjacency( entity_handle, *it );MB_CHK_ERR( result );
01721         result = aEntityFactory->remove_adjacency( *it, entity_handle );MB_CHK_ERR( result );
01722     }
01723 
01724     return MB_SUCCESS;
01725 }
01726 
01727 ErrorCode Core::adjacencies_iterate( Range::const_iterator iter, Range::const_iterator end,
01728                                      const std::vector< EntityHandle >**& adjs_ptr, int& count )
01729 {
01730     // Make sure the entity should have a connectivity.
01731     EntityType entity_type = TYPE_FROM_HANDLE( *iter );
01732 
01733     // WARNING: This is very dependent on the ordering of the EntityType enum
01734     if( entity_type < MBVERTEX || entity_type > MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
01735 
01736     EntitySequence* seq = NULL;
01737 
01738     // We know that connectivity is stored in an EntitySequence so jump straight
01739     // to the entity sequence
01740     ErrorCode rval = sequence_manager()->find( *iter, seq );
01741     if( !seq || rval != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
01742 
01743     adjs_ptr = const_cast< const std::vector< EntityHandle >** >( seq->data()->get_adjacency_data() );
01744     if( !adjs_ptr ) return rval;
01745 
01746     adjs_ptr += *iter - seq->data()->start_handle();
01747 
01748     EntityHandle real_end = *( iter.end_of_block() );
01749     if( *end ) real_end = std::min( real_end, *end );
01750     count = real_end - *iter + 1;
01751 
01752     return MB_SUCCESS;
01753 }
01754 
01755 ErrorCode Core::get_entities_by_dimension( const EntityHandle meshset, const int dimension, Range& entities,
01756                                            const bool recursive ) const
01757 {
01758     ErrorCode result = MB_SUCCESS;
01759     if( meshset )
01760     {
01761         const EntitySequence* seq;
01762         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01763         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01764         result = mseq->get_dimension( sequence_manager(), meshset, dimension, entities, recursive );MB_CHK_ERR( result );
01765     }
01766     else if( dimension > 3 )
01767     {
01768         sequence_manager()->get_entities( MBENTITYSET, entities );
01769     }
01770     else
01771     {
01772         for( EntityType this_type = CN::TypeDimensionMap[dimension].first;
01773              this_type <= CN::TypeDimensionMap[dimension].second; this_type++ )
01774         {
01775             sequence_manager()->get_entities( this_type, entities );
01776         }
01777     }
01778 
01779     return MB_SUCCESS;
01780 }
01781 
01782 ErrorCode Core::get_entities_by_dimension( const EntityHandle meshset, const int dimension,
01783                                            std::vector< EntityHandle >& entities, const bool recursive ) const
01784 {
01785     ErrorCode result = MB_SUCCESS;
01786     if( meshset )
01787     {
01788         const EntitySequence* seq;
01789         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01790         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01791         result = mseq->get_dimension( sequence_manager(), meshset, dimension, entities, recursive );MB_CHK_ERR( result );
01792     }
01793     else if( dimension > 3 )
01794     {
01795         sequence_manager()->get_entities( MBENTITYSET, entities );
01796     }
01797     else
01798     {
01799         for( EntityType this_type = CN::TypeDimensionMap[dimension].first;
01800              this_type <= CN::TypeDimensionMap[dimension].second; this_type++ )
01801         {
01802             sequence_manager()->get_entities( this_type, entities );
01803         }
01804     }
01805 
01806     return MB_SUCCESS;
01807 }
01808 
01809 ErrorCode Core::get_entities_by_type( const EntityHandle meshset, const EntityType entity_type, Range& entities,
01810                                       const bool recursive ) const
01811 {
01812     ErrorCode result = MB_SUCCESS;
01813     if( meshset )
01814     {
01815         const EntitySequence* seq;
01816         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01817         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01818         result                      = mseq->get_type( sequence_manager(), meshset, entity_type, entities, recursive );MB_CHK_ERR( result );
01819     }
01820     else
01821     {
01822         sequence_manager()->get_entities( entity_type, entities );
01823     }
01824 
01825     return MB_SUCCESS;
01826 }
01827 
01828 ErrorCode Core::get_entities_by_type( const EntityHandle meshset, const EntityType entity_type,
01829                                       std::vector< EntityHandle >& entities, const bool recursive ) const
01830 {
01831     ErrorCode result = MB_SUCCESS;
01832     if( meshset )
01833     {
01834         const EntitySequence* seq;
01835         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01836         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01837         result                      = mseq->get_type( sequence_manager(), meshset, entity_type, entities, recursive );MB_CHK_ERR( result );
01838     }
01839     else
01840     {
01841         sequence_manager()->get_entities( entity_type, entities );
01842     }
01843 
01844     return MB_SUCCESS;
01845 }
01846 
01847 ErrorCode Core::get_entities_by_type_and_tag( const EntityHandle meshset, const EntityType entity_type, const Tag* tags,
01848                                               const void* const* values, const int num_tags, Range& entities,
01849                                               const int condition, const bool recursive ) const
01850 {
01851     ErrorCode result;
01852     Range range;
01853 
01854     result = get_entities_by_type( meshset, entity_type, range, recursive );MB_CHK_ERR( result );
01855     if( !entities.empty() && Interface::INTERSECT == condition ) range = intersect( entities, range );
01856 
01857     // For each tag:
01858     //  if operation is INTERSECT remove from 'range' any non-tagged entities
01859     //  if operation is UNION add to 'entities' any tagged entities
01860     for( int it = 0; it < num_tags && !range.empty(); it++ )
01861     {
01862         if( !valid_tag_handle( tags[it] ) ) return MB_TAG_NOT_FOUND;
01863 
01864         // Of the entities in 'range', put in 'tmp_range' the subset
01865         // that are tagged as requested for this tag.
01866         Range tmp_range;
01867 
01868         // get the entities with this tag/value combo
01869         if( NULL == values || NULL == values[it] )
01870         {
01871             result = tags[it]->get_tagged_entities( sequenceManager, tmp_range, entity_type, &range );MB_CHK_ERR( result );
01872         }
01873         else
01874         {
01875             result = tags[it]->find_entities_with_value( sequenceManager, mError, tmp_range, values[it], 0, entity_type,
01876                                                          &range );MB_CHK_ERR( result );
01877             // if there is a default value, then we should return all entities
01878             // that are untagged
01879             if( tags[it]->equals_default_value( values[it] ) )
01880             {
01881                 Range all_tagged, untagged;
01882                 result = tags[it]->get_tagged_entities( sequenceManager, all_tagged, entity_type, &range );MB_CHK_ERR( result );
01883                 // add to 'tmp_range' any untagged entities in 'range'
01884                 tmp_range.merge( subtract( range, all_tagged ) );
01885             }
01886         }
01887 
01888         // The above calls should have already done the intersect for us.
01889         if( Interface::INTERSECT == condition )
01890             range.swap( tmp_range );
01891         else
01892             entities.merge( tmp_range );
01893     }
01894 
01895     if( Interface::INTERSECT == condition ) entities.swap( range );
01896 
01897     return MB_SUCCESS;
01898 }
01899 
01900 ErrorCode Core::get_entities_by_handle( const EntityHandle meshset, Range& entities, const bool recursive ) const
01901 {
01902     ErrorCode result = MB_SUCCESS;
01903     if( meshset )
01904     {
01905         const EntitySequence* seq;
01906         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01907         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01908         result                      = mseq->get_entities( sequence_manager(), meshset, entities, recursive );MB_CHK_ERR( result );
01909     }
01910     else
01911     {
01912         // iterate backwards so range insertion is quicker
01913         for( EntityType entity_type = MBENTITYSET; entity_type >= MBVERTEX; --entity_type )
01914             sequence_manager()->get_entities( entity_type, entities );
01915     }
01916 
01917     return MB_SUCCESS;
01918 }
01919 
01920 ErrorCode Core::get_entities_by_handle( const EntityHandle meshset, std::vector< EntityHandle >& entities,
01921                                         const bool recursive ) const
01922 {
01923     ErrorCode result;
01924     if( recursive || !meshset )
01925     {
01926         Range tmp_range;
01927         result        = get_entities_by_handle( meshset, tmp_range, recursive );
01928         size_t offset = entities.size();
01929         entities.resize( offset + tmp_range.size() );
01930         std::copy( tmp_range.begin(), tmp_range.end(), entities.begin() + offset );
01931     }
01932     else
01933     {
01934         const EntitySequence* seq;
01935         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01936         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01937         result                      = mseq->get_entities( meshset, entities );MB_CHK_ERR( result );
01938     }
01939     return MB_SUCCESS;
01940 }
01941 
01942 //! get # entities of a given dimension
01943 ErrorCode Core::get_number_entities_by_dimension( const EntityHandle meshset, const int dim, int& number,
01944                                                   const bool recursive ) const
01945 {
01946     ErrorCode result = MB_SUCCESS;
01947 
01948     if( !meshset )
01949     {
01950         number = 0;
01951         for( EntityType this_type = CN::TypeDimensionMap[dim].first; this_type <= CN::TypeDimensionMap[dim].second;
01952              this_type++ )
01953         {
01954             number += sequence_manager()->get_number_entities( this_type );
01955         }
01956     }
01957     else
01958     {
01959         const EntitySequence* seq;
01960         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01961         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01962         result                      = mseq->num_dimension( sequence_manager(), meshset, dim, number, recursive );MB_CHK_ERR( result );
01963     }
01964 
01965     return MB_SUCCESS;
01966 }
01967 
01968 //! returns the number of entities with a given type and tag
01969 ErrorCode Core::get_number_entities_by_type( const EntityHandle meshset, const EntityType entity_type, int& num_ent,
01970                                              const bool recursive ) const
01971 {
01972     ErrorCode result = MB_SUCCESS;
01973 
01974     if( recursive && entity_type == MBENTITYSET )  // will never return anything
01975         return MB_TYPE_OUT_OF_RANGE;
01976 
01977     if( meshset )
01978     {
01979         const EntitySequence* seq;
01980         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
01981         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
01982         result                      = mseq->num_type( sequence_manager(), meshset, entity_type, num_ent, recursive );MB_CHK_ERR( result );
01983     }
01984     else
01985     {
01986         num_ent = sequence_manager()->get_number_entities( entity_type );
01987     }
01988 
01989     return MB_SUCCESS;
01990 }
01991 
01992 ErrorCode Core::get_number_entities_by_type_and_tag( const EntityHandle meshset, const EntityType entity_type,
01993                                                      const Tag* tag_handles, const void* const* values,
01994                                                      const int num_tags, int& num_entities, int condition,
01995                                                      const bool recursive ) const
01996 {
01997     Range dum_ents;
01998     ErrorCode result = get_entities_by_type_and_tag( meshset, entity_type, tag_handles, values, num_tags, dum_ents,
01999                                                      condition, recursive );
02000     num_entities     = dum_ents.size();
02001     return result;
02002 }
02003 
02004 ErrorCode Core::get_number_entities_by_handle( const EntityHandle meshset, int& num_ent, const bool recursive ) const
02005 {
02006     ErrorCode result;
02007     if( meshset )
02008     {
02009         const EntitySequence* seq;
02010         result = sequence_manager()->find( meshset, seq );MB_CHK_ERR( result );
02011         const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
02012         return mseq->num_entities( sequence_manager(), meshset, num_ent, recursive );
02013     }
02014 
02015     num_ent = 0;
02016     for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
02017     {
02018         int dummy = 0;
02019         result    = get_number_entities_by_type( 0, this_type, dummy );
02020         if( result != MB_SUCCESS )
02021         {
02022             num_ent = 0;
02023             return result;
02024         }
02025         num_ent += dummy;
02026     }
02027 
02028     return MB_SUCCESS;
02029 }
02030 
02031 //! return the tag data for a given EntityHandle and Tag
02032 ErrorCode Core::tag_get_data( const Tag tag_handle, const EntityHandle* entity_handles, int num_entities,
02033                               void* tag_data ) const
02034 {
02035     assert( valid_tag_handle( tag_handle ) );
02036     CHECK_MESH_NULL
02037     return tag_handle->get_data( sequenceManager, mError, entity_handles, num_entities, tag_data );
02038 }
02039 
02040 //! return the tag data for a given EntityHandle and Tag
02041 ErrorCode Core::tag_get_data( const Tag tag_handle, const Range& entity_handles, void* tag_data ) const
02042 {
02043     assert( valid_tag_handle( tag_handle ) );
02044     return tag_handle->get_data( sequenceManager, mError, entity_handles, tag_data );
02045 }
02046 
02047 //! set the data  for given EntityHandles and Tag
02048 ErrorCode Core::tag_set_data( Tag tag_handle, const EntityHandle* entity_handles, int num_entities,
02049                               const void* tag_data )
02050 {
02051     assert( valid_tag_handle( tag_handle ) );
02052     CHECK_MESH_NULL
02053     return tag_handle->set_data( sequenceManager, mError, entity_handles, num_entities, tag_data );
02054 }
02055 
02056 //! set the data  for given EntityHandles and Tag
02057 ErrorCode Core::tag_set_data( Tag tag_handle, const Range& entity_handles, const void* tag_data )
02058 {
02059     assert( valid_tag_handle( tag_handle ) );
02060     return tag_handle->set_data( sequenceManager, mError, entity_handles, tag_data );
02061 }
02062 
02063 //! return the tag data for a given EntityHandle and Tag
02064 ErrorCode Core::tag_get_by_ptr( const Tag tag_handle, const EntityHandle* entity_handles, int num_entities,
02065                                 const void** tag_data, int* tag_sizes ) const
02066 {
02067     assert( valid_tag_handle( tag_handle ) );
02068     CHECK_MESH_NULL
02069     ErrorCode result =
02070         tag_handle->get_data( sequenceManager, mError, entity_handles, num_entities, tag_data, tag_sizes );
02071     int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() );
02072     if( tag_sizes && typesize != 1 )
02073         for( int i = 0; i < num_entities; ++i )
02074             tag_sizes[i] /= typesize;
02075     return result;
02076 }
02077 
02078 //! return the tag data for a given EntityHandle and Tag
02079 ErrorCode Core::tag_get_by_ptr( const Tag tag_handle, const Range& entity_handles, const void** tag_data,
02080                                 int* tag_sizes ) const
02081 {
02082     assert( valid_tag_handle( tag_handle ) );
02083     ErrorCode result = tag_handle->get_data( sequenceManager, mError, entity_handles, tag_data, tag_sizes );
02084     int typesize     = TagInfo::size_from_data_type( tag_handle->get_data_type() );
02085     if( tag_sizes && typesize != 1 )
02086     {
02087         int num_entities = entity_handles.size();
02088         for( int i = 0; i < num_entities; ++i )
02089             tag_sizes[i] /= typesize;
02090     }
02091     return result;
02092 }
02093 
02094 //! set the data  for given EntityHandles and Tag
02095 ErrorCode Core::tag_set_by_ptr( Tag tag_handle, const EntityHandle* entity_handles, int num_entities,
02096                                 void const* const* tag_data, const int* tag_sizes )
02097 {
02098     assert( valid_tag_handle( tag_handle ) );
02099     CHECK_MESH_NULL
02100     std::vector< int > tmp_sizes;
02101     int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() );
02102     if( typesize != 1 && tag_sizes )
02103     {
02104         tmp_sizes.resize( num_entities );
02105         for( int i = 0; i < num_entities; ++i )
02106             tmp_sizes[i] = tag_sizes[i] * typesize;
02107         tag_sizes = &tmp_sizes[0];
02108     }
02109     return tag_handle->set_data( sequenceManager, mError, entity_handles, num_entities, tag_data, tag_sizes );
02110 }
02111 
02112 //! set the data  for given EntityHandles and Tag
02113 ErrorCode Core::tag_set_by_ptr( Tag tag_handle, const Range& entity_handles, void const* const* tag_data,
02114                                 const int* tag_sizes )
02115 {
02116     assert( valid_tag_handle( tag_handle ) );
02117     std::vector< int > tmp_sizes;
02118     int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() );
02119     if( typesize != 1 && tag_sizes )
02120     {
02121         int num_entities = entity_handles.size();
02122         tmp_sizes.resize( num_entities );
02123         for( int i = 0; i < num_entities; ++i )
02124             tmp_sizes[i] = tag_sizes[i] * typesize;
02125         tag_sizes = &tmp_sizes[0];
02126     }
02127     return tag_handle->set_data( sequenceManager, mError, entity_handles, tag_data, tag_sizes );
02128 }
02129 
02130 //! set the data  for given EntityHandles and Tag
02131 ErrorCode Core::tag_clear_data( Tag tag_handle, const EntityHandle* entity_handles, int num_entities,
02132                                 const void* tag_data, int tag_size )
02133 {
02134     assert( valid_tag_handle( tag_handle ) );
02135     CHECK_MESH_NULL
02136     return tag_handle->clear_data( sequenceManager, mError, entity_handles, num_entities, tag_data,
02137                                    tag_size * TagInfo::size_from_data_type( tag_handle->get_data_type() ) );
02138 }
02139 
02140 //! set the data  for given EntityHandles and Tag
02141 ErrorCode Core::tag_clear_data( Tag tag_handle, const Range& entity_handles, const void* tag_data, int tag_size )
02142 {
02143     assert( valid_tag_handle( tag_handle ) );
02144     return tag_handle->clear_data( sequenceManager, mError, entity_handles, tag_data,
02145                                    tag_size * TagInfo::size_from_data_type( tag_handle->get_data_type() ) );
02146 }
02147 
02148 static bool is_zero_bytes( const void* mem, size_t size )
02149 {
02150     const char* iter      = reinterpret_cast< const char* >( mem );
02151     const char* const end = iter + size;
02152     for( ; iter != end; ++iter )
02153         if( *iter ) return false;
02154     return true;
02155 }
02156 
02157 ErrorCode Core::tag_get_handle( const char* name, int size, DataType data_type, Tag& tag_handle, unsigned flags,
02158                                 const void* default_value, bool* created )
02159 {
02160     if( created ) *created = false;
02161 
02162     // we always work with sizes in bytes internally
02163     if( !( ( flags & MB_TAG_VARLEN ) && size == MB_VARIABLE_LENGTH ) )
02164     {
02165         if( flags & MB_TAG_BYTES )
02166         {
02167             if( size % TagInfo::size_from_data_type( data_type ) ) return MB_INVALID_SIZE;
02168         }
02169         else
02170         {
02171             size *= TagInfo::size_from_data_type( data_type );
02172         }
02173     }
02174 
02175     const TagType storage = static_cast< TagType >( flags & 3 );
02176 
02177     // search for an existing tag
02178     tag_handle = 0;
02179     if( name && *name )
02180     {  // not anonymous tag
02181         for( std::list< Tag >::iterator i = tagList.begin(); i != tagList.end(); ++i )
02182         {
02183             if( ( *i )->get_name() == name )
02184             {
02185                 tag_handle = *i;
02186                 break;
02187             }
02188         }
02189     }
02190 
02191     if( tag_handle )
02192     {
02193         if( flags & MB_TAG_EXCL ) return MB_ALREADY_ALLOCATED;
02194         // user asked that we not check anything
02195         if( flags & MB_TAG_ANY ) return MB_SUCCESS;
02196         // user asked that we also match storage types
02197         if( ( flags & MB_TAG_STORE ) && tag_handle->get_storage_type() != storage ) return MB_TYPE_OUT_OF_RANGE;
02198         // check if data type matches
02199         const DataType extype = tag_handle->get_data_type();
02200         if( extype != data_type )
02201         {
02202             if( flags & MB_TAG_NOOPQ )
02203                 return MB_TYPE_OUT_OF_RANGE;
02204             else if( extype != MB_TYPE_OPAQUE && data_type != MB_TYPE_OPAQUE )
02205                 return MB_TYPE_OUT_OF_RANGE;
02206         }
02207 
02208         // Require that the size value be zero or MB_VARIABLE_LENGTH
02209         // for variable length tags.  The caller passing such a size
02210         // value is sufficient to indicate that the caller is aware
02211         // that it is requesting a variable-length tag, so no need
02212         // to also require/check the MB_TAG_VARLEN bit in the flags.
02213         if( tag_handle->variable_length() )
02214         {
02215             if( size != 0 && size != MB_VARIABLE_LENGTH && !( flags & MB_TAG_VARLEN ) ) return MB_INVALID_SIZE;
02216         }
02217         // But /do/ fail if MB_TAG_VARLEN flag is set and tag is
02218         // not variable length.
02219         else if( flags & MB_TAG_VARLEN )
02220             return MB_TYPE_OUT_OF_RANGE;
02221         // check size for fixed-length tag
02222         else if( tag_handle->get_size() != size )
02223             return MB_INVALID_SIZE;
02224 
02225         // If user passed a default value, check that it matches.
02226         // If user did not pass a default value, assume they're OK
02227         // with the existing one.
02228         // If tag does not have a default value but the user passed
02229         // one, allow it only if the tag is dense and the passed value
02230         // is all zero bytes because dense tags have an implicit default
02231         // value of all zeros in some cases.
02232         if( default_value && !( flags & MB_TAG_DFTOK ) &&
02233             !( tag_handle->equals_default_value( default_value, size ) ||
02234                ( !tag_handle->get_default_value() && tag_handle->get_storage_type() == MB_TAG_DENSE &&
02235                  is_zero_bytes( default_value, size ) ) ) )
02236             return MB_ALREADY_ALLOCATED;
02237 
02238         return MB_SUCCESS;
02239     }
02240 
02241     // MB_TAG_EXCL implies MB_TAG_CREAT
02242     if( !( flags & ( MB_TAG_CREAT | MB_TAG_EXCL ) ) ) return MB_TAG_NOT_FOUND;
02243 
02244     // if a non-opaque non-bit type was specified, then the size
02245     // must be multiple of the size of the type
02246     if( ( !( flags & MB_TAG_VARLEN ) || default_value ) &&
02247         ( size <= 0 || ( size % TagInfo::size_from_data_type( data_type ) ) != 0 ) )
02248         return MB_INVALID_SIZE;
02249 
02250     // if MB_TYPE_BIT may be used only with MB_TAG_BIT
02251     // if (storage != MB_TAG_BIT && data_type == MB_TYPE_BIT)
02252     //    return MB_INVALID_ARG;
02253     if( data_type == MB_TYPE_BIT ) flags &= ~(unsigned)( MB_TAG_DENSE | MB_TAG_SPARSE );
02254 
02255     // create the tag
02256     switch( flags & ( MB_TAG_DENSE | MB_TAG_SPARSE | MB_TAG_MESH | MB_TAG_VARLEN ) )
02257     {
02258         case MB_TAG_DENSE | MB_TAG_VARLEN:
02259             tag_handle = VarLenDenseTag::create_tag( sequenceManager, mError, name, data_type, default_value, size );
02260             break;
02261         case MB_TAG_DENSE:
02262             tag_handle = DenseTag::create_tag( sequenceManager, mError, name, size, data_type, default_value );
02263             break;
02264         case MB_TAG_SPARSE | MB_TAG_VARLEN:
02265             tag_handle = new VarLenSparseTag( name, data_type, default_value, size );
02266             break;
02267         case MB_TAG_SPARSE:
02268             tag_handle = new SparseTag( name, size, data_type, default_value );
02269             break;
02270         case MB_TAG_MESH | MB_TAG_VARLEN:
02271             tag_handle = new MeshTag( name, MB_VARIABLE_LENGTH, data_type, default_value, size );
02272             break;
02273         case MB_TAG_MESH:
02274             tag_handle = new MeshTag( name, size, data_type, default_value, size );
02275             break;
02276         case MB_TAG_BIT:
02277             if( MB_TYPE_BIT != data_type && MB_TYPE_OPAQUE != data_type ) return MB_TYPE_OUT_OF_RANGE;
02278             tag_handle = BitTag::create_tag( name, size, default_value );
02279             break;
02280         default:  // some illegal combination (multiple storage types, variable-length bit tag, etc.)
02281             return MB_TYPE_OUT_OF_RANGE;
02282     }
02283 
02284     if( !tag_handle ) return MB_INVALID_SIZE;
02285 
02286     if( created ) *created = true;
02287     tagList.push_back( tag_handle );
02288     return MB_SUCCESS;
02289 }
02290 
02291 ErrorCode Core::tag_get_handle( const char* name, int size, DataType data_type, Tag& tag_handle, unsigned flags,
02292                                 const void* default_value ) const
02293 {
02294     // If caller specified MB_TAG_EXCL, then we must fail because
02295     // this const function can never create a tag.  We need to test
02296     // this here because the non-const version of this function
02297     // assumes MB_TAG_CREAT if MB_TAG_EXCL is specified.
02298     if( flags & MB_TAG_EXCL )
02299     {
02300         // anonymous tag?
02301         if( !name || !*name ) return MB_TAG_NOT_FOUND;
02302 
02303         // search for an existing tag
02304         tag_handle = 0;
02305         for( std::list< Tag >::const_iterator i = tagList.begin(); i != tagList.end(); ++i )
02306         {
02307             if( ( *i )->get_name() == name )
02308             {
02309                 tag_handle = *i;
02310                 return MB_ALREADY_ALLOCATED;
02311             }
02312         }
02313 
02314         return MB_TAG_NOT_FOUND;
02315     }
02316 
02317     return const_cast< Core* >( this )->tag_get_handle( name, size, data_type, tag_handle,
02318                                                         flags & ~(unsigned)MB_TAG_CREAT, default_value );
02319 }
02320 
02321 //! removes the tag from the entity
02322 ErrorCode Core::tag_delete_data( Tag tag_handle, const EntityHandle* entity_handles, int num_entities )
02323 {
02324     assert( valid_tag_handle( tag_handle ) );
02325     CHECK_MESH_NULL
02326     return tag_handle->remove_data( sequenceManager, mError, entity_handles, num_entities );
02327 }
02328 
02329 //! removes the tag from the entity
02330 ErrorCode Core::tag_delete_data( Tag tag_handle, const Range& entity_handles )
02331 {
02332     assert( valid_tag_handle( tag_handle ) );
02333     return tag_handle->remove_data( sequenceManager, mError, entity_handles );
02334 }
02335 
02336 //! removes the tag from MB
02337 ErrorCode Core::tag_delete( Tag tag_handle )
02338 {
02339     std::list< TagInfo* >::iterator i = std::find( tagList.begin(), tagList.end(), tag_handle );
02340     if( i == tagList.end() ) return MB_TAG_NOT_FOUND;
02341 
02342     ErrorCode rval = tag_handle->release_all_data( sequenceManager, mError, true );MB_CHK_ERR( rval );
02343 
02344     tagList.erase( i );
02345     delete tag_handle;
02346     return MB_SUCCESS;
02347 }
02348 
02349 ErrorCode Core::tag_iterate( Tag tag_handle, Range::const_iterator iter, Range::const_iterator end, int& count,
02350                              void*& data_ptr, bool allocate )
02351 {
02352     Range::const_iterator init = iter;
02353     assert( valid_tag_handle( tag_handle ) );
02354     ErrorCode result = tag_handle->tag_iterate( sequenceManager, mError, iter, end, data_ptr, allocate );
02355     if( MB_SUCCESS == result ) count = iter - init;
02356     return result;
02357 }
02358 
02359 //! gets the tag name string for the tag_handle
02360 ErrorCode Core::tag_get_name( const Tag tag_handle, std::string& tag_name ) const
02361 {
02362     if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
02363     tag_name = tag_handle->get_name();
02364     return MB_SUCCESS;
02365 }
02366 
02367 ErrorCode Core::tag_get_handle( const char* tag_name, Tag& tag_handle ) const
02368 {
02369     return tag_get_handle( tag_name, 0, MB_TYPE_OPAQUE, tag_handle, MB_TAG_ANY );
02370 }
02371 
02372 //! get size of tag in bytes
02373 ErrorCode Core::tag_get_bytes( const Tag tag_handle, int& tag_size ) const
02374 {
02375     if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
02376 
02377     if( tag_handle->variable_length() )
02378     {
02379         tag_size = MB_VARIABLE_LENGTH;
02380         return MB_VARIABLE_DATA_LENGTH;
02381     }
02382     else if( tag_handle->get_storage_type() == MB_TAG_BIT )
02383     {
02384         tag_size = 1;
02385         return MB_SUCCESS;
02386     }
02387     else
02388     {
02389         tag_size = tag_handle->get_size();
02390         return MB_SUCCESS;
02391     }
02392 }
02393 
02394 //! get size of tag in $values
02395 ErrorCode Core::tag_get_length( const Tag tag_handle, int& tag_size ) const
02396 {
02397     if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
02398 
02399     if( tag_handle->variable_length() )
02400     {
02401         tag_size = MB_VARIABLE_LENGTH;
02402         return MB_VARIABLE_DATA_LENGTH;
02403     }
02404     else
02405     {
02406         tag_size = tag_handle->get_size() / TagInfo::size_from_data_type( tag_handle->get_data_type() );
02407         return MB_SUCCESS;
02408     }
02409 }
02410 
02411 ErrorCode Core::tag_get_data_type( const Tag handle, DataType& data_type ) const
02412 {
02413     if( !valid_tag_handle( handle ) ) return MB_TAG_NOT_FOUND;
02414 
02415     data_type = handle->get_data_type();
02416     return MB_SUCCESS;
02417 }
02418 
02419 //! get default value of the tag
02420 ErrorCode Core::tag_get_default_value( const Tag tag_handle, void* def_value ) const
02421 {
02422     if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
02423 
02424     if( tag_handle->variable_length() ) return MB_VARIABLE_DATA_LENGTH;
02425 
02426     if( !tag_handle->get_default_value() ) return MB_ENTITY_NOT_FOUND;
02427 
02428     memcpy( def_value, tag_handle->get_default_value(), tag_handle->get_default_value_size() );
02429     return MB_SUCCESS;
02430 }
02431 
02432 ErrorCode Core::tag_get_default_value( Tag tag, const void*& ptr, int& size ) const
02433 {
02434     if( !valid_tag_handle( tag ) ) return MB_ENTITY_NOT_FOUND;
02435 
02436     if( !tag->get_default_value() ) return MB_ENTITY_NOT_FOUND;
02437 
02438     ptr  = tag->get_default_value();
02439     size = tag->get_default_value_size() / TagInfo::size_from_data_type( tag->get_data_type() );
02440     return MB_SUCCESS;
02441 }
02442 
02443 //! get type of tag (sparse, dense, etc.; 0 = dense, 1 = sparse, 2 = bit, 3 = static)
02444 ErrorCode Core::tag_get_type( const Tag tag_handle, TagType& tag_type ) const
02445 {
02446     assert( valid_tag_handle( tag_handle ) );
02447     tag_type = tag_handle->get_storage_type();
02448     return MB_SUCCESS;
02449 }
02450 
02451 //! get handles for all tags defined
02452 ErrorCode Core::tag_get_tags( std::vector< Tag >& tag_handles ) const
02453 {
02454     std::copy( tagList.begin(), tagList.end(), std::back_inserter( tag_handles ) );
02455     return MB_SUCCESS;
02456 }
02457 
02458 //! Get handles for all tags defined on this entity
02459 ErrorCode Core::tag_get_tags_on_entity( const EntityHandle entity, std::vector< Tag >& tag_handles ) const
02460 {
02461     for( std::list< TagInfo* >::const_iterator i = tagList.begin(); i != tagList.end(); ++i )
02462         if( ( *i )->is_tagged( sequenceManager, entity ) ) tag_handles.push_back( *i );
02463     return MB_SUCCESS;
02464 }
02465 
02466 Tag Core::material_tag()
02467 {
02468     const int negone = -1;
02469     if( 0 == materialTag )
02470         tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, materialTag, MB_TAG_CREAT | MB_TAG_SPARSE, &negone );
02471     return materialTag;
02472 }
02473 
02474 Tag Core::neumannBC_tag()
02475 {
02476     const int negone = -1;
02477     if( 0 == neumannBCTag )
02478         tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, neumannBCTag, MB_TAG_CREAT | MB_TAG_SPARSE, &negone );
02479     return neumannBCTag;
02480 }
02481 
02482 Tag Core::dirichletBC_tag()
02483 {
02484     const int negone = -1;
02485     if( 0 == dirichletBCTag )
02486         tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, dirichletBCTag, MB_TAG_CREAT | MB_TAG_SPARSE,
02487                         &negone );
02488     return dirichletBCTag;
02489 }
02490 
02491 Tag Core::globalId_tag()
02492 {
02493     const int negone = -1;
02494     if( 0 == globalIdTag )
02495         tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, globalIdTag, MB_TAG_CREAT | MB_TAG_DENSE, &negone );
02496     return globalIdTag;
02497 }
02498 
02499 Tag Core::geom_dimension_tag()
02500 {
02501     const int negone = -1;
02502     if( 0 == geomDimensionTag )
02503         tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomDimensionTag, MB_TAG_CREAT | MB_TAG_SPARSE,
02504                         &negone );
02505     return geomDimensionTag;
02506 }
02507 
02508 //! creates an element based on the type and connectivity.  returns a handle and error code
02509 ErrorCode Core::create_element( const EntityType entity_type, const EntityHandle* connectivity, const int num_nodes,
02510                                 EntityHandle& handle )
02511 {
02512     // make sure we have enough vertices for this entity type
02513     if( num_nodes < CN::VerticesPerEntity( entity_type ) ) return MB_FAILURE;
02514 
02515     ErrorCode status = sequence_manager()->create_element( entity_type, connectivity, num_nodes, handle );
02516     if( MB_SUCCESS == status ) status = aEntityFactory->notify_create_entity( handle, connectivity, num_nodes );
02517 
02518 #ifdef MOAB_HAVE_AHF
02519     mesh_modified = true;
02520 #endif
02521 
02522     return status;
02523 }
02524 
02525 //! creates a vertex based on coordinates, returns a handle and error code
02526 ErrorCode Core::create_vertex( const double coords[3], EntityHandle& handle )
02527 {
02528     // get an available vertex handle
02529     return sequence_manager()->create_vertex( coords, handle );
02530 }
02531 
02532 ErrorCode Core::create_vertices( const double* coordinates, const int nverts, Range& entity_handles )
02533 {
02534     // Create vertices
02535     ReadUtilIface* read_iface;
02536     ErrorCode result = Interface::query_interface( read_iface );MB_CHK_ERR( result );
02537 
02538     std::vector< double* > arrays;
02539     EntityHandle start_handle_out = 0;
02540     result                        = read_iface->get_node_coords( 3, nverts, MB_START_ID, start_handle_out, arrays );
02541     Interface::release_interface( read_iface );MB_CHK_ERR( result );
02542     // Cppcheck warning (false positive): variable arrays is assigned a value that is never used
02543     for( int i = 0; i < nverts; i++ )
02544     {
02545         arrays[0][i] = coordinates[3 * i];
02546         arrays[1][i] = coordinates[3 * i + 1];
02547         arrays[2][i] = coordinates[3 * i + 2];
02548     }
02549 
02550     entity_handles.clear();
02551     entity_handles.insert( start_handle_out, start_handle_out + nverts - 1 );
02552 
02553     return MB_SUCCESS;
02554 }
02555 
02556 //! merges two  entities
02557 ErrorCode Core::merge_entities( EntityHandle entity_to_keep, EntityHandle entity_to_remove, bool auto_merge,
02558                                 bool delete_removed_entity )
02559 {
02560     if( auto_merge ) return MB_FAILURE;
02561 
02562     // The two entities to merge must not be the same entity.
02563     if( entity_to_keep == entity_to_remove ) return MB_FAILURE;
02564 
02565     // The two entities to merge must be of the same type
02566     EntityType type_to_keep = TYPE_FROM_HANDLE( entity_to_keep );
02567 
02568     if( type_to_keep != TYPE_FROM_HANDLE( entity_to_remove ) ) return MB_TYPE_OUT_OF_RANGE;
02569 
02570     // Make sure both entities exist before trying to merge.
02571     EntitySequence* seq = 0;
02572     ErrorCode result, status;
02573     status = sequence_manager()->find( entity_to_keep, seq );
02574     if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
02575     status = sequence_manager()->find( entity_to_remove, seq );
02576     if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
02577 
02578     // If auto_merge is not set, all sub-entities should
02579     // be merged if the entities are to be merged.
02580     int ent_dim = CN::Dimension( type_to_keep );
02581     if( ent_dim > 0 )
02582     {
02583         std::vector< EntityHandle > conn, conn2;
02584 
02585         result = get_connectivity( &entity_to_keep, 1, conn );MB_CHK_ERR( result );
02586         result = get_connectivity( &entity_to_remove, 1, conn2 );MB_CHK_ERR( result );
02587 
02588         // Check to see if we can merge before pulling adjacencies.
02589         int dum1, dum2;
02590         if( !auto_merge &&
02591             ( conn.size() != conn2.size() || !CN::ConnectivityMatch( &conn[0], &conn2[0], conn.size(), dum1, dum2 ) ) )
02592             return MB_FAILURE;
02593     }
02594 
02595     result = aEntityFactory->merge_adjust_adjacencies( entity_to_keep, entity_to_remove );
02596 
02597     if( MB_SUCCESS == result && delete_removed_entity ) result = delete_entities( &entity_to_remove, 1 );
02598 
02599     return result;
02600 }
02601 
02602 //! deletes an entity range
02603 ErrorCode Core::delete_entities( const Range& range )
02604 {
02605     ErrorCode result = MB_SUCCESS, temp_result;
02606     Range failed_ents;
02607 
02608     for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i )
02609     {
02610         temp_result = ( *i )->remove_data( sequenceManager, mError, range );
02611         // ok if the error is tag_not_found, some ents may not have every tag on them
02612         if( MB_SUCCESS != temp_result && MB_TAG_NOT_FOUND != temp_result ) result = temp_result;
02613     }
02614 
02615     for( Range::const_reverse_iterator rit = range.rbegin(); rit != range.rend(); ++rit )
02616     {
02617 
02618         // tell AEntityFactory that this element is going away
02619         temp_result = aEntityFactory->notify_delete_entity( *rit );
02620         if( MB_SUCCESS != temp_result )
02621         {
02622             result = temp_result;
02623             failed_ents.insert( *rit );
02624             continue;
02625         }
02626 
02627         if( TYPE_FROM_HANDLE( *rit ) == MBENTITYSET )
02628         {
02629             if( MeshSet* ptr = get_mesh_set( sequence_manager(), *rit ) )
02630             {
02631                 int j, count;
02632                 const EntityHandle* rel;
02633                 ptr->clear( *rit, a_entity_factory() );
02634                 rel = ptr->get_parents( count );
02635                 for( j = 0; j < count; ++j )
02636                     remove_child_meshset( rel[j], *rit );
02637                 rel = ptr->get_children( count );
02638                 for( j = 0; j < count; ++j )
02639                     remove_parent_meshset( rel[j], *rit );
02640             }
02641         }
02642     }
02643 
02644     if( !failed_ents.empty() )
02645     {
02646         Range dum_range = subtract( range, failed_ents );
02647         // don't test for success, since we'll return failure in this case
02648         sequence_manager()->delete_entities( mError, dum_range );
02649     }
02650     else
02651         // now delete the entities
02652         result = sequence_manager()->delete_entities( mError, range );
02653 
02654     return result;
02655 }
02656 
02657 //! deletes an entity vector
02658 ErrorCode Core::delete_entities( const EntityHandle* entities, const int num_entities )
02659 {
02660     ErrorCode result = MB_SUCCESS, temp_result;
02661     Range failed_ents;
02662 
02663     for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i )
02664     {
02665         temp_result = ( *i )->remove_data( sequenceManager, mError, entities, num_entities );
02666         // ok if the error is tag_not_found, some ents may not have every tag on them
02667         if( MB_SUCCESS != temp_result && MB_TAG_NOT_FOUND != temp_result ) result = temp_result;
02668     }
02669 
02670     for( int i = 0; i < num_entities; i++ )
02671     {
02672 
02673         // tell AEntityFactory that this element is going away
02674         bool failed = false;
02675         temp_result = aEntityFactory->notify_delete_entity( entities[i] );
02676         if( MB_SUCCESS != temp_result )
02677         {
02678             result = temp_result;
02679             failed = true;
02680         }
02681 
02682         if( TYPE_FROM_HANDLE( entities[i] ) == MBENTITYSET )
02683         {
02684             if( MeshSet* ptr = get_mesh_set( sequence_manager(), entities[i] ) )
02685             {
02686                 int j, count;
02687                 const EntityHandle* rel;
02688                 ptr->clear( entities[i], a_entity_factory() );
02689                 rel = ptr->get_parents( count );
02690                 for( j = 0; j < count; ++j )
02691                     remove_child_meshset( rel[j], entities[i] );
02692                 rel = ptr->get_children( count );
02693                 for( j = 0; j < count; ++j )
02694                     remove_parent_meshset( rel[j], entities[i] );
02695             }
02696         }
02697 
02698         if( failed )
02699             // don't test for success, since we'll return failure in this case
02700             sequence_manager()->delete_entity( mError, entities[i] );
02701         else
02702         {
02703             // now delete the entity
02704             temp_result = sequence_manager()->delete_entity( mError, entities[i] );
02705             if( MB_SUCCESS != temp_result ) result = temp_result;
02706         }
02707     }
02708 
02709     return result;
02710 }
02711 
02712 ErrorCode Core::list_entities( const EntityHandle* entities, const int num_entities ) const
02713 {
02714     Range temp_range;
02715     ErrorCode result = MB_SUCCESS;
02716     if( NULL == entities && num_entities == 0 )
02717     {
02718         // just list the numbers of each entity type
02719         int num_ents;
02720         std::cout << std::endl;
02721         std::cout << "Number of entities per type: " << std::endl;
02722         for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
02723         {
02724             result = get_number_entities_by_type( 0, this_type, num_ents );
02725             std::cout << CN::EntityTypeName( this_type ) << ": " << num_ents << std::endl;
02726         }
02727         std::cout << std::endl;
02728 
02729         return MB_SUCCESS;
02730     }
02731     else if( NULL == entities && num_entities < 0 )
02732     {
02733 
02734         // list all entities of all types
02735         std::cout << std::endl;
02736         for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
02737         {
02738             result = get_entities_by_type( 0, this_type, temp_range );
02739         }
02740 
02741         return list_entities( temp_range );
02742     }
02743     else if( NULL == entities && num_entities > 0 )
02744     {
02745 
02746         // list all entities of type == num_entities
02747         std::cout << std::endl;
02748         result = get_entities_by_type( 0, (EntityType)num_entities, temp_range );
02749 
02750         return list_entities( temp_range );
02751     }
02752     else
02753     {
02754         ErrorCode tmp_result;
02755         for( int i = 0; i < num_entities; i++ )
02756         {
02757             EntityType this_type = TYPE_FROM_HANDLE( entities[i] );
02758             std::cout << CN::EntityTypeName( this_type ) << " " << ID_FROM_HANDLE( entities[i] ) << ":" << endl;
02759 
02760             tmp_result = ( const_cast< Core* >( this ) )->list_entity( entities[i] );
02761             if( MB_SUCCESS != tmp_result ) result = tmp_result;
02762         }
02763     }
02764 
02765     return result;
02766 }
02767 
02768 ErrorCode Core::list_entities( const Range& temp_range ) const
02769 {
02770     ErrorCode result = MB_SUCCESS, tmp_result;
02771 
02772     for( Range::const_iterator rit = temp_range.begin(); rit != temp_range.end(); ++rit )
02773     {
02774         EntityType this_type = TYPE_FROM_HANDLE( *rit );
02775         std::cout << CN::EntityTypeName( this_type ) << " " << ID_FROM_HANDLE( *rit ) << ":" << endl;
02776 
02777         tmp_result = ( const_cast< Core* >( this ) )->list_entity( *rit );
02778         if( MB_SUCCESS != tmp_result ) result = tmp_result;
02779     }
02780 
02781     return result;
02782 }
02783 
02784 ErrorCode Core::list_entity( const EntityHandle entity ) const
02785 {
02786     ErrorCode result;
02787     HandleVec adj_vec;
02788 
02789     if( !is_valid( entity ) )
02790     {
02791         std::cout << "(invalid)" << std::endl;
02792         return MB_SUCCESS;
02793     }
02794 
02795     if( 0 != globalIdTag )
02796     {
02797         int dum;
02798         result = tag_get_data( globalIdTag, &entity, 1, &dum );
02799         if( MB_SUCCESS == result ) std::cout << "Global id = " << dum << std::endl;
02800     }
02801 
02802     // list entity
02803     EntityType this_type = TYPE_FROM_HANDLE( entity );
02804     if( this_type == MBVERTEX )
02805     {
02806         double coords[3];
02807         result = get_coords( &( entity ), 1, coords );MB_CHK_ERR( result );
02808         std::cout << "Coordinates: (" << coords[0] << ", " << coords[1] << ", " << coords[2] << ")" << std::endl;
02809     }
02810     else if( this_type == MBENTITYSET )
02811         this->print( entity, "" );
02812 
02813     std::cout << "  Adjacencies:" << std::endl;
02814     bool some    = false;
02815     int multiple = 0;
02816     for( int dim = 0; dim <= 3; dim++ )
02817     {
02818         if( dim == CN::Dimension( this_type ) ) continue;
02819         adj_vec.clear();
02820         // use const_cast here 'cuz we're in a const function and we're passing 'false' for
02821         // create_if_missing, so we know we won't change anything
02822         result = ( const_cast< Core* >( this ) )->get_adjacencies( &( entity ), 1, dim, false, adj_vec );
02823         if( MB_FAILURE == result ) continue;
02824         for( HandleVec::iterator adj_it = adj_vec.begin(); adj_it != adj_vec.end(); ++adj_it )
02825         {
02826             if( adj_it != adj_vec.begin() )
02827                 std::cout << ", ";
02828             else
02829                 std::cout << "   ";
02830             std::cout << CN::EntityTypeName( TYPE_FROM_HANDLE( *adj_it ) ) << " " << ID_FROM_HANDLE( *adj_it );
02831         }
02832         if( !adj_vec.empty() )
02833         {
02834             std::cout << std::endl;
02835             some = true;
02836         }
02837         if( MB_MULTIPLE_ENTITIES_FOUND == result ) multiple += dim;
02838     }
02839     if( !some ) std::cout << "(none)" << std::endl;
02840     const EntityHandle* explicit_adjs;
02841     int num_exp;
02842     aEntityFactory->get_adjacencies( entity, explicit_adjs, num_exp );
02843     if( NULL != explicit_adjs && 0 != num_exp )
02844     {
02845         std::cout << "  Explicit adjacencies: ";
02846         for( int i = 0; i < num_exp; i++ )
02847         {
02848             if( i != 0 ) std::cout << ", ";
02849             std::cout << CN::EntityTypeName( TYPE_FROM_HANDLE( explicit_adjs[i] ) ) << " "
02850                       << ID_FROM_HANDLE( explicit_adjs[i] );
02851         }
02852         std::cout << std::endl;
02853     }
02854     if( multiple != 0 ) std::cout << "   (MULTIPLE = " << multiple << ")" << std::endl;
02855 
02856     result = print_entity_tags( std::string(), entity, MB_TAG_DENSE );
02857 
02858     std::cout << std::endl;
02859 
02860     return result;
02861 }
02862 
02863 ErrorCode Core::convert_entities( const EntityHandle meshset, const bool mid_side, const bool mid_face,
02864                                   const bool mid_volume, Interface::HONodeAddedRemoved* function_object )
02865 {
02866     HigherOrderFactory fact( this, function_object );
02867     return fact.convert( meshset, mid_side, mid_face, mid_volume );
02868 }
02869 
02870 //! function to get the side number given two elements; returns
02871 //! MB_FAILURE if child not related to parent; does *not* create adjacencies
02872 //! between parent and child
02873 ErrorCode Core::side_number( const EntityHandle parent, const EntityHandle child, int& sd_number, int& sense,
02874                              int& offset ) const
02875 {
02876     // get the connectivity of parent and child
02877     const EntityHandle *parent_conn = NULL, *child_conn = NULL;
02878     int num_parent_vertices = 0, num_child_vertices = 0;
02879     ErrorCode result = get_connectivity( parent, parent_conn, num_parent_vertices, true );
02880     if( MB_NOT_IMPLEMENTED == result )
02881     {
02882         static std::vector< EntityHandle > tmp_connect( CN::MAX_NODES_PER_ELEMENT );
02883         result = get_connectivity( parent, parent_conn, num_parent_vertices, true, &tmp_connect );
02884     }
02885     if( MB_SUCCESS != result ) return result;
02886 
02887     if( TYPE_FROM_HANDLE( child ) == MBVERTEX )
02888     {
02889         int child_index = std::find( parent_conn, parent_conn + num_parent_vertices, child ) - parent_conn;
02890         if( child_index == num_parent_vertices )
02891         {
02892             sd_number = -1;
02893             sense     = 0;
02894             return MB_FAILURE;
02895         }
02896         else
02897         {
02898             sd_number = child_index;
02899             sense     = 1;
02900             return MB_SUCCESS;
02901         }
02902     }
02903 
02904     if( TYPE_FROM_HANDLE( parent ) == MBPOLYHEDRON )
02905     {
02906         // find the child in the parent_conn connectivity list, and call it a day ..
02907         // it should work only for faces within a conn list
02908         for( int i = 0; i < num_parent_vertices; i++ )
02909             if( child == parent_conn[i] )
02910             {
02911                 sd_number = i;
02912                 sense     = 1;  // always
02913                 offset    = 0;
02914                 return MB_SUCCESS;
02915             }
02916         return MB_FAILURE;
02917     }
02918     result = get_connectivity( child, child_conn, num_child_vertices, true );MB_CHK_ERR( result );
02919 
02920     // call handle vector-based function
02921     if( TYPE_FROM_HANDLE( parent ) != MBPOLYGON && TYPE_FROM_HANDLE( parent ) != MBPOLYHEDRON )
02922     {
02923 
02924         // find indices into parent_conn for each entry in child_conn
02925         int child_conn_indices[10];
02926         assert( (unsigned)num_child_vertices <= sizeof( child_conn_indices ) / sizeof( child_conn_indices[0] ) );
02927         for( int i = 0; i < num_child_vertices; ++i )
02928         {
02929             child_conn_indices[i] =
02930                 std::find( parent_conn, parent_conn + num_parent_vertices, child_conn[i] ) - parent_conn;
02931             if( child_conn_indices[i] >= num_parent_vertices )
02932             {
02933                 sd_number = -1;
02934                 return MB_FAILURE;
02935             }
02936         }
02937 
02938         int temp_result = CN::SideNumber( TYPE_FROM_HANDLE( parent ), child_conn_indices, num_child_vertices,
02939                                           CN::Dimension( TYPE_FROM_HANDLE( child ) ), sd_number, sense, offset );
02940         return ( 0 == temp_result ? MB_SUCCESS : MB_FAILURE );
02941     }
02942     else if( TYPE_FROM_HANDLE( parent ) == MBPOLYGON )
02943     {
02944         // find location of 1st vertex; this works even for padded vertices
02945         const EntityHandle* first_v = std::find( parent_conn, parent_conn + num_parent_vertices, child_conn[0] );
02946         if( first_v == parent_conn + num_parent_vertices ) return MB_ENTITY_NOT_FOUND;
02947         sd_number = first_v - parent_conn;
02948         offset    = sd_number;
02949         if( TYPE_FROM_HANDLE( child ) == MBVERTEX )
02950         {
02951             sense = 0;
02952             return MB_SUCCESS;
02953         }
02954         else if( TYPE_FROM_HANDLE( child ) == MBPOLYGON )
02955         {
02956             bool match = CN::ConnectivityMatch( parent_conn, child_conn, num_parent_vertices, sense, offset );
02957             sd_number  = 0;
02958             if( match )
02959                 return MB_SUCCESS;
02960             else
02961                 return MB_ENTITY_NOT_FOUND;
02962         }
02963         else if( TYPE_FROM_HANDLE( child ) == MBEDGE )
02964         {
02965             // determine the actual number of vertices, for the padded case
02966             // the padded case could be like ABCDEFFF; num_parent_vertices=8,
02967             // actual_num_parent_vertices=6
02968             int actual_num_parent_vertices = num_parent_vertices;
02969             while( actual_num_parent_vertices >= 3 &&
02970                    ( parent_conn[actual_num_parent_vertices - 2] == parent_conn[actual_num_parent_vertices - 1] ) )
02971                 actual_num_parent_vertices--;
02972 
02973             if( parent_conn[( sd_number + 1 ) % num_parent_vertices] == child_conn[1] )
02974                 sense = 1;
02975             else if( parent_conn[( sd_number + num_parent_vertices - 1 ) % num_parent_vertices] ==
02976                      child_conn[1] )  // this will also cover edge AF for padded case, side will
02977                                       // be 0, sense -1
02978                 sense = -1;
02979             // if edge FA in above example, we should return sd_number = 5, sense 1
02980             else if( ( sd_number == actual_num_parent_vertices - 1 ) && ( child_conn[1] == parent_conn[0] ) )
02981                 sense = 1;
02982             else
02983                 return MB_ENTITY_NOT_FOUND;
02984             return MB_SUCCESS;
02985         }
02986     }
02987 
02988     return MB_FAILURE;
02989 }
02990 
02991 //! given an entity and the connectivity and type of one of its subfacets, find the
02992 //! high order node on that subfacet, if any
02993 ErrorCode Core::high_order_node( const EntityHandle parent_handle, const EntityHandle* subfacet_conn,
02994                                  const EntityType subfacet_type, EntityHandle& hon ) const
02995 {
02996     hon = 0;
02997 
02998     EntityType parent_type = TYPE_FROM_HANDLE( parent_handle );
02999 
03000     // get the parent's connectivity
03001     const EntityHandle* parent_conn = NULL;
03002     int num_parent_vertices         = 0;
03003     ErrorCode result                = get_connectivity( parent_handle, parent_conn, num_parent_vertices, false );MB_CHK_ERR( result );
03004 
03005     // find whether this entity has ho nodes
03006     int mid_nodes[4];
03007     CN::HasMidNodes( parent_type, num_parent_vertices, mid_nodes );
03008 
03009     // check whether this entity has mid nodes on this dimension subfacet;
03010     // use dimension-1 because vertices don't have mid nodes
03011     if( !mid_nodes[CN::Dimension( subfacet_type )] ) return MB_SUCCESS;
03012 
03013     // ok, we have mid nodes; now must compute expected index in connectivity array;
03014     // ho nodes stored for edges, faces then entity
03015 
03016     // offset starts with # corner vertices
03017     int offset = CN::VerticesPerEntity( parent_type );
03018     int i;
03019 
03020     for( i = 0; i < CN::Dimension( subfacet_type ) - 1; i++ )
03021         // for each dimension lower than that of the subfacet we're looking for,
03022         // if this entity has midnodes in that dimension, increment offset by #
03023         // of subfacets of that dimension; use dimension-1 in loop because
03024         // canon numbering table only has 2 positions, for edges and faces;
03025         if( mid_nodes[i + 1] ) offset += CN::mConnectivityMap[parent_type][i].num_sub_elements;
03026 
03027     // now add the index of this subfacet; only need to if it's not the highest dimension
03028     if( subfacet_type != parent_type )
03029     {
03030 
03031         // find indices into parent_conn for each entry in child_conn
03032         unsigned subfacet_size = CN::VerticesPerEntity( subfacet_type );
03033         int subfacet_indices[10];
03034         assert( subfacet_size <= sizeof( subfacet_indices ) / sizeof( subfacet_indices[0] ) );
03035         for( unsigned j = 0; j < subfacet_size; ++j )
03036         {
03037             subfacet_indices[j] =
03038                 std::find( parent_conn, parent_conn + num_parent_vertices, subfacet_conn[j] ) - parent_conn;
03039             if( subfacet_indices[j] >= num_parent_vertices ) { return MB_FAILURE; }
03040         }
03041 
03042         int dum, side_no, temp_offset;
03043         int temp_result =
03044             CN::SideNumber( parent_type, subfacet_indices, subfacet_size, subfacet_type, side_no, dum, temp_offset );
03045         if( temp_result != 0 ) return MB_FAILURE;
03046 
03047         offset += side_no;
03048     }
03049 
03050     // offset shouldn't be off the end of the connectivity vector
03051     if( offset >= num_parent_vertices ) return MB_INDEX_OUT_OF_RANGE;
03052 
03053     hon = parent_conn[offset];
03054 
03055     return MB_SUCCESS;
03056 }
03057 
03058 //! given an entity and a target dimension & side number, get that entity
03059 ErrorCode Core::side_element( const EntityHandle source_entity, const int dim, const int sd_number,
03060                               EntityHandle& target_entity ) const
03061 {
03062     // get a handle on the connectivity
03063     const EntityHandle* verts;
03064     int num_verts;
03065     ErrorCode result = get_connectivity( source_entity, verts, num_verts );MB_CHK_ERR( result );
03066 
03067     // special case for vertices
03068     if( dim == 0 )
03069     {
03070         if( sd_number < num_verts )
03071         {
03072             target_entity = verts[sd_number];
03073             return MB_SUCCESS;
03074         }
03075 
03076         else
03077             return MB_INDEX_OUT_OF_RANGE;
03078     }
03079 
03080     // get the vertices comprising the target entity
03081     Range side_verts, target_ents;
03082     const EntityType source_type = TYPE_FROM_HANDLE( source_entity );
03083     // first get the indices
03084     std::vector< int > vertex_indices;
03085 
03086     int temp_result = CN::AdjacentSubEntities( source_type, &sd_number, 1, dim, 0, vertex_indices );
03087     if( 0 != temp_result ) return MB_FAILURE;
03088     // now get the actual vertices
03089     for( unsigned int i = 0; i < vertex_indices.size(); i++ )
03090         side_verts.insert( verts[vertex_indices[i]] );
03091 
03092     // now look for an entity of the correct type
03093     // use const_cast here 'cuz we're in a const function and we're passing 'false' for
03094     // create_if_missing, so we know we won't change anything
03095     result = ( const_cast< Core* >( this ) )->get_adjacencies( side_verts, dim, false, target_ents );
03096     if( MB_SUCCESS != result && MB_MULTIPLE_ENTITIES_FOUND != result ) return result;
03097 
03098     if( !target_ents.empty() && TYPE_FROM_HANDLE( *( target_ents.begin() ) ) != MBVERTEX &&
03099         TYPE_FROM_HANDLE( *( target_ents.begin() ) ) !=
03100             CN::mConnectivityMap[source_type][dim - 1].target_type[sd_number] )
03101         return MB_ENTITY_NOT_FOUND;
03102 
03103     if( !target_ents.empty() ) target_entity = *( target_ents.begin() );
03104 
03105     return result;
03106 }
03107 
03108 //-------------------------Set Functions---------------------//
03109 
03110 ErrorCode Core::create_meshset( const unsigned int setoptions, EntityHandle& ms_handle, int )
03111 {
03112     return sequence_manager()->create_mesh_set( setoptions, ms_handle );
03113 }
03114 
03115 ErrorCode Core::get_meshset_options( const EntityHandle ms_handle, unsigned int& setoptions ) const
03116 {
03117     if( !ms_handle )
03118     {  // root set
03119         setoptions = MESHSET_SET | MESHSET_TRACK_OWNER;
03120         return MB_SUCCESS;
03121     }
03122 
03123     const MeshSet* set = get_mesh_set( sequence_manager(), ms_handle );
03124     if( !set ) return MB_ENTITY_NOT_FOUND;
03125 
03126     setoptions = set->flags();
03127     return MB_SUCCESS;
03128 }
03129 
03130 ErrorCode Core::set_meshset_options( const EntityHandle ms_handle, const unsigned int setoptions )
03131 {
03132     MeshSet* set = get_mesh_set( sequence_manager(), ms_handle );
03133     if( !set ) return MB_ENTITY_NOT_FOUND;
03134 
03135     return set->set_flags( setoptions, ms_handle, a_entity_factory() );
03136 }
03137 
03138 ErrorCode Core::clear_meshset( const EntityHandle* ms_handles, const int num_meshsets )
03139 {
03140     ErrorCode result = MB_SUCCESS;
03141     for( int i = 0; i < num_meshsets; ++i )
03142     {
03143         MeshSet* set = get_mesh_set( sequence_manager(), ms_handles[i] );
03144         if( set )
03145             set->clear( ms_handles[i], a_entity_factory() );
03146         else
03147             result = MB_ENTITY_NOT_FOUND;
03148     }
03149 
03150     return result;
03151 }
03152 
03153 ErrorCode Core::clear_meshset( const Range& ms_handles )
03154 {
03155     ErrorCode result = MB_SUCCESS;
03156     for( Range::iterator i = ms_handles.begin(); i != ms_handles.end(); ++i )
03157     {
03158         MeshSet* set = get_mesh_set( sequence_manager(), *i );
03159         if( set )
03160             set->clear( *i, a_entity_factory() );
03161         else
03162             result = MB_ENTITY_NOT_FOUND;
03163     }
03164 
03165     return result;
03166 }
03167 
03168 ErrorCode Core::subtract_meshset( EntityHandle meshset1, const EntityHandle meshset2 )
03169 {
03170     MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 );
03171     MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 );
03172     if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND;
03173 
03174     return set1->subtract( set2, meshset1, a_entity_factory() );
03175 }
03176 
03177 ErrorCode Core::intersect_meshset( EntityHandle meshset1, const EntityHandle meshset2 )
03178 {
03179     MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 );
03180     MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 );
03181     if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND;
03182 
03183     return set1->intersect( set2, meshset1, a_entity_factory() );
03184 }
03185 
03186 ErrorCode Core::unite_meshset( EntityHandle meshset1, const EntityHandle meshset2 )
03187 {
03188     MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 );
03189     MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 );
03190     if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND;
03191 
03192     return set1->unite( set2, meshset1, a_entity_factory() );
03193 }
03194 
03195 ErrorCode Core::add_entities( EntityHandle meshset, const Range& entities )
03196 {
03197     MeshSet* set = get_mesh_set( sequence_manager(), meshset );
03198     if( set )
03199         return set->add_entities( entities, meshset, a_entity_factory() );
03200     else
03201         return MB_ENTITY_NOT_FOUND;
03202 }
03203 
03204 ErrorCode Core::add_entities( EntityHandle meshset, const EntityHandle* entities, const int num_entities )
03205 {
03206     MeshSet* set = get_mesh_set( sequence_manager(), meshset );
03207     if( set )
03208         return set->add_entities( entities, num_entities, meshset, a_entity_factory() );
03209     else
03210         return MB_ENTITY_NOT_FOUND;
03211 }
03212 
03213 //! remove a range of entities from a meshset
03214 ErrorCode Core::remove_entities( EntityHandle meshset, const Range& entities )
03215 {
03216     MeshSet* set = get_mesh_set( sequence_manager(), meshset );
03217     if( set )
03218         return set->remove_entities( entities, meshset, a_entity_factory() );
03219     else
03220         return MB_ENTITY_NOT_FOUND;
03221 }
03222 
03223 //! remove a vector of entities from a meshset
03224 ErrorCode Core::remove_entities( EntityHandle meshset, const EntityHandle* entities, const int num_entities )
03225 {
03226     MeshSet* set = get_mesh_set( sequence_manager(), meshset );
03227     if( set )
03228         return set->remove_entities( entities, num_entities, meshset, a_entity_factory() );
03229     else
03230         return MB_ENTITY_NOT_FOUND;
03231 }
03232 
03233 //! return true if all entities are contained in set
03234 bool Core::contains_entities( EntityHandle meshset, const EntityHandle* entities, int num_entities,
03235                               const int operation_type )
03236 {
03237     if( !meshset )  // root
03238         return true;
03239     else if( MeshSet* set = get_mesh_set( sequence_manager(), meshset ) )
03240         return set->contains_entities( entities, num_entities, operation_type );
03241     else
03242         return false;
03243 }
03244 
03245 // replace entities in a meshset
03246 ErrorCode Core::replace_entities( EntityHandle meshset, const EntityHandle* old_entities,
03247                                   const EntityHandle* new_entities, int num_entities )
03248 {
03249     MeshSet* set = get_mesh_set( sequence_manager(), meshset );
03250     if( set )
03251         return set->replace_entities( meshset, old_entities, new_entities, num_entities, a_entity_factory() );
03252     else
03253         return MB_ENTITY_NOT_FOUND;
03254 }
03255 
03256 ErrorCode Core::get_parent_meshsets( const EntityHandle meshset, std::vector< EntityHandle >& parents,
03257                                      const int num_hops ) const
03258 {
03259     if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
03260 
03261     const EntitySequence* seq;
03262     ErrorCode rval = sequence_manager()->find( meshset, seq );
03263     if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
03264     const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
03265 
03266     return mseq->get_parents( sequence_manager(), meshset, parents, num_hops );
03267 }
03268 
03269 ErrorCode Core::get_parent_meshsets( const EntityHandle meshset, Range& parents, const int num_hops ) const
03270 {
03271     if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
03272 
03273     std::vector< EntityHandle > parent_vec;
03274     ErrorCode result = get_parent_meshsets( meshset, parent_vec, num_hops );MB_CHK_ERR( result );
03275     std::sort( parent_vec.begin(), parent_vec.end() );
03276     std::copy( parent_vec.rbegin(), parent_vec.rend(), range_inserter( parents ) );
03277     return MB_SUCCESS;
03278 }
03279 
03280 ErrorCode Core::get_child_meshsets( const EntityHandle meshset, std::vector< EntityHandle >& children,
03281                                     const int num_hops ) const
03282 {
03283     if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
03284 
03285     const EntitySequence* seq;
03286     ErrorCode rval = sequence_manager()->find( meshset, seq );
03287     if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
03288     const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
03289 
03290     return mseq->get_children( sequence_manager(), meshset, children, num_hops );
03291 }
03292 
03293 ErrorCode Core::get_child_meshsets( const EntityHandle meshset, Range& children, const int num_hops ) const
03294 {
03295     if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
03296 
03297     std::vector< EntityHandle > child_vec;
03298     ErrorCode result = get_child_meshsets( meshset, child_vec, num_hops );MB_CHK_ERR( result );
03299     std::sort( child_vec.begin(), child_vec.end() );
03300     std::copy( child_vec.rbegin(), child_vec.rend(), range_inserter( children ) );
03301     return MB_SUCCESS;
03302 }
03303 
03304 ErrorCode Core::get_contained_meshsets( const EntityHandle meshset, std::vector< EntityHandle >& children,
03305                                         const int num_hops ) const
03306 {
03307     if( 0 == meshset ) { return get_entities_by_type( meshset, MBENTITYSET, children ); }
03308 
03309     const EntitySequence* seq;
03310     ErrorCode rval = sequence_manager()->find( meshset, seq );
03311     if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
03312     const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
03313 
03314     return mseq->get_contained_sets( sequence_manager(), meshset, children, num_hops );
03315 }
03316 
03317 ErrorCode Core::get_contained_meshsets( const EntityHandle meshset, Range& children, const int num_hops ) const
03318 {
03319     if( 0 == meshset ) { return get_entities_by_type( meshset, MBENTITYSET, children ); }
03320 
03321     std::vector< EntityHandle > child_vec;
03322     ErrorCode result = get_contained_meshsets( meshset, child_vec, num_hops );MB_CHK_ERR( result );
03323     std::sort( child_vec.begin(), child_vec.end() );
03324     std::copy( child_vec.rbegin(), child_vec.rend(), range_inserter( children ) );
03325     return MB_SUCCESS;
03326 }
03327 
03328 ErrorCode Core::num_parent_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const
03329 {
03330     if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
03331 
03332     const EntitySequence* seq;
03333     ErrorCode rval = sequence_manager()->find( meshset, seq );
03334     if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
03335     const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
03336 
03337     return mseq->num_parents( sequence_manager(), meshset, *number, num_hops );
03338 }
03339 
03340 ErrorCode Core::num_child_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const
03341 {
03342     if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
03343 
03344     const EntitySequence* seq;
03345     ErrorCode rval = sequence_manager()->find( meshset, seq );
03346     if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
03347     const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
03348 
03349     return mseq->num_children( sequence_manager(), meshset, *number, num_hops );
03350 }
03351 
03352 ErrorCode Core::num_contained_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const
03353 {
03354     if( 0 == meshset ) { return get_number_entities_by_type( 0, MBENTITYSET, *number ); }
03355 
03356     const EntitySequence* seq;
03357     ErrorCode rval = sequence_manager()->find( meshset, seq );
03358     if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
03359     const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
03360 
03361     return mseq->num_contained_sets( sequence_manager(), meshset, *number, num_hops );
03362 }
03363 
03364 ErrorCode Core::add_parent_meshset( EntityHandle meshset, const EntityHandle parent_meshset )
03365 {
03366     MeshSet* set_ptr    = get_mesh_set( sequence_manager(), meshset );
03367     MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent_meshset );
03368     if( !set_ptr || !parent_ptr ) return MB_ENTITY_NOT_FOUND;
03369 
03370     set_ptr->add_parent( parent_meshset );
03371     return MB_SUCCESS;
03372 }
03373 
03374 ErrorCode Core::add_parent_meshsets( EntityHandle meshset, const EntityHandle* parents, int count )
03375 {
03376     MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
03377     if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
03378 
03379     for( int i = 0; i < count; ++i )
03380         if( !get_mesh_set( sequence_manager(), parents[i] ) ) return MB_ENTITY_NOT_FOUND;
03381 
03382     for( int i = 0; i < count; ++i )
03383         set_ptr->add_parent( parents[i] );
03384     return MB_SUCCESS;
03385 }
03386 
03387 ErrorCode Core::add_child_meshset( EntityHandle meshset, const EntityHandle child_meshset )
03388 {
03389     MeshSet* set_ptr   = get_mesh_set( sequence_manager(), meshset );
03390     MeshSet* child_ptr = get_mesh_set( sequence_manager(), child_meshset );
03391     if( !set_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND;
03392 
03393     set_ptr->add_child( child_meshset );
03394     return MB_SUCCESS;
03395 }
03396 
03397 ErrorCode Core::add_child_meshsets( EntityHandle meshset, const EntityHandle* children, int count )
03398 {
03399     MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
03400     if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
03401 
03402     for( int i = 0; i < count; ++i )
03403         if( !get_mesh_set( sequence_manager(), children[i] ) ) return MB_ENTITY_NOT_FOUND;
03404 
03405     for( int i = 0; i < count; ++i )
03406         set_ptr->add_child( children[i] );
03407     return MB_SUCCESS;
03408 }
03409 
03410 ErrorCode Core::add_parent_child( EntityHandle parent, EntityHandle child )
03411 {
03412     MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent );
03413     MeshSet* child_ptr  = get_mesh_set( sequence_manager(), child );
03414     if( !parent_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND;
03415 
03416     parent_ptr->add_child( child );
03417     child_ptr->add_parent( parent );
03418     return MB_SUCCESS;
03419 }
03420 
03421 ErrorCode Core::remove_parent_child( EntityHandle parent, EntityHandle child )
03422 {
03423     MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent );
03424     MeshSet* child_ptr  = get_mesh_set( sequence_manager(), child );
03425     if( !parent_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND;
03426 
03427     parent_ptr->remove_child( child );
03428     child_ptr->remove_parent( parent );
03429     return MB_SUCCESS;
03430 }
03431 
03432 ErrorCode Core::remove_parent_meshset( EntityHandle meshset, const EntityHandle parent_meshset )
03433 {
03434     MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
03435     if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
03436     set_ptr->remove_parent( parent_meshset );
03437     return MB_SUCCESS;
03438 }
03439 
03440 ErrorCode Core::remove_child_meshset( EntityHandle meshset, const EntityHandle child_meshset )
03441 {
03442     MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
03443     if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
03444     set_ptr->remove_child( child_meshset );
03445     return MB_SUCCESS;
03446 }
03447 
03448 ErrorCode Core::get_last_error( std::string& info ) const
03449 {
03450     MBErrorHandler_GetLastError( info );
03451     return MB_SUCCESS;
03452 }
03453 
03454 std::string Core::get_error_string( const ErrorCode code ) const
03455 {
03456     return (unsigned)code <= (unsigned)MB_FAILURE ? ErrorCodeStr[code] : "INVALID ERROR CODE";
03457 }
03458 
03459 void Core::print( const EntityHandle ms_handle, const char* prefix, bool first_call ) const
03460 {
03461     // get the entities
03462     Range entities;
03463 
03464     if( 0 != ms_handle )
03465     {
03466         get_entities_by_handle( ms_handle, entities );
03467         std::cout << prefix << "MBENTITYSET " << ID_FROM_HANDLE( ms_handle ) << std::endl;
03468     }
03469     else
03470     {
03471         get_entities_by_dimension( 0, 3, entities );
03472         if( entities.empty() ) get_entities_by_dimension( 0, 2, entities );
03473         if( entities.empty() ) get_entities_by_dimension( 0, 1, entities );
03474         get_entities_by_dimension( 0, 0, entities );
03475         get_entities_by_type( 0, MBENTITYSET, entities );
03476         std::cout << prefix << "--: " << std::endl;
03477     }
03478 
03479     std::string indent_prefix = prefix;
03480     indent_prefix += "  ";
03481     entities.print( indent_prefix.c_str() );
03482 
03483     if( !first_call || !ms_handle ) return;
03484 
03485     // print parent/children
03486     Range temp;
03487     this->get_parent_meshsets( ms_handle, temp );
03488     std::cout << "  Parent sets: ";
03489     if( temp.empty() )
03490         std::cout << "(none)" << std::endl;
03491     else
03492     {
03493         for( Range::iterator rit = temp.begin(); rit != temp.end(); ++rit )
03494         {
03495             if( rit != temp.begin() ) std::cout << ", ";
03496             std::cout << ID_FROM_HANDLE( *rit );
03497         }
03498         std::cout << std::endl;
03499     }
03500 
03501     temp.clear();
03502     this->get_child_meshsets( ms_handle, temp );
03503     std::cout << "  Child sets: ";
03504     if( temp.empty() )
03505         std::cout << "(none)" << std::endl;
03506     else
03507     {
03508         for( Range::iterator rit = temp.begin(); rit != temp.end(); ++rit )
03509         {
03510             if( rit != temp.begin() ) std::cout << ", ";
03511             std::cout << ID_FROM_HANDLE( *rit );
03512         }
03513         std::cout << std::endl;
03514     }
03515 
03516     // print all sparse tags
03517     print_entity_tags( indent_prefix, ms_handle, MB_TAG_SPARSE );
03518 }
03519 
03520 ErrorCode Core::print_entity_tags( std::string indent_prefix, const EntityHandle handle, TagType tp ) const
03521 {
03522     std::vector< Tag > set_tags;
03523     ErrorCode result = this->tag_get_tags_on_entity( handle, set_tags );
03524     std::cout << indent_prefix << ( tp == MB_TAG_SPARSE ? "Sparse tags:" : "Dense tags:" ) << std::endl;
03525     indent_prefix += "  ";
03526 
03527     for( std::vector< Tag >::iterator vit = set_tags.begin(); vit != set_tags.end(); ++vit )
03528     {
03529         TagType this_type;
03530         result = this->tag_get_type( *vit, this_type );
03531         if( MB_SUCCESS != result || tp != this_type ) continue;
03532         DataType this_data_type;
03533         result = this->tag_get_data_type( *vit, this_data_type );
03534         if( MB_SUCCESS != result ) continue;
03535         int this_size;
03536         result = this->tag_get_length( *vit, this_size );
03537         if( MB_SUCCESS != result ) continue;
03538         // use double since this is largest single-valued tag
03539         std::vector< double > dbl_vals( this_size );
03540         std::vector< int > int_vals( this_size );
03541         std::vector< EntityHandle > hdl_vals( this_size );
03542         std::string tag_name;
03543         result = this->tag_get_name( *vit, tag_name );
03544         if( MB_SUCCESS != result ) continue;
03545         switch( this_data_type )
03546         {
03547             case MB_TYPE_INTEGER:
03548                 result = this->tag_get_data( *vit, &handle, 1, &int_vals[0] );
03549                 if( MB_SUCCESS != result ) continue;
03550                 std::cout << indent_prefix << tag_name << " = ";
03551                 if( this_size < 10 )
03552                     for( int i = 0; i < this_size; i++ )
03553                         std::cout << int_vals[i] << " ";
03554                 else
03555                     std::cout << int_vals[0] << "... (mult values)";
03556                 std::cout << std::endl;
03557                 break;
03558             case MB_TYPE_DOUBLE:
03559                 result = this->tag_get_data( *vit, &handle, 1, &dbl_vals[0] );
03560                 if( MB_SUCCESS != result ) continue;
03561                 std::cout << indent_prefix << tag_name << " = ";
03562                 if( this_size < 10 )
03563                     for( int i = 0; i < this_size; i++ )
03564                         std::cout << dbl_vals[i] << " ";
03565                 else
03566                     std::cout << dbl_vals[0] << "... (mult values)";
03567                 std::cout << std::endl;
03568                 break;
03569             case MB_TYPE_HANDLE:
03570                 result = this->tag_get_data( *vit, &handle, 1, &hdl_vals[0] );
03571                 if( MB_SUCCESS != result ) continue;
03572                 std::cout << indent_prefix << tag_name << " = ";
03573                 if( this_size < 10 )
03574                     for( int i = 0; i < this_size; i++ )
03575                         std::cout << hdl_vals[i] << " ";
03576                 else
03577                     std::cout << hdl_vals[0] << "... (mult values)";
03578                 std::cout << std::endl;
03579                 break;
03580             case MB_TYPE_OPAQUE:
03581                 if( NAME_TAG_SIZE == this_size )
03582                 {
03583                     char dum_tag[NAME_TAG_SIZE];
03584                     result = this->tag_get_data( *vit, &handle, 1, &dum_tag );
03585                     if( MB_SUCCESS != result ) continue;
03586                     // insert NULL just in case there isn't one
03587                     dum_tag[NAME_TAG_SIZE - 1] = '\0';
03588                     std::cout << indent_prefix << tag_name << " = " << dum_tag << std::endl;
03589                 }
03590                 break;
03591             case MB_TYPE_BIT:
03592                 break;
03593         }
03594     }
03595 
03596     return MB_SUCCESS;
03597 }
03598 
03599 ErrorCode Core::check_adjacencies()
03600 {
03601     // run through all entities, checking adjacencies and reverse-evaluating them
03602     Range all_ents;
03603     ErrorCode result = get_entities_by_handle( 0, all_ents );MB_CHK_ERR( result );
03604 
03605     for( Range::iterator rit = all_ents.begin(); rit != all_ents.end(); ++rit )
03606     {
03607         result = check_adjacencies( &( *rit ), 1 );MB_CHK_ERR( result );
03608     }
03609 
03610     return MB_SUCCESS;
03611 }
03612 
03613 ErrorCode Core::check_adjacencies( const EntityHandle* ents, int num_ents )
03614 {
03615 
03616     ErrorCode result = MB_SUCCESS, tmp_result;
03617     std::ostringstream oss;
03618 
03619     for( int i = 0; i < num_ents; i++ )
03620     {
03621         EntityHandle this_ent = ents[i];
03622         std::ostringstream ent_str;
03623         ent_str << CN::EntityTypeName( TYPE_FROM_HANDLE( this_ent ) ) << " " << ID_FROM_HANDLE( this_ent ) << ": ";
03624         int this_dim = dimension_from_handle( this_ent );
03625 
03626         if( !is_valid( this_ent ) )
03627         {
03628             std::cerr << ent_str.str() << "Not a valid entity." << std::endl;
03629             result = MB_FAILURE;
03630         }
03631 
03632         else
03633         {
03634             if( TYPE_FROM_HANDLE( this_ent ) == MBENTITYSET ) continue;
03635 
03636             // get adjacencies for this entity
03637             Range adjs;
03638             for( int dim = 0; dim <= 3; dim++ )
03639             {
03640                 if( dim == this_dim ) continue;
03641                 tmp_result = get_adjacencies( &this_ent, 1, dim, false, adjs, Interface::UNION );
03642                 if( MB_SUCCESS != tmp_result )
03643                 {
03644                     oss << ent_str.str() << "Failed to get adjacencies for dimension " << dim << "." << std::endl;
03645                     result = tmp_result;
03646                 }
03647             }
03648             if( !oss.str().empty() )
03649             {
03650                 std::cerr << oss.str();
03651                 oss.str( "" );
03652             }
03653 
03654             // now check and reverse-evaluate them
03655             for( Range::iterator rit = adjs.begin(); rit != adjs.end(); ++rit )
03656             {
03657                 EntitySequence* seq = 0;
03658                 tmp_result          = sequence_manager()->find( *rit, seq );
03659                 if( seq == 0 || tmp_result != MB_SUCCESS )
03660                 {
03661                     oss << ent_str.str() << "Adjacent entity " << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " "
03662                         << ID_FROM_HANDLE( *rit ) << " is invalid." << std::endl;
03663                     result = tmp_result;
03664                 }
03665                 else
03666                 {
03667                     Range rev_adjs;
03668                     tmp_result = get_adjacencies( &( *rit ), 1, this_dim, false, rev_adjs );
03669                     if( MB_SUCCESS != tmp_result )
03670                     {
03671                         oss << ent_str.str() << "Failed to get reverse adjacency from "
03672                             << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " " << ID_FROM_HANDLE( *rit );
03673                         if( MB_MULTIPLE_ENTITIES_FOUND == tmp_result )
03674                             oss << " (MULTIPLE)" << std::endl;
03675                         else
03676                             oss << " (" << tmp_result << ")" << std::endl;
03677                         result = tmp_result;
03678                     }
03679                     else if( rev_adjs.find( this_ent ) == rev_adjs.end() )
03680                     {
03681                         oss << ent_str.str() << "Failed to find adjacency to this entity from "
03682                             << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " " << ID_FROM_HANDLE( *rit ) << "."
03683                             << std::endl;
03684                         result = tmp_result;
03685                     }
03686                 }
03687                 if( !oss.str().empty() )
03688                 {
03689                     std::cerr << oss.str();
03690                     oss.str( "" );
03691                 }
03692             }
03693         }
03694     }
03695 
03696     return result;
03697 }
03698 
03699 bool Core::is_valid( const EntityHandle this_ent ) const
03700 {
03701     const EntitySequence* seq = 0;
03702     ErrorCode result          = sequence_manager()->find( this_ent, seq );
03703     return seq != 0 && result == MB_SUCCESS;
03704 }
03705 
03706 ErrorCode Core::create_set_iterator( EntityHandle meshset, EntityType ent_type, int ent_dim, int chunk_size,
03707                                      bool check_valid, SetIterator*& set_iter )
03708 {
03709     // check the type of set
03710     unsigned int setoptions;
03711     ErrorCode rval = MB_SUCCESS;
03712     if( meshset )
03713     {
03714         rval = get_meshset_options( meshset, setoptions );MB_CHK_ERR( rval );
03715     }
03716 
03717     if( !meshset || ( setoptions & MESHSET_SET ) )
03718         set_iter = new( std::nothrow ) RangeSetIterator( this, meshset, chunk_size, ent_type, ent_dim, check_valid );
03719     else
03720         set_iter = new( std::nothrow ) VectorSetIterator( this, meshset, chunk_size, ent_type, ent_dim, check_valid );
03721 
03722     setIterators.push_back( set_iter );
03723     return MB_SUCCESS;
03724 }
03725 
03726 /** \brief Remove the set iterator from the instance's list
03727  * This function is called from the SetIterator destructor, and should not be called directly
03728  * from anywhere else.
03729  * \param set_iter Set iterator being removed
03730  */
03731 ErrorCode Core::remove_set_iterator( SetIterator* set_iter )
03732 {
03733     std::vector< SetIterator* >::iterator vit = std::find( setIterators.begin(), setIterators.end(), set_iter );
03734     if( vit == setIterators.end() ) { MB_SET_ERR( MB_FAILURE, "Didn't find that iterator" ); }
03735 
03736     setIterators.erase( vit );
03737 
03738     return MB_SUCCESS;
03739 }
03740 
03741 /** \brief Get all set iterators associated with the set passed in
03742  * \param meshset Meshset for which iterators are requested
03743  * \param set_iters Set iterators for the set
03744  */
03745 ErrorCode Core::get_set_iterators( EntityHandle meshset, std::vector< SetIterator* >& set_iters )
03746 {
03747     for( std::vector< SetIterator* >::const_iterator vit = setIterators.begin(); vit != setIterators.end(); ++vit )
03748         if( ( *vit )->ent_set() == meshset ) set_iters.push_back( *vit );
03749     return MB_SUCCESS;
03750 }
03751 
03752 void Core::estimated_memory_use_internal( const Range* ents, type_memstorage* total_storage,
03753                                           type_memstorage* total_amortized_storage, type_memstorage* entity_storage,
03754                                           type_memstorage* amortized_entity_storage, type_memstorage* adjacency_storage,
03755                                           type_memstorage* amortized_adjacency_storage, const Tag* tag_array,
03756                                           unsigned num_tags, type_memstorage* tag_storage,
03757                                           type_memstorage* amortized_tag_storage )
03758 {
03759     // Figure out which values we need to calculate
03760     type_memstorage i_entity_storage, ia_entity_storage, i_adjacency_storage, ia_adjacency_storage, i_tag_storage,
03761         ia_tag_storage;
03762     type_memstorage *total_tag_storage = 0, *amortized_total_tag_storage = 0;
03763     if( !tag_array )
03764     {
03765         total_tag_storage           = tag_storage;
03766         amortized_total_tag_storage = amortized_tag_storage;
03767     }
03768     if( total_storage || total_amortized_storage )
03769     {
03770         if( !entity_storage ) entity_storage = &i_entity_storage;
03771         if( !amortized_entity_storage ) amortized_entity_storage = &ia_entity_storage;
03772         if( !adjacency_storage ) adjacency_storage = &i_adjacency_storage;
03773         if( !amortized_adjacency_storage ) amortized_adjacency_storage = &ia_adjacency_storage;
03774     }
03775     else
03776     {
03777         if( entity_storage || amortized_entity_storage )
03778         {
03779             if( !amortized_entity_storage )
03780                 amortized_entity_storage = &ia_entity_storage;
03781             else if( !entity_storage )
03782                 entity_storage = &i_entity_storage;
03783         }
03784         if( adjacency_storage || amortized_adjacency_storage )
03785         {
03786             if( !amortized_adjacency_storage )
03787                 amortized_adjacency_storage = &ia_adjacency_storage;
03788             else if( !adjacency_storage )
03789                 adjacency_storage = &i_adjacency_storage;
03790         }
03791     }
03792     if( !total_tag_storage && total_storage ) total_tag_storage = &i_tag_storage;
03793     if( !amortized_total_tag_storage && total_amortized_storage ) amortized_total_tag_storage = &ia_tag_storage;
03794 
03795     // get entity storage
03796     if( amortized_entity_storage )
03797     {
03798         if( ents )
03799             sequenceManager->get_memory_use( *ents, *entity_storage, *amortized_entity_storage );
03800         else
03801             sequenceManager->get_memory_use( *entity_storage, *amortized_entity_storage );
03802     }
03803 
03804     // get adjacency storage
03805     if( amortized_adjacency_storage )
03806     {
03807         if( ents )
03808             aEntityFactory->get_memory_use( *ents, *adjacency_storage, *amortized_adjacency_storage );
03809         else
03810 #ifdef MOAB_HAVE_AHF
03811             ahfRep->get_memory_use( *adjacency_storage, *amortized_adjacency_storage );
03812 #else
03813             aEntityFactory->get_memory_use( *adjacency_storage, *amortized_adjacency_storage );
03814 #endif
03815     }
03816 
03817     // get storage for requested list of tags
03818     if( tag_array )
03819     {
03820         for( unsigned i = 0; i < num_tags; ++i )
03821         {
03822             if( !valid_tag_handle( tag_array[i] ) ) continue;
03823 
03824             unsigned long total = 0, per_ent = 0;
03825             tag_array[i]->get_memory_use( sequenceManager, total, per_ent );
03826 
03827             if( ents )
03828             {
03829                 size_t count = 0, count2 = 0;
03830                 tag_array[i]->num_tagged_entities( sequenceManager, count, MBMAXTYPE, ents );
03831                 if( tag_storage ) tag_storage[i] = count * per_ent;
03832                 if( amortized_tag_storage )
03833                 {
03834                     tag_array[i]->num_tagged_entities( sequenceManager, count2 );
03835                     if( count2 )
03836                         amortized_tag_storage[i] = static_cast< type_memstorage >( total * count * 1.0 / count2 );
03837                 }
03838             }
03839             else
03840             {
03841                 size_t count = 0;
03842                 if( tag_storage )
03843                 {
03844                     tag_array[i]->num_tagged_entities( sequenceManager, count );
03845                     tag_storage[i] = count * per_ent;
03846                 }
03847                 if( amortized_tag_storage ) amortized_tag_storage[i] = total;
03848             }
03849         }
03850     }
03851 
03852     // get storage for all tags
03853     if( total_tag_storage || amortized_total_tag_storage )
03854     {
03855         if( amortized_total_tag_storage ) *amortized_total_tag_storage = 0;
03856         if( total_tag_storage ) *total_tag_storage = 0;
03857 
03858         std::vector< Tag > tags;
03859         tag_get_tags( tags );
03860         for( std::list< TagInfo* >::const_iterator i = tagList.begin(); i != tagList.end(); ++i )
03861         {
03862             unsigned long total = 0, per_ent = 0;
03863             ( *i )->get_memory_use( sequenceManager, total, per_ent );
03864 
03865             if( ents )
03866             {
03867                 size_t count = 0, count2 = 0;
03868                 ( *i )->num_tagged_entities( sequenceManager, count, MBMAXTYPE, ents );
03869                 if( total_tag_storage ) *total_tag_storage += count * per_ent;
03870                 if( amortized_total_tag_storage )
03871                 {
03872                     ( *i )->num_tagged_entities( sequenceManager, count2 );
03873                     if( count2 )
03874                         *amortized_total_tag_storage += static_cast< type_memstorage >( total * count * 1.0 / count2 );
03875                 }
03876             }
03877             else
03878             {
03879                 size_t count = 0;
03880                 if( total_tag_storage )
03881                 {
03882                     ( *i )->num_tagged_entities( sequenceManager, count );
03883                     *total_tag_storage += count * per_ent;
03884                 }
03885                 if( amortized_total_tag_storage ) *amortized_total_tag_storage += total;
03886             }
03887         }
03888     }
03889 
03890     // calculate totals
03891     if( total_storage ) *total_storage = *entity_storage + *adjacency_storage + *total_tag_storage;
03892 
03893     if( total_amortized_storage )
03894         *total_amortized_storage =
03895             *amortized_entity_storage + *amortized_adjacency_storage + *amortized_total_tag_storage;
03896 }
03897 
03898 void Core::estimated_memory_use( const EntityHandle* ent_array, unsigned long num_ents, type_memstorage* total_storage,
03899                                  type_memstorage* total_amortized_storage, type_memstorage* entity_storage,
03900                                  type_memstorage* amortized_entity_storage, type_memstorage* adjacency_storage,
03901                                  type_memstorage* amortized_adjacency_storage, const Tag* tag_array, unsigned num_tags,
03902                                  type_memstorage* tag_storage, type_memstorage* amortized_tag_storage )
03903 {
03904     Range range;
03905 
03906     // If non-empty entity list, call range version of function
03907     if( ent_array )
03908     {
03909         if( num_ents > 20 )
03910         {
03911             std::vector< EntityHandle > list( num_ents );
03912             std::copy( ent_array, ent_array + num_ents, list.begin() );
03913             std::sort( list.begin(), list.end() );
03914             Range::iterator j = range.begin();
03915             for( std::vector< EntityHandle >::reverse_iterator i = list.rbegin(); i != list.rend(); ++i )
03916                 j = range.insert( j, *i, *i );
03917         }
03918         else
03919         {
03920             std::copy( ent_array, ent_array + num_ents, range_inserter( range ) );
03921         }
03922     }
03923 
03924     estimated_memory_use_internal( ent_array ? &range : 0, total_storage, total_amortized_storage, entity_storage,
03925                                    amortized_entity_storage, adjacency_storage, amortized_adjacency_storage, tag_array,
03926                                    num_tags, tag_storage, amortized_tag_storage );
03927 }
03928 
03929 void Core::estimated_memory_use( const Range& ents, type_memstorage* total_storage,
03930                                  type_memstorage* total_amortized_storage, type_memstorage* entity_storage,
03931                                  type_memstorage* amortized_entity_storage, type_memstorage* adjacency_storage,
03932                                  type_memstorage* amortized_adjacency_storage, const Tag* tag_array, unsigned num_tags,
03933                                  type_memstorage* tag_storage, type_memstorage* amortized_tag_storage )
03934 {
03935     estimated_memory_use_internal( &ents, total_storage, total_amortized_storage, entity_storage,
03936                                    amortized_entity_storage, adjacency_storage, amortized_adjacency_storage, tag_array,
03937                                    num_tags, tag_storage, amortized_tag_storage );
03938 }
03939 
03940 void Core::print_database() const
03941 {
03942     ErrorCode rval;
03943     TypeSequenceManager::const_iterator i;
03944     const TypeSequenceManager& verts = sequence_manager()->entity_map( MBVERTEX );
03945     if( !verts.empty() )
03946         printf( "  Vertex ID  X        Y        Z        Adjacencies   \n"
03947                 "  ---------- -------- -------- -------- -----------...\n" );
03948     const EntityHandle* adj;
03949     int nadj;
03950     for( i = verts.begin(); i != verts.end(); ++i )
03951     {
03952         const VertexSequence* seq = static_cast< const VertexSequence* >( *i );
03953         printf( "(Sequence [%d,%d] in SequenceData [%d,%d])\n", (int)ID_FROM_HANDLE( seq->start_handle() ),
03954                 (int)ID_FROM_HANDLE( seq->end_handle() ), (int)ID_FROM_HANDLE( seq->data()->start_handle() ),
03955                 (int)ID_FROM_HANDLE( seq->data()->end_handle() ) );
03956 
03957         double c[3];
03958         for( EntityHandle h = seq->start_handle(); h <= seq->end_handle(); ++h )
03959         {
03960             rval = seq->get_coordinates( h, c );
03961             if( MB_SUCCESS == rval )
03962                 printf( "  %10d %8g %8g %8g", (int)ID_FROM_HANDLE( h ), c[0], c[1], c[2] );
03963             else
03964                 printf( "  %10d <       ERROR %4d       >", (int)ID_FROM_HANDLE( h ), (int)rval );
03965 
03966             rval = a_entity_factory()->get_adjacencies( h, adj, nadj );
03967             if( MB_SUCCESS != rval )
03968             {
03969                 printf( " <ERROR %d>\n", (int)rval );
03970                 continue;
03971             }
03972             EntityType pt = MBMAXTYPE;
03973             for( int j = 0; j < nadj; ++j )
03974             {
03975                 if( TYPE_FROM_HANDLE( adj[j] ) != pt )
03976                 {
03977                     pt = TYPE_FROM_HANDLE( adj[j] );
03978                     printf( "  %s", pt >= MBMAXTYPE ? "INVALID TYPE" : CN::EntityTypeName( pt ) );
03979                 }
03980                 printf( " %d", (int)ID_FROM_HANDLE( adj[j] ) );
03981             }
03982             printf( "\n" );
03983         }
03984     }
03985 
03986     for( EntityType t = MBEDGE; t < MBENTITYSET; ++t )
03987     {
03988         const TypeSequenceManager& elems = sequence_manager()->entity_map( t );
03989         if( elems.empty() ) continue;
03990 
03991         int clen = 0;
03992         for( i = elems.begin(); i != elems.end(); ++i )
03993         {
03994             int n = static_cast< const ElementSequence* >( *i )->nodes_per_element();
03995             if( n > clen ) clen = n;
03996         }
03997 
03998         clen *= 5;
03999         if( clen < (int)strlen( "Connectivity" ) ) clen = strlen( "Connectivity" );
04000         std::vector< char > dashes( clen, '-' );
04001         dashes.push_back( '\0' );
04002         printf( "  %7s ID %-*s Adjacencies\n", CN::EntityTypeName( t ), clen, "Connectivity" );
04003         printf( "  ---------- %s -----------...\n", &dashes[0] );
04004 
04005         std::vector< EntityHandle > storage;
04006         const EntityHandle* conn;
04007         int nconn;
04008         for( i = elems.begin(); i != elems.end(); ++i )
04009         {
04010             const ElementSequence* seq = static_cast< const ElementSequence* >( *i );
04011             printf( "(Sequence [%d,%d] in SequenceData [%d,%d])\n", (int)ID_FROM_HANDLE( seq->start_handle() ),
04012                     (int)ID_FROM_HANDLE( seq->end_handle() ), (int)ID_FROM_HANDLE( seq->data()->start_handle() ),
04013                     (int)ID_FROM_HANDLE( seq->data()->end_handle() ) );
04014 
04015             for( EntityHandle h = seq->start_handle(); h <= seq->end_handle(); ++h )
04016             {
04017                 printf( "  %10d", (int)ID_FROM_HANDLE( h ) );
04018                 rval = get_connectivity( h, conn, nconn, false, &storage );
04019                 if( MB_SUCCESS != rval )
04020                     printf( "  <ERROR %2d>%*s", (int)rval, clen - 10, "" );
04021                 else
04022                 {
04023                     for( int j = 0; j < nconn; ++j )
04024                         printf( " %4d", (int)ID_FROM_HANDLE( conn[j] ) );
04025                     printf( "%*s", clen - 5 * nconn, "" );
04026                 }
04027 
04028                 rval = a_entity_factory()->get_adjacencies( h, adj, nadj );
04029                 if( MB_SUCCESS != rval )
04030                 {
04031                     printf( " <ERROR %d>\n", (int)rval );
04032                     continue;
04033                 }
04034                 EntityType pt = MBMAXTYPE;
04035                 for( int j = 0; j < nadj; ++j )
04036                 {
04037                     if( TYPE_FROM_HANDLE( adj[j] ) != pt )
04038                     {
04039                         pt = TYPE_FROM_HANDLE( adj[j] );
04040                         printf( "  %s", pt >= MBMAXTYPE ? "INVALID TYPE" : CN::EntityTypeName( pt ) );
04041                     }
04042                     printf( " %d", (int)ID_FROM_HANDLE( adj[j] ) );
04043                 }
04044                 printf( "\n" );
04045             }
04046         }
04047     }
04048 }
04049 
04050 ErrorCode Core::create_scd_sequence( const HomCoord& coord_min, const HomCoord& coord_max, EntityType entity_type,
04051                                      EntityID start_id_hint, EntityHandle& first_handle_out,
04052                                      EntitySequence*& sequence_out )
04053 {
04054     // NR: Previously, the structured element sequences were created via direct call to
04055     // the sequence manager instead of using the same from the ScdInterface which
04056     // creates the associated scd bounding box after element sequence creation.
04057 
04058     if( !scdInterface ) scdInterface = new ScdInterface( this );
04059     ScdBox* newBox = NULL;
04060     ErrorCode rval = scdInterface->create_scd_sequence( coord_min, coord_max, entity_type,
04061                                                         /*starting_id*/ (int)start_id_hint, newBox );MB_CHK_ERR( rval );
04062 
04063     if( MBVERTEX == entity_type )
04064         first_handle_out = newBox->get_vertex( coord_min );
04065     else
04066         first_handle_out = newBox->get_element( coord_min );
04067     return sequence_manager()->find( first_handle_out, sequence_out );
04068 }
04069 
04070 ErrorCode Core::add_vsequence( EntitySequence* vert_seq, EntitySequence* elem_seq, const HomCoord& p1,
04071                                const HomCoord& q1, const HomCoord& p2, const HomCoord& q2, const HomCoord& p3,
04072                                const HomCoord& q3, bool bb_input, const HomCoord* bb_min, const HomCoord* bb_max )
04073 {
04074     return sequence_manager()->add_vsequence( vert_seq, elem_seq, p1, q1, p2, q2, p3, q3, bb_input, bb_min, bb_max );
04075 }
04076 
04077 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines