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