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