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