Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
Core.cpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #ifdef WIN32
17 // turn off warnings that say they debugging identifier has been truncated
18 // this warning comes up when using some STL containers
19 #pragma warning( disable : 4786 )
20 #endif
21 
22 #define MOAB_MPE_LOG "moab.mpe"
23 
24 #include <iostream>
25 #include <sstream>
26 #include <vector>
27 #include <string>
28 #include <algorithm>
29 #include "moab/Core.hpp"
30 #include "MeshSetSequence.hpp"
31 #include "ElementSequence.hpp"
32 #include "VertexSequence.hpp"
33 #include <cassert>
34 #include "AEntityFactory.hpp"
35 #include "ReadUtil.hpp"
36 #include "WriteUtil.hpp"
37 #include "moab/CN.hpp"
39 #include "SequenceManager.hpp"
40 #include "moab/Error.hpp"
41 #include "moab/ReaderWriterSet.hpp"
42 #include "moab/ReaderIface.hpp"
43 #include "moab/WriterIface.hpp"
44 #include "moab/ScdInterface.hpp"
45 #include "moab/SetIterator.hpp"
46 
47 #include "BitTag.hpp"
48 #include "DenseTag.hpp"
49 #include "MeshTag.hpp"
50 #include "SparseTag.hpp"
51 #include "VarLenDenseTag.hpp"
52 #include "VarLenSparseTag.hpp"
53 
54 #include <sys/stat.h>
55 #include <cerrno>
56 #include <cstring>
57 
58 #ifdef MOAB_HAVE_AHF
59 #include "moab/HalfFacetRep.hpp"
60 #endif
61 
62 #ifdef MOAB_HAVE_MPI
63 /* Leave ParallelComm.hpp before mpi.h or MPICH2 will fail
64  * because its C++ headers do not like SEEK_* macros.
65  */
66 #include "moab/ParallelComm.hpp"
67 #include "moab_mpi.h"
68 #include "ReadParallel.hpp"
69 #endif
70 
71 #ifdef MOAB_HAVE_HDF5
72 #ifdef MOAB_HAVE_HDF5_PARALLEL
73 #include "WriteHDF5Parallel.hpp"
75 #define DefaultWriterName "WriteHDF5Parallel"
76 #else
77 #include "WriteHDF5.hpp"
79 #define DefaultWriterName "WriteHDF5"
80 #endif
81 #elif defined( MOAB_HAVE_NETCDF )
82 #include "WriteNCDF.hpp"
84 #define DefaultWriterName "WriteNCDF"
85 #else
86 #include "WriteVtk.hpp"
88 #define DefaultWriterName "WriteVtk"
89 #endif
90 #include "MBTagConventions.hpp"
91 #include "ExoIIUtil.hpp"
92 #include "EntitySequence.hpp"
93 #include "moab/FileOptions.hpp"
94 #ifdef LINUX
95 #include <dlfcn.h>
96 #include <dirent.h>
97 #endif
98 
99 #ifdef MOAB_HAVE_MPI
100 #include "moab_mpe.h"
101 #endif
102 
103 // MOAB used to use a NULL handle list and a zero handle count
104 // to indicate that tag functions are to operate on the global/mesh
105 // value of the tag. For the 3.0 release MOAB also accepted a handle
106 // with a value of 0 to indicate the same. Now we want to drop the
107 // old NULL list method because a) it is one less special case that
108 // must be handled in the tag get/set paths and b) it aviods unexpected
109 // segfaults when applications requested tag data with an empty list
110 // of handles.
111 //
112 // Define this constant to revert to the old behavior, but also print
113 // a warning.
114 #define ALLOW_NULL_FOR_MESH_TAG
115 //
116 // Define this to print an error and abort() when a NULL handle list
117 // is passed. This is intended as an interim solution to help catch
118 // spots in code that haven't been updated for the change.
119 #undef DISALLOW_EMPTY_HANDLE_LIST_FOR_TAGS
120 //
121 // The eventual goal is to define neither of the above, eliminating the
122 // check and allowing applications to safely request tag data for no
123 // entities.
124 
126 {
127  std::cerr << "WARNING: Accepting empty array to indicate mesh tag" << std::endl;
128 }
129 
130 #ifdef ALLOW_NULL_FOR_MESH_TAG
131 #define CHECK_MESH_NULL \
132  EntityHandle root = 0; \
133  if( NULL == entity_handles && 0 == num_entities ) \
134  { \
135  entity_handles = &root; \
136  num_entities = 1; \
137  warn_null_array_mesh_tag(); \
138  }
139 #elif defined( DISALLOW_EMPTY_HANDLE_LIST_FOR_TAGS )
140 #define CHECK_MESH_NULL \
141  if( NULL == entity_handles ) \
142  { \
143  std::cerr << "ERROR: Deprecated NULL handle list at " __FILE__ ":" << __LINE__ << std::endl; \
144  abort(); \
145  }
146 #else
147 #define CHECK_MESH_NULL
148 #endif
149 
150 namespace moab
151 {
152 
153 using namespace std;
154 
155 static inline const MeshSet* get_mesh_set( const SequenceManager* sm, EntityHandle h )
156 {
157  const EntitySequence* seq;
158  if( MBENTITYSET != TYPE_FROM_HANDLE( h ) || MB_SUCCESS != sm->find( h, seq ) ) return 0;
159  return reinterpret_cast< const MeshSetSequence* >( seq )->get_set( h );
160 }
161 
163 {
164  EntitySequence* seq;
165  if( MBENTITYSET != TYPE_FROM_HANDLE( h ) || MB_SUCCESS != sm->find( h, seq ) ) return 0;
166  return reinterpret_cast< MeshSetSequence* >( seq )->get_set( h );
167 }
168 
169 //! Constructor
171 {
172  if( initialize() != MB_SUCCESS )
173  {
174  printf( "Error initializing moab::Core\n" );
175  exit( 1 );
176  }
177 }
178 
179 //! destructor
181 {
182  if( mMBWriteUtil ) delete mMBWriteUtil;
183  if( mMBReadUtil ) delete mMBReadUtil;
184  if( scdInterface ) delete scdInterface;
185 
186  mMBWriteUtil = NULL;
187  mMBReadUtil = NULL;
188  scdInterface = NULL;
189 
190  deinitialize();
191 }
192 
194 {
195 #ifdef MOAB_HAVE_MPI
196  int flag;
197  if( MPI_SUCCESS == MPI_Initialized( &flag ) )
198  {
199  if( flag )
200  {
201  writeMPELog = !MPE_Initialized_logging();
202  if( writeMPELog ) (void)MPE_Init_log();
203  }
204  }
205 #endif
206 
207  initErrorHandlerInCore = false;
209  {
211  initErrorHandlerInCore = true;
212  }
213 
214  geometricDimension = 3;
215  materialTag = 0;
216  neumannBCTag = 0;
217  dirichletBCTag = 0;
218  geomDimensionTag = 0;
219  globalIdTag = 0;
220 
221  sequenceManager = new( std::nothrow ) SequenceManager;
222  if( !sequenceManager ) return MB_MEMORY_ALLOCATION_FAILED;
223 
224  aEntityFactory = new( std::nothrow ) AEntityFactory( this );
225  if( !aEntityFactory ) return MB_MEMORY_ALLOCATION_FAILED;
226 
227  mError = new( std::nothrow ) Error;
228  if( !mError ) return MB_MEMORY_ALLOCATION_FAILED;
229 
230  mMBWriteUtil = NULL;
231  mMBReadUtil = NULL;
232  scdInterface = NULL;
233 
234  // Readers and writers try to get pointers to above utils.
235  // Do this after pointers are initialized. (Pointers should
236  // really be initialized in constructor to avoid this kind
237  // of thing -- j.kraftcheck.)
238  readerWriterSet = new( std::nothrow ) ReaderWriterSet( this );
239  if( !readerWriterSet ) return MB_MEMORY_ALLOCATION_FAILED;
240 
241  material_tag();
242  neumannBC_tag();
243  dirichletBC_tag();
244  geom_dimension_tag();
245  globalId_tag();
246 
247 #ifdef MOAB_HAVE_AHF
248  ahfRep = new HalfFacetRep( this );
249  if( !ahfRep ) return MB_MEMORY_ALLOCATION_FAILED;
250  mesh_modified = false;
251 #endif
252 
253  return MB_SUCCESS;
254 }
255 
257 {
258  return 0;
259 }
260 
262 {
263 
264 #ifdef MOAB_HAVE_MPI
265  std::vector< ParallelComm* > pc_list;
266  ParallelComm::get_all_pcomm( this, pc_list );
267  for( std::vector< ParallelComm* >::iterator vit = pc_list.begin(); vit != pc_list.end(); ++vit )
268  delete *vit;
269 #endif
270 
271 #ifdef MOAB_HAVE_AHF
272  delete ahfRep;
273  ahfRep = 0;
274 #endif
275 
276  if( aEntityFactory ) delete aEntityFactory;
277 
278  aEntityFactory = 0;
279 
280  while( !tagList.empty() )
281  tag_delete( tagList.front() );
282 
283  if( sequenceManager ) delete sequenceManager;
284 
285  sequenceManager = 0;
286 
287  delete readerWriterSet;
288  readerWriterSet = 0;
289 
290  if( mError ) delete mError;
291  mError = 0;
292 
293 #ifdef MOAB_HAVE_MPI
294  if( writeMPELog )
295  {
296  const char* default_log = MOAB_MPE_LOG;
297  const char* logfile = getenv( "MPE_LOG_FILE" );
298  if( !logfile ) logfile = default_log;
299  MPE_Finish_log( logfile );
300  }
301 #endif
302 
303  if( initErrorHandlerInCore ) MBErrorHandler_Finalize();
304 }
305 
306 ErrorCode Core::query_interface_type( const std::type_info& interface_type, void*& ptr )
307 {
308  if( interface_type == typeid( ReadUtilIface ) )
309  {
310  if( !mMBReadUtil ) mMBReadUtil = new ReadUtil( this, mError );
311  ptr = static_cast< ReadUtilIface* >( mMBReadUtil );
312  }
313  else if( interface_type == typeid( WriteUtilIface ) )
314  {
315  if( !mMBWriteUtil ) mMBWriteUtil = new WriteUtil( this );
316  ptr = static_cast< WriteUtilIface* >( mMBWriteUtil );
317  }
318  else if( interface_type == typeid( ReaderWriterSet ) )
319  {
320  ptr = reader_writer_set();
321  }
322  else if( interface_type == typeid( Error ) )
323  {
324  ptr = mError;
325  }
326  else if( interface_type == typeid( ExoIIInterface ) )
327  {
328  ptr = static_cast< ExoIIInterface* >( new ExoIIUtil( this ) );
329  }
330  else if( interface_type == typeid( ScdInterface ) )
331  {
332  if( !scdInterface ) scdInterface = new ScdInterface( this );
333  ptr = scdInterface;
334  }
335  else
336  {
337  ptr = 0;
338  return MB_FAILURE;
339  }
340  return MB_SUCCESS;
341 }
342 
343 ErrorCode Core::release_interface_type( const std::type_info& interface_type, void* iface )
344 {
345  if( interface_type == typeid( ExoIIInterface ) )
346  delete static_cast< ExoIIInterface* >( iface );
347  else if( interface_type != typeid( ReadUtilIface ) && interface_type != typeid( WriteUtilIface ) &&
348  interface_type != typeid( ReaderWriterSet ) && interface_type != typeid( Error ) &&
349  interface_type != typeid( ScdInterface ) )
350  return MB_FAILURE;
351 
352  return MB_SUCCESS;
353 }
354 
356 {
357  *iface = 0;
358  if( uuid == IDD_MBUnknown ) *iface = this;
359  if( uuid == IDD_MBCore )
360  *iface = this;
361  else
362  return 0;
363  return 1;
364 }
365 
366 float Core::impl_version( std::string* version_string )
367 {
368  if( version_string ) *version_string = MOAB_PACKAGE_VERSION_STRING;
369 
371 }
372 
373 //! get the type from a handle, returns type
374 EntityType Core::type_from_handle( const EntityHandle handle ) const
375 {
376  if( !handle ) // root set
377  return MBENTITYSET;
378  else
379  return TYPE_FROM_HANDLE( handle );
380 }
381 
382 //! get the id from a handle, returns id
384 {
385  return ID_FROM_HANDLE( handle );
386 }
387 
388 //! get a handle from an id and type
389 ErrorCode Core::handle_from_id( const EntityType entity_type, const EntityID id, EntityHandle& handle ) const
390 {
391  int err;
392  handle = CREATE_HANDLE( entity_type, id, err );
393 
394  // check to see if handle exists
395  const EntitySequence* dummy_seq = 0;
396  ErrorCode error_code = sequence_manager()->find( handle, dummy_seq );
397  return error_code;
398 }
399 
400 int Core::dimension_from_handle( const EntityHandle handle ) const
401 {
402  if( !handle ) // root set
403  return 4;
404  else
405  return CN::Dimension( TYPE_FROM_HANDLE( handle ) );
406 }
407 
408 //! load mesh from data in file
409 //! NOTE: if there is mesh already present, the new mesh will be added
410 ErrorCode Core::load_mesh( const char* file_name, const int* block_id_list, const int num_blocks )
411 {
412  const char* name = block_id_list ? MATERIAL_SET_TAG_NAME : 0;
413  return load_file( file_name, 0, 0, name, block_id_list, num_blocks );
414 }
415 
416 ErrorCode Core::load_file( const char* file_name,
417  const EntityHandle* file_set,
418  const char* setoptions,
419  const char* set_tag_name,
420  const int* set_tag_vals,
421  int num_set_tag_vals )
422 {
423  FileOptions opts( setoptions );
424  ErrorCode rval;
425  ReaderIface::IDTag t = { set_tag_name, set_tag_vals, num_set_tag_vals };
426  ReaderIface::SubsetList sl = { &t, 1, 0, 0 };
427 
428  assert( !file_set || ( *file_set && is_valid( *file_set ) ) );
429  if( file_set && !*file_set )
430  {
431  MB_SET_GLB_ERR( MB_FAILURE, "Non-NULL file set pointer should point to non-NULL set" );
432  }
433 
434  // if reading in parallel, call a different reader
435  std::string parallel_opt;
436  rval = opts.get_option( "PARALLEL", parallel_opt );
437  if( MB_SUCCESS == rval )
438  {
439 #ifdef MOAB_HAVE_MPI
440  ParallelComm* pcomm = 0;
441  int pcomm_id;
442  rval = opts.get_int_option( "PARALLEL_COMM", pcomm_id );
443  if( MB_ENTITY_NOT_FOUND == rval ) rval = opts.get_int_option( "PCOMM", pcomm_id );
444  if( rval == MB_SUCCESS )
445  {
446  pcomm = ParallelComm::get_pcomm( this, pcomm_id );
447  if( !pcomm ) return MB_ENTITY_NOT_FOUND;
448  }
449  else if( rval != MB_ENTITY_NOT_FOUND )
450  return rval;
451  if( set_tag_name && num_set_tag_vals )
452  {
453  MB_CHK_SET_ERR( ReadParallel( this, pcomm ).load_file( file_name, file_set, opts, &sl ),
454  "can't load subset file in parallel" );
455  }
456  else
457  {
458  MB_CHK_SET_ERR( ReadParallel( this, pcomm ).load_file( file_name, file_set, opts ),
459  "can't load file in parallel" );
460  }
461 #else
462  MB_SET_GLB_ERR( MB_FAILURE, "PARALLEL option not valid, this instance compiled for serial execution" );
463 #endif
464  }
465  else
466  {
467  if( set_tag_name && num_set_tag_vals )
468  {
469  MB_CHK_SET_ERR( serial_load_file( file_name, file_set, opts, &sl ), "can't load subset file in serial" );
470  }
471  else
472  {
473  MB_CHK_SET_ERR( serial_load_file( file_name, file_set, opts ), "can't load file in serial" );
474  }
475  }
476 
477  if( MB_SUCCESS == rval && !opts.all_seen() )
478  {
479  std::string bad_opt;
480  if( MB_SUCCESS == opts.get_unseen_option( bad_opt ) )
481  {
482  MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option: \"" << bad_opt << "\"" );
483  }
484  else
485  {
486  MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option" );
487  }
488  }
489 
490  return MB_SUCCESS;
491 }
492 
493 void Core::clean_up_failed_read( const Range& initial_ents, std::vector< Tag > initial_tags )
494 {
495  Range new_ents;
496  get_entities_by_handle( 0, new_ents );
497  new_ents = subtract( new_ents, initial_ents );
498  delete_entities( new_ents );
499 
500  std::vector< Tag > all_tags, new_tags;
501  tag_get_tags( all_tags );
502  std::sort( initial_tags.begin(), initial_tags.end() );
503  std::sort( all_tags.begin(), all_tags.end() );
504  std::set_difference( all_tags.begin(), all_tags.end(), initial_tags.begin(), initial_tags.end(),
505  std::back_inserter( new_tags ) );
506  while( !new_tags.empty() )
507  {
508  tag_delete( new_tags.back() );
509  new_tags.pop_back();
510  }
511 }
512 
513 ErrorCode Core::serial_load_file( const char* file_name,
514  const EntityHandle* file_set,
515  const FileOptions& opts,
516  const ReaderIface::SubsetList* subsets,
517  const Tag* id_tag )
518 {
519  int status;
520 #if defined( WIN32 ) || defined( WIN64 ) || defined( MSC_VER )
521  struct _stat stat_data;
522  status = _stat( file_name, &stat_data );
523 #else
524  struct stat stat_data;
525  status = stat( file_name, &stat_data );
526 #endif
527  if( status )
528  {
529  MB_SET_GLB_ERR( MB_FILE_DOES_NOT_EXIST, file_name << ": " << strerror( errno ) );
530  }
531 #if defined( WIN32 ) || defined( WIN64 ) || defined( MSC_VER )
532  else if( stat_data.st_mode & _S_IFDIR )
533  {
534 #else
535  else if( S_ISDIR( stat_data.st_mode ) )
536  {
537 #endif
538  MB_SET_GLB_ERR( MB_FILE_DOES_NOT_EXIST, file_name << ": Cannot read directory/folder" );
539  }
540 
541  const ReaderWriterSet* set = reader_writer_set();
542 
543  Range initial_ents;
544  MB_CHK_SET_ERR( get_entities_by_handle( 0, initial_ents ), "can't get entities by handle" );
545 
546  std::vector< Tag > initial_tags;
547  MB_CHK_SET_ERR( tag_get_tags( initial_tags ), "can't get tags" );
548 
549  // otherwise try using the file extension to select a reader
550  std::string ext = set->extension_from_filename( file_name );
551 
552  // Try all the readers
554  ErrorCode rval = MB_FAILURE;
555  bool tried_one = false;
556  for( iter = set->begin(); iter != set->end(); ++iter )
557  {
558  if( !iter->reads_extension( ext.c_str() ) ) continue;
559 
560  ReaderIface* reader = iter->make_reader( this );
561  if( NULL != reader )
562  {
563  tried_one = true;
564  rval = reader->load_file( file_name, file_set, opts, subsets, id_tag );
565  delete reader;
566  if( MB_SUCCESS == rval ) break;
567  clean_up_failed_read( initial_ents, initial_tags );
568  }
569  }
570 
571  if( MB_SUCCESS != rval && !tried_one )
572  {
573  // didn't recognize the extension; try all of them now
574  for( iter = set->begin(); iter != set->end(); ++iter )
575  {
576  ReaderIface* reader = iter->make_reader( this );
577  if( !reader ) continue;
578  rval = reader->load_file( file_name, file_set, opts, subsets, id_tag );
579  delete reader;
580  if( MB_SUCCESS == rval ) break;
581  clean_up_failed_read( initial_ents, initial_tags );
582  }
583  }
584 
585  if( MB_SUCCESS != rval )
586  {
587  clean_up_failed_read( initial_ents, initial_tags );
588  MB_SET_ERR( rval, "Failed to load file after trying all possible readers" );
589  }
590  else if( file_set )
591  {
592  Range new_ents;
593  get_entities_by_handle( 0, new_ents );
594  new_ents = subtract( new_ents, initial_ents );
595 
596  // Check if gather set exists
597  EntityHandle gather_set;
598  rval = mMBReadUtil->get_gather_set( gather_set );
599  if( MB_SUCCESS == rval )
600  {
601  // Exclude gather set itself
602  new_ents.erase( gather_set );
603 
604  // Exclude gather set entities
605  Range gather_ents;
606  rval = get_entities_by_handle( gather_set, gather_ents );
607  if( MB_SUCCESS == rval ) new_ents = subtract( new_ents, gather_ents );
608  }
609 
610  rval = add_entities( *file_set, new_ents );
611  }
612 
613  return rval;
614 } // namespace moab
615 
616 ErrorCode Core::serial_read_tag( const char* file_name,
617  const char* tag_name,
618  const FileOptions& opts,
619  std::vector< int >& vals,
620  const ReaderIface::SubsetList* subsets )
621 {
622  ErrorCode rval = MB_FAILURE;
623  const ReaderWriterSet* set = reader_writer_set();
624 
625  // otherwise try using the file extension to select a reader
626  ReaderIface* reader = set->get_file_extension_reader( file_name );
627  if( reader )
628  {
629  rval = reader->read_tag_values( file_name, tag_name, opts, vals, subsets );
630  delete reader;
631  }
632  else
633  {
634  // Try all the readers
636  for( iter = set->begin(); iter != set->end(); ++iter )
637  {
638  reader = iter->make_reader( this );
639  if( NULL != reader )
640  {
641  rval = reader->read_tag_values( file_name, tag_name, opts, vals, subsets );
642  delete reader;
643  if( MB_SUCCESS == rval ) break;
644  }
645  }
646  }
647 
648  return rval;
649 }
650 
651 ErrorCode Core::write_mesh( const char* file_name, const EntityHandle* output_list, const int num_sets )
652 {
653  return write_file( file_name, 0, 0, output_list, num_sets );
654 }
655 
656 ErrorCode Core::write_file( const char* file_name,
657  const char* file_type,
658  const char* options_string,
659  const EntityHandle* output_sets,
660  int num_output_sets,
661  const Tag* tag_list,
662  int num_tags )
663 {
664  Range range;
665  std::copy( output_sets, output_sets + num_output_sets, range_inserter( range ) );
666  return write_file( file_name, file_type, options_string, range, tag_list, num_tags );
667 }
668 
669 ErrorCode Core::write_file( const char* file_name,
670  const char* file_type,
671  const char* options_string,
672  const Range& output_sets,
673  const Tag* tag_list,
674  int num_tags )
675 {
676  // convert range to vector
677  std::vector< EntityHandle > list( output_sets.size() );
678  std::copy( output_sets.begin(), output_sets.end(), list.begin() );
679 
680  // parse some options
681  FileOptions opts( options_string );
682  ErrorCode rval;
683 
684  rval = opts.get_null_option( "CREATE" );
685  if( rval == MB_TYPE_OUT_OF_RANGE )
686  {
687  MB_SET_GLB_ERR( MB_FAILURE, "Unexpected value for CREATE option" );
688  }
689  bool overwrite = ( rval == MB_ENTITY_NOT_FOUND );
690 
691  // Get the file writer
692  std::string ext = ReaderWriterSet::extension_from_filename( file_name );
693  std::vector< std::string > qa_records;
694  const EntityHandle* list_ptr = list.empty() ? (EntityHandle*)0 : &list[0];
695 
696  rval = MB_TYPE_OUT_OF_RANGE;
697 
698  // Try all possible writers
699  for( ReaderWriterSet::iterator i = reader_writer_set()->begin(); i != reader_writer_set()->end(); ++i )
700  {
701 
702  if( ( file_type && !i->name().compare( file_type ) ) || i->writes_extension( ext.c_str() ) )
703  {
704 
705  WriterIface* writer = i->make_writer( this );
706 
707  // write the file
708  rval =
709  writer->write_file( file_name, overwrite, opts, list_ptr, list.size(), qa_records, tag_list, num_tags );
710  delete writer;
711  if( MB_SUCCESS == rval ) break;
712  printf( "Writer with name %s for file %s using extension %s (file type \"%s\") was "
713  "unsuccessful\n",
714  i->name().c_str(), file_name, ext.c_str(), file_type );
715  }
716  }
717 
718  if( file_type && rval == MB_TYPE_OUT_OF_RANGE )
719  {
720  MB_SET_ERR( rval, "Unrecognized file type \"" << file_type << "\"" );
721  }
722  // Should we use default writer (e.g. HDF5)?
723  else if( MB_SUCCESS != rval )
724  {
725  DefaultWriter writer( this );
726  printf( "Using default writer %s for file %s \n", DefaultWriterName, file_name );
727  rval = writer.write_file( file_name, overwrite, opts, list_ptr, list.size(), qa_records, tag_list, num_tags );
728  }
729 
730  if( MB_SUCCESS == rval && !opts.all_seen() )
731  {
732  std::string bad_opt;
733  if( MB_SUCCESS == opts.get_unseen_option( bad_opt ) )
734  {
735  MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option: \"" << bad_opt << "\"" );
736  }
737  else
738  {
739  MB_SET_ERR( MB_UNHANDLED_OPTION, "Unrecognized option" );
740  }
741  }
742 
743  return MB_SUCCESS;
744 }
745 
746 //! deletes all mesh entities from this datastore
748 {
749 
750  ErrorCode result = MB_SUCCESS;
751 
752  // perform all deinitialization procedures to clean up
753  if( aEntityFactory ) delete aEntityFactory;
754  aEntityFactory = new AEntityFactory( this );
755 
756  for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i )
757  {
758  result = ( *i )->release_all_data( sequenceManager, mError, false );
759  MB_CHK_ERR( result );
760  }
761 
762  sequenceManager->clear();
763 
764  return MB_SUCCESS;
765 }
766 
767 //! get overall geometric dimension
769 {
770  dim = geometricDimension;
771  return MB_SUCCESS;
772 }
773 
774 //! set overall geometric dimension
775 /** Returns error if setting to 3 dimensions, mesh has been created, and
776  * there are only 2 dimensions on that mesh
777  */
779 {
780  // check to see if current dimension is smaller
781  if( geometricDimension < dim )
782  {
783  // need to check the number of entities
784  int num;
785  /*ErrorCode result = */ get_number_entities_by_dimension( 0, geometricDimension, num );
786 
787  // test written to be more readable but possibly less efficient
788  // if (MB_SUCCESS != result) return MB_FAILURE;
789  // else if (0 != num && dim == 2 && ycoordTag == 0) return MB_FAILURE;
790  // else if (0 != num && dim == 3 && (ycoordTag == 0 || zcoordTag == 0)) return MB_FAILURE;
791  // TODO -- replace this with not using xcoordTag, etc...
792  }
793 
794  // if we got here, it's ok to set dimension
795  geometricDimension = dim;
796  return MB_SUCCESS;
797 }
798 
799 //! get blocked vertex coordinates for all vertices
800 /** Blocked = all x, then all y, etc.
801  */
802 ErrorCode Core::get_vertex_coordinates( std::vector< double >& coords ) const
803 {
804  // INEFFICIENT implementation for now, until we get blocked tag access
805  Range vertices;
806  ErrorCode result = get_entities_by_type( 0, MBVERTEX, vertices );
807  MB_CHK_ERR( result );
808 
809  // the least we can do is resize the vector and only go through the
810  // vertex list once
811  int num_verts = vertices.size();
812  int vec_pos = 0;
813  double xyz[3];
814  coords.resize( geometricDimension * num_verts );
815  for( Range::iterator it = vertices.begin(); it != vertices.end(); ++it )
816  {
817  result = get_coords( &( *it ), 1, xyz );
818  MB_CHK_ERR( result );
819 
820  coords[vec_pos] = xyz[0];
821  coords[num_verts + vec_pos] = xyz[1];
822  coords[2 * num_verts + vec_pos] = xyz[2];
823 
824  vec_pos++;
825  }
826 
827  return MB_SUCCESS;
828 }
829 
832  double*& xcoords_ptr,
833  double*& ycoords_ptr,
834  double*& zcoords_ptr,
835  int& count )
836 {
837  EntitySequence* seq;
838  ErrorCode rval = sequence_manager()->find( *iter, seq );
839  if( MB_SUCCESS != rval )
840  {
841  xcoords_ptr = ycoords_ptr = zcoords_ptr = NULL;
842  MB_SET_ERR( rval, "Couldn't find sequence for start handle" );
843  }
844  VertexSequence* vseq = dynamic_cast< VertexSequence* >( seq );
845  if( !vseq )
846  {
847  MB_SET_ERR( MB_ENTITY_NOT_FOUND, "Couldn't find sequence for start handle" );
848  }
849 
850  unsigned int offset = *iter - vseq->data()->start_handle();
851  xcoords_ptr = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 0 ) ) + offset;
852  ycoords_ptr = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 1 ) ) + offset;
853  zcoords_ptr = reinterpret_cast< double* >( vseq->data()->get_sequence_data( 2 ) ) + offset;
854 
855  EntityHandle real_end = std::min( seq->end_handle(), *( iter.end_of_block() ) );
856  if( *end ) real_end = std::min( real_end, *end );
857  count = real_end - *iter + 1;
858 
859  return MB_SUCCESS;
860 }
861 
862 ErrorCode Core::get_coords( const Range& entities, double* coords ) const
863 {
864  const TypeSequenceManager& vert_data = sequence_manager()->entity_map( MBVERTEX );
866 
868  EntityHandle first = i->first;
869  while( i != entities.const_pair_end() && TYPE_FROM_HANDLE( i->first ) == MBVERTEX )
870  {
871 
872  seq_iter = vert_data.lower_bound( first );
873  if( seq_iter == vert_data.end() || first < ( *seq_iter )->start_handle() ) return MB_ENTITY_NOT_FOUND;
874  const VertexSequence* vseq = reinterpret_cast< const VertexSequence* >( *seq_iter );
875 
876  EntityID offset = first - vseq->start_handle();
877  EntityID count;
878  if( i->second <= vseq->end_handle() )
879  {
880  count = i->second - first + 1;
881  ++i;
882  if( i != entities.const_pair_end() ) first = i->first;
883  }
884  else
885  {
886  count = vseq->end_handle() - first + 1;
887  first = vseq->end_handle() + 1;
888  }
889 
890  double const *x, *y, *z;
891  MB_CHK_SET_ERR( vseq->get_coordinate_arrays( x, y, z ), "can't get coordinate arrays" );
892  x += offset;
893  y += offset;
894  z += offset;
895  for( EntityID j = 0; j < count; ++j )
896  {
897  coords[3 * j] = x[j];
898  coords[3 * j + 1] = y[j];
899  coords[3 * j + 2] = z[j];
900  }
901  coords = &coords[3 * count];
902  }
903 
904  // for non-vertices...
905  ErrorCode rval = MB_SUCCESS;
906  for( Range::const_iterator rit( &( *i ), i->first ); rit != entities.end(); ++rit )
907  {
908  MB_CHK_SET_ERR( get_coords( &( *rit ), 1, coords ), "can't get coords" );
909  coords += 3;
910  }
911 
912  return rval;
913 }
914 
915 /**\author Jason Kraftcheck <[email protected]> - 2007-5-15 */
916 ErrorCode Core::get_coords( const Range& entities, double* x_coords, double* y_coords, double* z_coords ) const
917 {
918  const TypeSequenceManager& vert_data = sequence_manager()->entity_map( MBVERTEX );
920 
922  EntityHandle first = i->first;
923  while( i != entities.const_pair_end() && TYPE_FROM_HANDLE( i->first ) == MBVERTEX )
924  {
925 
926  seq_iter = vert_data.lower_bound( first );
927  if( seq_iter == vert_data.end() || first < ( *seq_iter )->start_handle() ) return MB_ENTITY_NOT_FOUND;
928  const VertexSequence* vseq = reinterpret_cast< const VertexSequence* >( *seq_iter );
929 
930  EntityID offset = first - vseq->start_handle();
931  EntityID count;
932  if( i->second <= vseq->end_handle() )
933  {
934  count = i->second - first + 1;
935  ++i;
936  if( i != entities.const_pair_end() ) first = i->first;
937  }
938  else
939  {
940  count = vseq->end_handle() - first + 1;
941  first = vseq->end_handle() + 1;
942  }
943 
944  double const *x, *y, *z;
945  MB_CHK_SET_ERR( vseq->get_coordinate_arrays( x, y, z ), "can't get coordinate arrays" );
946  if( x_coords )
947  {
948  memcpy( x_coords, x + offset, count * sizeof( double ) );
949  x_coords += count;
950  }
951  if( y_coords )
952  {
953  memcpy( y_coords, y + offset, count * sizeof( double ) );
954  y_coords += count;
955  }
956  if( z_coords )
957  {
958  memcpy( z_coords, z + offset, count * sizeof( double ) );
959  z_coords += count;
960  }
961  }
962 
963  // for non-vertices...
964  ErrorCode rval = MB_SUCCESS;
965  double xyz[3];
966  for( Range::const_iterator rit( &( *i ), i->first ); rit != entities.end(); ++rit )
967  {
968  MB_CHK_SET_ERR( get_coords( &( *rit ), 1, xyz ), "can't get coords" );
969  *x_coords++ = xyz[0];
970  *y_coords++ = xyz[1];
971  *z_coords++ = xyz[2];
972  }
973 
974  return rval;
975 }
976 
977 ErrorCode Core::get_coords( const EntityHandle* entities, const int num_entities, double* coords ) const
978 {
979  const EntitySequence* seq = NULL;
980  const VertexSequence* vseq = NULL;
981  const EntityHandle* const end = entities + num_entities;
982  const EntityHandle* iter = entities;
983  ErrorCode status = MB_SUCCESS;
984 
985  while( iter != end )
986  {
987  if( TYPE_FROM_HANDLE( *iter ) == MBVERTEX )
988  {
989  if( !seq )
990  {
991  seq = sequence_manager()->get_last_accessed_sequence( MBVERTEX );
992  vseq = static_cast< const VertexSequence* >( seq );
993  }
994  if( !vseq )
995  return MB_ENTITY_NOT_FOUND;
996  else if( vseq->start_handle() > *iter || vseq->end_handle() < *iter )
997  {
998  if( MB_SUCCESS != sequence_manager()->find( *iter, seq ) ) return MB_ENTITY_NOT_FOUND;
999  vseq = static_cast< const VertexSequence* >( seq );
1000  }
1001  vseq->get_coordinates( *iter, coords );
1002  }
1003  else
1004  {
1005  static std::vector< EntityHandle > dum_conn( CN::MAX_NODES_PER_ELEMENT );
1006  static std::vector< double > dum_pos( 3 * CN::MAX_NODES_PER_ELEMENT );
1007  static const EntityHandle* conn;
1008  static int num_conn;
1009  status = get_connectivity( *iter, conn, num_conn, false, &dum_conn );
1010  MB_CHK_ERR( status );
1011  status = get_coords( conn, num_conn, &dum_pos[0] );
1012  MB_CHK_ERR( status );
1013  coords[0] = coords[1] = coords[2] = 0.0;
1014  for( int i = 0; i < num_conn; i++ )
1015  {
1016  coords[0] += dum_pos[3 * i];
1017  coords[1] += dum_pos[3 * i + 1];
1018  coords[2] += dum_pos[3 * i + 2];
1019  }
1020  coords[0] /= num_conn;
1021  coords[1] /= num_conn;
1022  coords[2] /= num_conn;
1023  }
1024  coords += 3;
1025  ++iter;
1026  }
1027 
1028  return status;
1029 }
1030 
1032  const double*& x,
1033  const double*& y,
1034  const double*& z ) const
1035 {
1037 
1038  if( TYPE_FROM_HANDLE( entity_handle ) == MBVERTEX )
1039  {
1040  const EntitySequence* seq = 0;
1041  status = sequence_manager()->find( entity_handle, seq );
1042 
1043  if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
1044 
1045  status = static_cast< const VertexSequence* >( seq )->get_coordinates_ref( entity_handle, x, y, z );
1046  }
1047 
1048  return status;
1049 }
1050 
1051 //! set the coordinate information for this handle if it is of type Vertex
1052 //! otherwise, return an error
1053 ErrorCode Core::set_coords( const EntityHandle* entity_handles, const int num_entities, const double* coords )
1054 {
1055 
1056  ErrorCode status = MB_SUCCESS;
1057 
1058  int i, j = 0;
1059 
1060  for( i = 0; i < num_entities; i++ )
1061  {
1062  if( TYPE_FROM_HANDLE( entity_handles[i] ) == MBVERTEX )
1063  {
1064  EntitySequence* seq = 0;
1065  status = sequence_manager()->find( entity_handles[i], seq );
1066 
1067  if( seq != 0 && status == MB_SUCCESS )
1068  {
1069  status = static_cast< VertexSequence* >( seq )->set_coordinates( entity_handles[i], coords[j],
1070  coords[j + 1], coords[j + 2] );
1071  j += 3;
1072  }
1073  }
1074  else if( status == MB_SUCCESS )
1075  status = MB_TYPE_OUT_OF_RANGE;
1076  }
1077 
1078  return status;
1079 }
1080 
1081 //! set the coordinate information for this handle if it is of type Vertex
1082 //! otherwise, return an error
1083 ErrorCode Core::set_coords( Range entity_handles, const double* coords )
1084 {
1085 
1086  ErrorCode status = MB_SUCCESS;
1087 
1088  int j = 0;
1089 
1090  for( Range::iterator rit = entity_handles.begin(); rit != entity_handles.end(); ++rit )
1091  {
1092  if( TYPE_FROM_HANDLE( *rit ) == MBVERTEX )
1093  {
1094  EntitySequence* seq = 0;
1095  status = sequence_manager()->find( *rit, seq );
1096 
1097  if( seq != 0 && status == MB_SUCCESS )
1098  {
1099  status = static_cast< VertexSequence* >( seq )->set_coordinates( *rit, coords[j], coords[j + 1],
1100  coords[j + 2] );
1101  j += 3;
1102  }
1103  }
1104  else if( status == MB_SUCCESS )
1105  status = MB_TYPE_OUT_OF_RANGE;
1106  }
1107 
1108  return status;
1109 }
1110 
1112 {
1113  return sequenceManager->get_sequence_multiplier();
1114 }
1115 
1116 void Core::set_sequence_multiplier( double factor )
1117 {
1118  assert( factor >= 1.0 );
1119  sequenceManager->set_sequence_multiplier( factor );
1120 }
1121 
1122 //! get global connectivity array for specified entity type
1123 /** Assumes just vertices, no higher order nodes
1124  */
1125 ErrorCode Core::get_connectivity_by_type( const EntityType entity_type, std::vector< EntityHandle >& connect ) const
1126 {
1127  // inefficient implementation until we get blocked tag access
1128 
1129  // get the range of entities of this type
1130  Range this_range;
1131  ErrorCode result = get_entities_by_type( 0, entity_type, this_range );
1132 
1133  int num_ents = this_range.size();
1134  connect.reserve( num_ents * CN::VerticesPerEntity( entity_type ) );
1135 
1136  // now loop over these entities, getting connectivity for each
1137  for( Range::iterator this_it = this_range.begin(); this_it != this_range.end(); ++this_it )
1138  {
1139  const EntityHandle* connect_vec = NULL;
1140  result = get_connectivity( *this_it, connect_vec, num_ents, true );
1141  MB_CHK_ERR( result );
1142  connect.insert( connect.end(), &connect_vec[0], &connect_vec[num_ents] );
1143  }
1144 
1145  return MB_SUCCESS;
1146 }
1147 
1148 //! get the connectivity for element /handles. For non-element handles, return an error
1150  const int num_handles,
1151  Range& connectivity,
1152  bool corners_only ) const
1153 {
1154  std::vector< EntityHandle > tmp_connect;
1155  ErrorCode result = get_connectivity( entity_handles, num_handles, tmp_connect, corners_only );
1156  MB_CHK_ERR( result );
1157 
1158  std::sort( tmp_connect.begin(), tmp_connect.end() );
1159  std::copy( tmp_connect.rbegin(), tmp_connect.rend(), range_inserter( connectivity ) );
1160  return result;
1161 }
1162 
1163 //! get the connectivity for element /handles. For non-element handles, return an error
1165  const int num_handles,
1166  std::vector< EntityHandle >& connectivity,
1167  bool corners_only,
1168  std::vector< int >* offsets ) const
1169 {
1170  connectivity.clear(); // this seems wrong as compared to other API functions,
1171  // but changing it breaks lost of code, so I'm leaving
1172  // it in. - j.kraftcheck 2009-11-06
1173 
1174  std::vector< EntityHandle > tmp_storage; // used only for structured mesh
1175  const EntityHandle* conn;
1176  int len;
1177  if( offsets ) offsets->push_back( 0 );
1178  for( int i = 0; i < num_handles; ++i )
1179  {
1180  MB_CHK_SET_ERR( get_connectivity( entity_handles[i], conn, len, corners_only, &tmp_storage ),
1181  "can't get connectivity" );
1182  connectivity.insert( connectivity.end(), conn, conn + len );
1183  if( offsets ) offsets->push_back( connectivity.size() );
1184  }
1185  return MB_SUCCESS;
1186 }
1187 
1188 //! get the connectivity for element handles. For non-element handles, return an error
1190  const EntityHandle*& connectivity,
1191  int& number_nodes,
1192  bool corners_only,
1193  std::vector< EntityHandle >* storage ) const
1194 {
1195  ErrorCode status;
1196 
1197  // Make sure the entity should have a connectivity.
1198  EntityType entity_type = TYPE_FROM_HANDLE( entity_handle );
1199 
1200  // WARNING: This is very dependent on the ordering of the EntityType enum
1201  if( entity_type < MBVERTEX || entity_type >= MBENTITYSET )
1202  return MB_TYPE_OUT_OF_RANGE;
1203 
1204  else if( entity_type == MBVERTEX )
1205  {
1206  return MB_FAILURE;
1207  }
1208 
1209  const EntitySequence* seq = 0;
1210 
1211  // We know that connectivity is stored in an EntitySequence so jump straight
1212  // to the entity sequence
1213  status = sequence_manager()->find( entity_handle, seq );
1214  if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
1215 
1216  return static_cast< const ElementSequence* >( seq )->get_connectivity( entity_handle, connectivity, number_nodes,
1217  corners_only, storage );
1218 }
1219 
1220 //! set the connectivity for element handles. For non-element handles, return an error
1221 ErrorCode Core::set_connectivity( const EntityHandle entity_handle, EntityHandle* connect, const int num_connect )
1222 {
1223  ErrorCode status = MB_FAILURE;
1224 
1225  // Make sure the entity should have a connectivity.
1226  // WARNING: This is very dependent on the ordering of the EntityType enum
1227  EntityType entity_type = TYPE_FROM_HANDLE( entity_handle );
1228 
1229  EntitySequence* seq = 0;
1230 
1231  if( entity_type < MBVERTEX || entity_type > MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
1232 
1233  status = sequence_manager()->find( entity_handle, seq );
1234  if( seq == 0 || status != MB_SUCCESS ) return ( status != MB_SUCCESS ? status : MB_ENTITY_NOT_FOUND );
1235 
1236  const EntityHandle* old_conn;
1237  int len;
1238  status = static_cast< ElementSequence* >( seq )->get_connectivity( entity_handle, old_conn, len );
1239  MB_CHK_ERR( status );
1240 
1241  aEntityFactory->notify_change_connectivity( entity_handle, old_conn, connect, num_connect );
1242 
1243  status = static_cast< ElementSequence* >( seq )->set_connectivity( entity_handle, connect, num_connect );
1244  if( status != MB_SUCCESS )
1245  aEntityFactory->notify_change_connectivity( entity_handle, connect, old_conn, num_connect );
1246 
1247  return status;
1248 }
1249 
1250 template < typename ITER >
1252  ITER begin,
1253  ITER end,
1254  int to_dimension,
1255  bool create_if_missing,
1256  Range& adj_entities )
1257 {
1258  const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000;
1259  const size_t MAX_OUTER_ITERATIONS = 100;
1260 
1261  std::vector< EntityHandle > temp_vec, storage;
1262  std::vector< EntityHandle >::const_iterator ti;
1263  ErrorCode result = MB_SUCCESS, tmp_result;
1264  ITER i = begin;
1265  Range::iterator ins;
1266  const EntityHandle* conn;
1267  int conn_len;
1268 
1269  // Just copy any vertices from the input range into the output
1270  size_t remaining = end - begin;
1271  assert( begin + remaining == end );
1272 
1273  // How many entities to work with at once? 2000 or so shouldn't require
1274  // too much memory, but don't iterate in outer loop more than a
1275  // 1000 times (make it bigger if many input entiites.)
1276  const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining / MAX_OUTER_ITERATIONS );
1277  while( remaining > 0 )
1278  {
1279  const size_t count = remaining > block_size ? block_size : remaining;
1280  remaining -= count;
1281  temp_vec.clear();
1282  for( size_t j = 0; j < count; ++i, ++j )
1283  {
1284  if( CN::Dimension( TYPE_FROM_HANDLE( *i ) ) == to_dimension )
1285  {
1286  temp_vec.push_back( *i );
1287  }
1288  else if( to_dimension == 0 && TYPE_FROM_HANDLE( *i ) != MBPOLYHEDRON )
1289  {
1290  tmp_result = gMB->get_connectivity( *i, conn, conn_len, false, &storage );
1291  if( MB_SUCCESS != tmp_result )
1292  {
1293  result = tmp_result;
1294  continue;
1295  }
1296  temp_vec.insert( temp_vec.end(), conn, conn + conn_len );
1297  }
1298  else
1299  {
1300  tmp_result = gMB->a_entity_factory()->get_adjacencies( *i, to_dimension, create_if_missing, temp_vec );
1301  if( MB_SUCCESS != tmp_result )
1302  {
1303  result = tmp_result;
1304  continue;
1305  }
1306  }
1307  }
1308 
1309  std::sort( temp_vec.begin(), temp_vec.end() );
1310  ins = adj_entities.begin();
1311  ti = temp_vec.begin();
1312  while( ti != temp_vec.end() )
1313  {
1314  EntityHandle first = *ti;
1315  EntityHandle second = *ti;
1316  for( ++ti; ti != temp_vec.end() && ( *ti - second <= 1 ); ++ti )
1317  second = *ti;
1318  ins = adj_entities.insert( ins, first, second );
1319  }
1320  }
1321  return result;
1322 }
1323 
1324 template < typename ITER >
1326  ITER begin,
1327  ITER end,
1328  const int to_dimension,
1329  const bool create_if_missing,
1330  std::vector< EntityHandle >& adj_entities )
1331 {
1332  const size_t SORT_THRESHOLD = 200;
1333  std::vector< EntityHandle > temp_vec;
1334  std::vector< EntityHandle >::iterator adj_it, w_it;
1335  ErrorCode result = MB_SUCCESS;
1336 
1337  if( begin == end )
1338  {
1339  adj_entities.clear(); // intersection
1340  return MB_SUCCESS;
1341  }
1342 
1343  // First iteration is a special case if input list is empty.
1344  // Rather than returning nothing (intersecting with empty
1345  // input list), we begin with the adjacencies for the first entity.
1346  if( adj_entities.empty() )
1347  {
1348  EntityType entity_type = TYPE_FROM_HANDLE( *begin );
1349  if( to_dimension == CN::Dimension( entity_type ) )
1350  adj_entities.push_back( *begin );
1351  else if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
1352  {
1353  result = mb->get_connectivity( &( *begin ), 1, adj_entities );
1354  MB_CHK_ERR( result );
1355  }
1356  else
1357  {
1358  result = mb->a_entity_factory()->get_adjacencies( *begin, to_dimension, create_if_missing, adj_entities );
1359  MB_CHK_ERR( result );
1360  }
1361  ++begin;
1362  }
1363 
1364  for( ITER from_it = begin; from_it != end; ++from_it )
1365  {
1366  // running results kept in adj_entities; clear temp_vec, which is working space
1367  temp_vec.clear();
1368 
1369  // get the next set of adjacencies
1370  EntityType entity_type = TYPE_FROM_HANDLE( *from_it );
1371  if( to_dimension == CN::Dimension( entity_type ) )
1372  temp_vec.push_back( *from_it );
1373  else if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
1374  {
1375  result = mb->get_connectivity( &( *from_it ), 1, temp_vec );
1376  MB_CHK_ERR( result );
1377  }
1378  else
1379  {
1380  result = mb->a_entity_factory()->get_adjacencies( *from_it, to_dimension, create_if_missing, temp_vec );
1381  MB_CHK_ERR( result );
1382  }
1383 
1384  // otherwise intersect with the current set of results
1385  w_it = adj_it = adj_entities.begin();
1386  if( temp_vec.size() * adj_entities.size() < SORT_THRESHOLD )
1387  {
1388  for( ; adj_it != adj_entities.end(); ++adj_it )
1389  if( std::find( temp_vec.begin(), temp_vec.end(), *adj_it ) != temp_vec.end() )
1390  {
1391  *w_it = *adj_it;
1392  ++w_it;
1393  }
1394  }
1395  else
1396  {
1397  std::sort( temp_vec.begin(), temp_vec.end() );
1398  for( ; adj_it != adj_entities.end(); ++adj_it )
1399  if( std::binary_search( temp_vec.begin(), temp_vec.end(), *adj_it ) )
1400  {
1401  *w_it = *adj_it;
1402  ++w_it;
1403  }
1404  }
1405  adj_entities.erase( w_it, adj_entities.end() );
1406 
1407  // we're intersecting, so if there are no more results, we're done
1408  if( adj_entities.empty() ) break;
1409  }
1410 
1411  return MB_SUCCESS;
1412 }
1413 
1414 template < typename ITER >
1416  ITER begin,
1417  ITER end,
1418  const int to_dimension,
1419  const bool create_if_missing,
1420  Range& adj_entities )
1421 {
1422  std::vector< EntityHandle > results;
1423  MB_CHK_SET_ERR( moab::get_adjacencies_intersection( mb, begin, end, to_dimension, create_if_missing, results ),
1424  "can't get adjacencies intersection" );
1425 
1426  if( adj_entities.empty() )
1427  {
1428  std::copy( results.begin(), results.end(), range_inserter( adj_entities ) );
1429  return MB_SUCCESS;
1430  }
1431 
1432  Range::iterator it = adj_entities.begin();
1433  while( it != adj_entities.end() )
1434  {
1435  if( std::find( results.begin(), results.end(), *it ) == results.end() )
1436  it = adj_entities.erase( it );
1437  else
1438  ++it;
1439  }
1440  return MB_SUCCESS;
1441 }
1442 
1443 ///////////////////////////////////////////////////////////////////
1444 //////////////////////////////////////////
1445 #ifdef MOAB_HAVE_AHF
1446 
1447 template < typename ITER >
1448 static inline ErrorCode get_adjacencies_intersection_ahf( Core* mb,
1449  ITER begin,
1450  ITER end,
1451  const int to_dimension,
1452  std::vector< EntityHandle >& adj_entities )
1453 {
1454  const size_t SORT_THRESHOLD = 200;
1455  std::vector< EntityHandle > temp_vec;
1456  std::vector< EntityHandle >::iterator adj_it, w_it;
1457  ErrorCode result = MB_SUCCESS;
1458 
1459  if( begin == end )
1460  {
1461  adj_entities.clear(); // intersection
1462  return MB_SUCCESS;
1463  }
1464 
1465  // First iteration is a special case if input list is empty.
1466  // Rather than returning nothing (intersecting with empty
1467  // input list), we begin with the adjacencies for the first entity.
1468  if( adj_entities.empty() )
1469  {
1470  EntityType entity_type = TYPE_FROM_HANDLE( *begin );
1471 
1472  if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
1473  result = mb->get_connectivity( &( *begin ), 1, adj_entities );
1474  else
1475  result = mb->a_half_facet_rep()->get_adjacencies( *begin, to_dimension, adj_entities );
1476  if( MB_SUCCESS != result ) return result;
1477  ++begin;
1478  }
1479 
1480  for( ITER from_it = begin; from_it != end; ++from_it )
1481  {
1482  // running results kept in adj_entities; clear temp_vec, which is working space
1483  temp_vec.clear();
1484 
1485  // get the next set of adjacencies
1486  EntityType entity_type = TYPE_FROM_HANDLE( *from_it );
1487  if( to_dimension == 0 && entity_type != MBPOLYHEDRON )
1488  result = mb->get_connectivity( &( *from_it ), 1, temp_vec );
1489  else
1490  result = mb->a_half_facet_rep()->get_adjacencies( *from_it, to_dimension, temp_vec );
1491  if( MB_SUCCESS != result ) return result;
1492 
1493  // otherwise intersect with the current set of results
1494  w_it = adj_it = adj_entities.begin();
1495  if( temp_vec.size() * adj_entities.size() < SORT_THRESHOLD )
1496  {
1497  for( ; adj_it != adj_entities.end(); ++adj_it )
1498  if( std::find( temp_vec.begin(), temp_vec.end(), *adj_it ) != temp_vec.end() )
1499  {
1500  *w_it = *adj_it;
1501  ++w_it;
1502  }
1503  }
1504  else
1505  {
1506  std::sort( temp_vec.begin(), temp_vec.end() );
1507  for( ; adj_it != adj_entities.end(); ++adj_it )
1508  if( std::binary_search( temp_vec.begin(), temp_vec.end(), *adj_it ) )
1509  {
1510  *w_it = *adj_it;
1511  ++w_it;
1512  }
1513  }
1514  adj_entities.erase( w_it, adj_entities.end() );
1515 
1516  // we're intersecting, so if there are no more results, we're done
1517  if( adj_entities.empty() ) break;
1518  }
1519 
1520  return MB_SUCCESS;
1521 }
1522 #endif
1523 
1524 ///////////////////////////////////////////
1525 
1527  const int num_entities,
1528  const int to_dimension,
1529  const bool create_if_missing,
1530  std::vector< EntityHandle >& adj_entities,
1531  const int operation_type )
1532 {
1533 
1534 #ifdef MOAB_HAVE_AHF
1535  bool can_handle = true;
1536 
1537  if( to_dimension == 4 )
1538  can_handle = false; // NOT SUPPORTED: meshsets
1539  else if( create_if_missing )
1540  can_handle = false; // NOT SUPPORTED: create_if_missing
1541 
1542  bool mixed = ahfRep->check_mixed_entity_type(); // NOT SUPPORTED: mixed entity types or
1543  // polygonal/hedrals types
1544  if( mixed ) can_handle = false;
1545 
1546  if( mesh_modified ) // NOT SUPPORTED: modified mesh
1547  can_handle = false;
1548 
1549  if( can_handle )
1550  {
1551  ErrorCode result;
1552  if( operation_type == Interface::INTERSECT )
1553  return get_adjacencies_intersection_ahf( this, from_entities, from_entities + num_entities, to_dimension,
1554  adj_entities );
1555  else if( operation_type != Interface::UNION )
1556  return MB_FAILURE;
1557 
1558  // do union
1559 
1560  std::vector< EntityHandle > tmp_storage;
1561  const EntityHandle* conn;
1562  int len;
1563  for( int i = 0; i < num_entities; ++i )
1564  {
1565  if( to_dimension == 0 && TYPE_FROM_HANDLE( from_entities[0] ) != MBPOLYHEDRON )
1566  {
1567  result = get_connectivity( from_entities[i], conn, len, false, &tmp_storage );
1568  adj_entities.insert( adj_entities.end(), conn, conn + len );
1569  if( MB_SUCCESS != result ) return result;
1570  }
1571  else
1572  {
1573  result = ahfRep->get_adjacencies( from_entities[i], to_dimension, adj_entities );
1574  if( MB_SUCCESS != result ) return result;
1575  }
1576  }
1577  std::sort( adj_entities.begin(), adj_entities.end() );
1578  adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() );
1579  }
1580  else
1581  {
1582 
1583 #endif
1584 
1585  if( operation_type == Interface::INTERSECT )
1586  return get_adjacencies_intersection( this, from_entities, from_entities + num_entities, to_dimension,
1587  create_if_missing, adj_entities );
1588  else if( operation_type != Interface::UNION )
1589  return MB_FAILURE;
1590 
1591  // do union
1592  ErrorCode result;
1593  std::vector< EntityHandle > tmp_storage;
1594  const EntityHandle* conn;
1595  int len;
1596  for( int i = 0; i < num_entities; ++i )
1597  {
1598  if( to_dimension == 0 && TYPE_FROM_HANDLE( from_entities[0] ) != MBPOLYHEDRON )
1599  {
1600  result = get_connectivity( from_entities[i], conn, len, false, &tmp_storage );
1601  MB_CHK_ERR( result );
1602  adj_entities.insert( adj_entities.end(), conn, conn + len );
1603  }
1604  else
1605  {
1606  result =
1607  aEntityFactory->get_adjacencies( from_entities[i], to_dimension, create_if_missing, adj_entities );
1608  MB_CHK_ERR( result );
1609  }
1610  }
1611  std::sort( adj_entities.begin(), adj_entities.end() );
1612  adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() );
1613 
1614  // return MB_SUCCESS;
1615 
1616 #ifdef MOAB_HAVE_AHF
1617  }
1618 #endif
1619 
1620  return MB_SUCCESS;
1621 }
1622 
1624  const int num_entities,
1625  const int to_dimension,
1626  const bool create_if_missing,
1627  Range& adj_entities,
1628  const int operation_type )
1629 {
1630  if( operation_type == Interface::INTERSECT )
1631  return get_adjacencies_intersection( this, from_entities, from_entities + num_entities, to_dimension,
1632  create_if_missing, adj_entities );
1633  else if( operation_type == Interface::UNION )
1634  return get_adjacencies_union( this, from_entities, from_entities + num_entities, to_dimension,
1635  create_if_missing, adj_entities );
1636  else
1637  return MB_FAILURE;
1638 }
1639 
1640 ErrorCode Core::get_connectivity( const Range& from_entities, Range& adj_entities, bool corners_only ) const
1641 {
1642  const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000;
1643  const size_t MAX_OUTER_ITERATIONS = 100;
1644 
1645  std::vector< EntityHandle > temp_vec, storage;
1646  std::vector< EntityHandle >::const_iterator ti;
1647  ErrorCode result = MB_SUCCESS, tmp_result;
1648  Range::const_iterator i = from_entities.begin();
1649  Range::iterator ins;
1650  const EntityHandle* conn;
1651  int conn_len;
1652 
1653  // Just copy any vertices from the input range into the output
1654  size_t remaining = from_entities.size();
1655  for( ; i != from_entities.end() && TYPE_FROM_HANDLE( *i ) == MBVERTEX; ++i )
1656  --remaining;
1657  adj_entities.merge( from_entities.begin(), i );
1658 
1659  // How many entities to work with at once? 2000 or so shouldn't require
1660  // too much memory, but don't iterate in outer loop more than a
1661  // 1000 times (make it bigger if many input entiites.)
1662  const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining / MAX_OUTER_ITERATIONS );
1663  while( remaining > 0 )
1664  {
1665  const size_t count = remaining > block_size ? block_size : remaining;
1666  remaining -= count;
1667  temp_vec.clear();
1668  for( size_t j = 0; j < count; ++i, ++j )
1669  {
1670  tmp_result = get_connectivity( *i, conn, conn_len, corners_only, &storage );
1671  if( MB_SUCCESS != tmp_result )
1672  {
1673  result = tmp_result;
1674  continue;
1675  }
1676 
1677  const size_t oldsize = temp_vec.size();
1678  temp_vec.resize( oldsize + conn_len );
1679  memcpy( &temp_vec[oldsize], conn, sizeof( EntityHandle ) * conn_len );
1680  }
1681 
1682  std::sort( temp_vec.begin(), temp_vec.end() );
1683  ins = adj_entities.begin();
1684  ti = temp_vec.begin();
1685  while( ti != temp_vec.end() )
1686  {
1687  EntityHandle first = *ti;
1688  EntityHandle second = *ti;
1689  for( ++ti; ti != temp_vec.end() && ( *ti - second <= 1 ); ++ti )
1690  second = *ti;
1691  ins = adj_entities.insert( ins, first, second );
1692  }
1693  }
1694  return result;
1695 }
1696 
1699  EntityHandle*& connect,
1700  int& verts_per_entity,
1701  int& count )
1702 {
1703  // Make sure the entity should have a connectivity.
1704  EntityType entity_type = TYPE_FROM_HANDLE( *iter );
1705 
1706  // WARNING: This is very dependent on the ordering of the EntityType enum
1707  if( entity_type <= MBVERTEX || entity_type >= MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
1708 
1709  EntitySequence* seq = NULL;
1710 
1711  // We know that connectivity is stored in an EntitySequence so jump straight
1712  // to the entity sequence
1713  ErrorCode rval = sequence_manager()->find( *iter, seq );
1714  if( !seq || rval != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
1715 
1716  ElementSequence* eseq = dynamic_cast< ElementSequence* >( seq );
1717  assert( eseq != NULL );
1718 
1719  connect = eseq->get_connectivity_array();
1720  if( !connect )
1721  {
1722  MB_SET_ERR( MB_FAILURE, "Couldn't find connectivity array for start handle" );
1723  }
1724 
1725  connect += eseq->nodes_per_element() * ( *iter - eseq->start_handle() );
1726 
1727  EntityHandle real_end = std::min( eseq->end_handle(), *( iter.end_of_block() ) );
1728  if( *end ) real_end = std::min( real_end, *end );
1729  count = real_end - *iter + 1;
1730 
1731  verts_per_entity = eseq->nodes_per_element();
1732 
1733  return MB_SUCCESS;
1734 }
1735 
1736 ErrorCode Core::get_vertices( const Range& from_entities, Range& vertices )
1737 {
1738  Range range;
1739  MB_CHK_SET_ERR( get_connectivity( from_entities, range ), "can't get connectivity" );
1740 
1741  // If input contained polyhedra, connectivity will contain faces.
1742  // Get vertices from faces.
1743  if( !range.all_of_dimension( 0 ) )
1744  {
1745  Range::iterator it = range.upper_bound( MBVERTEX );
1746  Range polygons;
1747  polygons.merge( it, range.end() );
1748  range.erase( it, range.end() );
1749  MB_CHK_SET_ERR( get_connectivity( polygons, range ), "can't get connectivity" );
1750  }
1751 
1752  if( vertices.empty() )
1753  vertices.swap( range );
1754  else
1755  vertices.merge( range );
1756  return MB_SUCCESS;
1757 }
1758 
1759 ErrorCode Core::get_adjacencies( const Range& from_entities,
1760  const int to_dimension,
1761  const bool create_if_missing,
1762  Range& adj_entities,
1763  const int operation_type )
1764 {
1765  if( operation_type == Interface::INTERSECT )
1766  return get_adjacencies_intersection( this, from_entities.begin(), from_entities.end(), to_dimension,
1767  create_if_missing, adj_entities );
1768  else if( operation_type != Interface::UNION )
1769  return MB_FAILURE;
1770  else if( to_dimension == 0 )
1771  return get_vertices( from_entities, adj_entities );
1772  else
1773  return get_adjacencies_union( this, from_entities.begin(), from_entities.end(), to_dimension, create_if_missing,
1774  adj_entities );
1775 }
1776 
1777 /** \brief Add adjacencies between entities
1778  * \param from_handle Entity from which adjacencies are being added
1779  * \param to_handles Entities to which adjacencies are being added
1780  * \param num_handles Number of handles in to_handles
1781  * \param both_ways If true, add the adjacency information in both directions
1782  * \see Interface::add_adjacencies(const EntityHandle, const EntityHandle*, const int, bool)
1783  */
1784 ErrorCode Core::add_adjacencies( const EntityHandle from_handle,
1785  const EntityHandle* to_handles,
1786  const int num_handles,
1787  bool both_ways )
1788 {
1789  ErrorCode result = MB_SUCCESS;
1790 
1791  for( const EntityHandle* it = to_handles; it != to_handles + num_handles; it++ )
1792  {
1793  result = aEntityFactory->add_adjacency( from_handle, *it, both_ways );
1794  MB_CHK_ERR( result );
1795  }
1796 
1797  return MB_SUCCESS;
1798 }
1799 
1800 /** \brief Add adjacencies between entities using Range
1801  * \param from_handle Entity from which adjacencies are being added
1802  * \param adjacencies Range of entities to which adjacencies are being added
1803  * \param both_ways If true, add the adjacency information in both directions
1804  * \see Interface::add_adjacencies(const EntityHandle, Range&, bool)
1805  */
1806 ErrorCode Core::add_adjacencies( const EntityHandle from_handle, Range& adjacencies, bool both_ways )
1807 {
1808  ErrorCode result = MB_SUCCESS;
1809 
1810  for( Range::iterator rit = adjacencies.begin(); rit != adjacencies.end(); ++rit )
1811  {
1812  result = aEntityFactory->add_adjacency( from_handle, *rit, both_ways );
1813  MB_CHK_ERR( result );
1814  }
1815 
1816  return MB_SUCCESS;
1817 }
1818 
1819 /** \brief Remove adjacencies between entities
1820  * \param from_handle Entity from which adjacencies are being removed
1821  * \param to_handles Entities to which adjacencies are being removed
1822  * \param num_handles Number of handles in to_handles
1823  * \see Interface::remove_adjacencies(const EntityHandle, const EntityHandle*, const int)
1824  */
1826  const EntityHandle* to_handles,
1827  const int num_handles )
1828 {
1829  ErrorCode result = MB_SUCCESS;
1830 
1831  for( const EntityHandle* it = to_handles; it != to_handles + num_handles; it++ )
1832  {
1833  result = aEntityFactory->remove_adjacency( from_handle, *it );
1834  MB_CHK_ERR( result );
1835  result = aEntityFactory->remove_adjacency( *it, from_handle );
1836  MB_CHK_ERR( result );
1837  }
1838 
1839  return MB_SUCCESS;
1840 }
1841 
1844  const std::vector< EntityHandle >**& adjs_ptr,
1845  int& count )
1846 {
1847  // Make sure the entity should have a connectivity.
1848  EntityType entity_type = TYPE_FROM_HANDLE( *iter );
1849 
1850  // WARNING: This is very dependent on the ordering of the EntityType enum
1851  if( entity_type < MBVERTEX || entity_type > MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
1852 
1853  EntitySequence* seq = NULL;
1854 
1855  // We know that connectivity is stored in an EntitySequence so jump straight
1856  // to the entity sequence
1857  ErrorCode rval = sequence_manager()->find( *iter, seq );
1858  if( !seq || rval != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
1859 
1860  adjs_ptr = const_cast< const std::vector< EntityHandle >** >( seq->data()->get_adjacency_data() );
1861  if( !adjs_ptr ) return rval;
1862 
1863  adjs_ptr += *iter - seq->data()->start_handle();
1864 
1865  EntityHandle real_end = *( iter.end_of_block() );
1866  if( *end ) real_end = std::min( real_end, *end );
1867  count = real_end - *iter + 1;
1868 
1869  return MB_SUCCESS;
1870 }
1871 
1873  const int dimension,
1874  Range& entities,
1875  const bool recursive ) const
1876 {
1877  ErrorCode result = MB_SUCCESS;
1878  if( meshset )
1879  {
1880  const EntitySequence* seq;
1881  result = sequence_manager()->find( meshset, seq );
1882  MB_CHK_ERR( result );
1883  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
1884  result = mseq->get_dimension( sequence_manager(), meshset, dimension, entities, recursive );
1885  MB_CHK_ERR( result );
1886  }
1887  else if( dimension > 3 )
1888  {
1889  sequence_manager()->get_entities( MBENTITYSET, entities );
1890  }
1891  else
1892  {
1893  for( EntityType this_type = CN::TypeDimensionMap[dimension].first;
1894  this_type <= CN::TypeDimensionMap[dimension].second; this_type++ )
1895  {
1896  sequence_manager()->get_entities( this_type, entities );
1897  }
1898  }
1899 
1900  return MB_SUCCESS;
1901 }
1902 
1904  const int dimension,
1905  std::vector< EntityHandle >& entities,
1906  const bool recursive ) const
1907 {
1908  ErrorCode result = MB_SUCCESS;
1909  if( meshset )
1910  {
1911  const EntitySequence* seq;
1912  result = sequence_manager()->find( meshset, seq );
1913  MB_CHK_ERR( result );
1914  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
1915  result = mseq->get_dimension( sequence_manager(), meshset, dimension, entities, recursive );
1916  MB_CHK_ERR( result );
1917  }
1918  else if( dimension > 3 )
1919  {
1920  sequence_manager()->get_entities( MBENTITYSET, entities );
1921  }
1922  else
1923  {
1924  for( EntityType this_type = CN::TypeDimensionMap[dimension].first;
1925  this_type <= CN::TypeDimensionMap[dimension].second; this_type++ )
1926  {
1927  sequence_manager()->get_entities( this_type, entities );
1928  }
1929  }
1930 
1931  return MB_SUCCESS;
1932 }
1933 
1935  const EntityType entity_type,
1936  Range& entities,
1937  const bool recursive ) const
1938 {
1939  ErrorCode result = MB_SUCCESS;
1940  if( meshset )
1941  {
1942  const EntitySequence* seq;
1943  result = sequence_manager()->find( meshset, seq );
1944  MB_CHK_ERR( result );
1945  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
1946  result = mseq->get_type( sequence_manager(), meshset, entity_type, entities, recursive );
1947  MB_CHK_ERR( result );
1948  }
1949  else
1950  {
1951  sequence_manager()->get_entities( entity_type, entities );
1952  }
1953 
1954  return MB_SUCCESS;
1955 }
1956 
1958  const EntityType entity_type,
1959  std::vector< EntityHandle >& entities,
1960  const bool recursive ) const
1961 {
1962  ErrorCode result = MB_SUCCESS;
1963  if( meshset )
1964  {
1965  const EntitySequence* seq;
1966  result = sequence_manager()->find( meshset, seq );
1967  MB_CHK_ERR( result );
1968  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
1969  result = mseq->get_type( sequence_manager(), meshset, entity_type, entities, recursive );
1970  MB_CHK_ERR( result );
1971  }
1972  else
1973  {
1974  sequence_manager()->get_entities( entity_type, entities );
1975  }
1976 
1977  return MB_SUCCESS;
1978 }
1979 
1981  const EntityType entity_type,
1982  const Tag* tags,
1983  const void* const* values,
1984  const int num_tags,
1985  Range& entities,
1986  const int condition,
1987  const bool recursive ) const
1988 {
1989  ErrorCode result;
1990  Range range;
1991 
1992  result = get_entities_by_type( meshset, entity_type, range, recursive );
1993  MB_CHK_ERR( result );
1994  if( !entities.empty() && Interface::INTERSECT == condition ) range = intersect( entities, range );
1995 
1996  // For each tag:
1997  // if operation is INTERSECT remove from 'range' any non-tagged entities
1998  // if operation is UNION add to 'entities' any tagged entities
1999  for( int it = 0; it < num_tags && !range.empty(); it++ )
2000  {
2001  if( !valid_tag_handle( tags[it] ) ) return MB_TAG_NOT_FOUND;
2002 
2003  // Of the entities in 'range', put in 'tmp_range' the subset
2004  // that are tagged as requested for this tag.
2005  Range tmp_range;
2006 
2007  // get the entities with this tag/value combo
2008  if( NULL == values || NULL == values[it] )
2009  {
2010  result = tags[it]->get_tagged_entities( sequenceManager, tmp_range, entity_type, &range );
2011  MB_CHK_ERR( result );
2012  }
2013  else
2014  {
2015  result = tags[it]->find_entities_with_value( sequenceManager, mError, tmp_range, values[it], 0, entity_type,
2016  &range );
2017  MB_CHK_ERR( result );
2018  // if there is a default value, then we should return all entities
2019  // that are untagged
2020  if( tags[it]->equals_default_value( values[it] ) )
2021  {
2022  Range all_tagged, untagged;
2023  result = tags[it]->get_tagged_entities( sequenceManager, all_tagged, entity_type, &range );
2024  MB_CHK_ERR( result );
2025  // add to 'tmp_range' any untagged entities in 'range'
2026  tmp_range.merge( subtract( range, all_tagged ) );
2027  }
2028  }
2029 
2030  // The above calls should have already done the intersect for us.
2031  if( Interface::INTERSECT == condition )
2032  range.swap( tmp_range );
2033  else
2034  entities.merge( tmp_range );
2035  }
2036 
2037  if( Interface::INTERSECT == condition ) entities.swap( range );
2038 
2039  return MB_SUCCESS;
2040 }
2041 
2042 ErrorCode Core::get_entities_by_handle( const EntityHandle meshset, Range& entities, const bool recursive ) const
2043 {
2044  ErrorCode result = MB_SUCCESS;
2045  if( meshset )
2046  {
2047  const EntitySequence* seq;
2048  result = sequence_manager()->find( meshset, seq );
2049  MB_CHK_ERR( result );
2050  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
2051  result = mseq->get_entities( sequence_manager(), meshset, entities, recursive );
2052  MB_CHK_ERR( result );
2053  }
2054  else
2055  {
2056  // iterate backwards so range insertion is quicker
2057  for( EntityType entity_type = MBENTITYSET; entity_type >= MBVERTEX; --entity_type )
2058  sequence_manager()->get_entities( entity_type, entities );
2059  }
2060 
2061  return MB_SUCCESS;
2062 }
2063 
2065  std::vector< EntityHandle >& entities,
2066  const bool recursive ) const
2067 {
2068  ErrorCode result;
2069  if( recursive || !meshset )
2070  {
2071  Range tmp_range;
2072  result = get_entities_by_handle( meshset, tmp_range, recursive );
2073  size_t offset = entities.size();
2074  entities.resize( offset + tmp_range.size() );
2075  std::copy( tmp_range.begin(), tmp_range.end(), entities.begin() + offset );
2076  }
2077  else
2078  {
2079  const EntitySequence* seq;
2080  result = sequence_manager()->find( meshset, seq );
2081  MB_CHK_ERR( result );
2082  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
2083  result = mseq->get_entities( meshset, entities );
2084  MB_CHK_ERR( result );
2085  }
2086  return MB_SUCCESS;
2087 }
2088 
2089 //! get # entities of a given dimension
2091  const int dim,
2092  int& number,
2093  const bool recursive ) const
2094 {
2095  ErrorCode result = MB_SUCCESS;
2096 
2097  if( !meshset )
2098  {
2099  number = 0;
2100  for( EntityType this_type = CN::TypeDimensionMap[dim].first; this_type <= CN::TypeDimensionMap[dim].second;
2101  this_type++ )
2102  {
2103  number += sequence_manager()->get_number_entities( this_type );
2104  }
2105  }
2106  else
2107  {
2108  const EntitySequence* seq;
2109  result = sequence_manager()->find( meshset, seq );
2110  MB_CHK_ERR( result );
2111  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
2112  result = mseq->num_dimension( sequence_manager(), meshset, dim, number, recursive );
2113  MB_CHK_ERR( result );
2114  }
2115 
2116  return MB_SUCCESS;
2117 }
2118 
2119 //! returns the number of entities with a given type and tag
2121  const EntityType entity_type,
2122  int& num_ent,
2123  const bool recursive ) const
2124 {
2125  ErrorCode result = MB_SUCCESS;
2126 
2127  if( recursive && entity_type == MBENTITYSET ) // will never return anything
2128  return MB_TYPE_OUT_OF_RANGE;
2129 
2130  if( meshset )
2131  {
2132  const EntitySequence* seq;
2133  result = sequence_manager()->find( meshset, seq );
2134  MB_CHK_ERR( result );
2135  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
2136  result = mseq->num_type( sequence_manager(), meshset, entity_type, num_ent, recursive );
2137  MB_CHK_ERR( result );
2138  }
2139  else
2140  {
2141  num_ent = sequence_manager()->get_number_entities( entity_type );
2142  }
2143 
2144  return MB_SUCCESS;
2145 }
2146 
2148  const EntityType entity_type,
2149  const Tag* tag_handles,
2150  const void* const* values,
2151  const int num_tags,
2152  int& num_entities,
2153  int condition,
2154  const bool recursive ) const
2155 {
2156  Range dum_ents;
2157  ErrorCode result = get_entities_by_type_and_tag( meshset, entity_type, tag_handles, values, num_tags, dum_ents,
2158  condition, recursive );
2159  num_entities = dum_ents.size();
2160  return result;
2161 }
2162 
2163 ErrorCode Core::get_number_entities_by_handle( const EntityHandle meshset, int& num_ent, const bool recursive ) const
2164 {
2165  ErrorCode result;
2166  if( meshset )
2167  {
2168  const EntitySequence* seq;
2169  result = sequence_manager()->find( meshset, seq );
2170  MB_CHK_ERR( result );
2171  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
2172  return mseq->num_entities( sequence_manager(), meshset, num_ent, recursive );
2173  }
2174 
2175  num_ent = 0;
2176  for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
2177  {
2178  int dummy = 0;
2179  result = get_number_entities_by_type( 0, this_type, dummy );
2180  if( result != MB_SUCCESS )
2181  {
2182  num_ent = 0;
2183  return result;
2184  }
2185  num_ent += dummy;
2186  }
2187 
2188  return MB_SUCCESS;
2189 }
2190 
2191 //! return the tag data for a given EntityHandle and Tag
2193  const EntityHandle* entity_handles,
2194  int num_entities,
2195  void* tag_data ) const
2196 {
2197  assert( valid_tag_handle( tag_handle ) );
2199  return tag_handle->get_data( sequenceManager, mError, entity_handles, num_entities, tag_data );
2200 }
2201 
2202 //! return the tag data for a given EntityHandle and Tag
2203 ErrorCode Core::tag_get_data( const Tag tag_handle, const Range& entity_handles, void* tag_data ) const
2204 {
2205  assert( valid_tag_handle( tag_handle ) );
2206  return tag_handle->get_data( sequenceManager, mError, entity_handles, tag_data );
2207 }
2208 
2209 //! set the data for given EntityHandles and Tag
2211  const EntityHandle* entity_handles,
2212  int num_entities,
2213  const void* tag_data )
2214 {
2215  assert( valid_tag_handle( tag_handle ) );
2217  return tag_handle->set_data( sequenceManager, mError, entity_handles, num_entities, tag_data );
2218 }
2219 
2220 //! set the data for given EntityHandles and Tag
2221 ErrorCode Core::tag_set_data( Tag tag_handle, const Range& entity_handles, const void* tag_data )
2222 {
2223  assert( valid_tag_handle( tag_handle ) );
2224  return tag_handle->set_data( sequenceManager, mError, entity_handles, tag_data );
2225 }
2226 
2227 //! return the tag data for a given EntityHandle and Tag
2229  const EntityHandle* entity_handles,
2230  int num_entities,
2231  const void** tag_data,
2232  int* tag_sizes ) const
2233 {
2234  assert( valid_tag_handle( tag_handle ) );
2236  ErrorCode result =
2237  tag_handle->get_data( sequenceManager, mError, entity_handles, num_entities, tag_data, tag_sizes );
2238  int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() );
2239  if( tag_sizes && typesize != 1 )
2240  for( int i = 0; i < num_entities; ++i )
2241  tag_sizes[i] /= typesize;
2242  return result;
2243 }
2244 
2245 //! return the tag data for a given EntityHandle and Tag
2247  const Range& entity_handles,
2248  const void** tag_data,
2249  int* tag_sizes ) const
2250 {
2251  assert( valid_tag_handle( tag_handle ) );
2252  ErrorCode result = tag_handle->get_data( sequenceManager, mError, entity_handles, tag_data, tag_sizes );
2253  int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() );
2254  if( tag_sizes && typesize != 1 )
2255  {
2256  int num_entities = entity_handles.size();
2257  for( int i = 0; i < num_entities; ++i )
2258  tag_sizes[i] /= typesize;
2259  }
2260  return result;
2261 }
2262 
2263 //! set the data for given EntityHandles and Tag
2265  const EntityHandle* entity_handles,
2266  int num_entities,
2267  void const* const* tag_data,
2268  const int* tag_sizes )
2269 {
2270  assert( valid_tag_handle( tag_handle ) );
2272  std::vector< int > tmp_sizes;
2273  int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() );
2274  if( typesize != 1 && tag_sizes )
2275  {
2276  tmp_sizes.resize( num_entities );
2277  for( int i = 0; i < num_entities; ++i )
2278  tmp_sizes[i] = tag_sizes[i] * typesize;
2279  tag_sizes = &tmp_sizes[0];
2280  }
2281  return tag_handle->set_data( sequenceManager, mError, entity_handles, num_entities, tag_data, tag_sizes );
2282 }
2283 
2284 //! set the data for given EntityHandles and Tag
2286  const Range& entity_handles,
2287  void const* const* tag_data,
2288  const int* tag_sizes )
2289 {
2290  assert( valid_tag_handle( tag_handle ) );
2291  std::vector< int > tmp_sizes;
2292  int typesize = TagInfo::size_from_data_type( tag_handle->get_data_type() );
2293  if( typesize != 1 && tag_sizes )
2294  {
2295  int num_entities = entity_handles.size();
2296  tmp_sizes.resize( num_entities );
2297  for( int i = 0; i < num_entities; ++i )
2298  tmp_sizes[i] = tag_sizes[i] * typesize;
2299  tag_sizes = &tmp_sizes[0];
2300  }
2301  return tag_handle->set_data( sequenceManager, mError, entity_handles, tag_data, tag_sizes );
2302 }
2303 
2304 //! set the data for given EntityHandles and Tag
2306  const EntityHandle* entity_handles,
2307  int num_entities,
2308  const void* tag_data,
2309  int tag_size )
2310 {
2311  assert( valid_tag_handle( tag_handle ) );
2313  return tag_handle->clear_data( sequenceManager, mError, entity_handles, num_entities, tag_data,
2314  tag_size * TagInfo::size_from_data_type( tag_handle->get_data_type() ) );
2315 }
2316 
2317 //! set the data for given EntityHandles and Tag
2318 ErrorCode Core::tag_clear_data( Tag tag_handle, const Range& entity_handles, const void* tag_data, int tag_size )
2319 {
2320  assert( valid_tag_handle( tag_handle ) );
2321  return tag_handle->clear_data( sequenceManager, mError, entity_handles, tag_data,
2322  tag_size * TagInfo::size_from_data_type( tag_handle->get_data_type() ) );
2323 }
2324 
2325 static bool is_zero_bytes( const void* mem, size_t size )
2326 {
2327  const char* iter = reinterpret_cast< const char* >( mem );
2328  const char* const end = iter + size;
2329  for( ; iter != end; ++iter )
2330  if( *iter ) return false;
2331  return true;
2332 }
2333 
2335  int size,
2336  DataType data_type,
2337  Tag& tag_handle,
2338  unsigned flags,
2339  const void* default_value,
2340  bool* created )
2341 {
2342  if( created ) *created = false;
2343 
2344  // we always work with sizes in bytes internally
2345  if( !( ( flags & MB_TAG_VARLEN ) && size == MB_VARIABLE_LENGTH ) )
2346  {
2347  if( flags & MB_TAG_BYTES )
2348  {
2349  if( size % TagInfo::size_from_data_type( data_type ) ) return MB_INVALID_SIZE;
2350  }
2351  else
2352  {
2353  size *= TagInfo::size_from_data_type( data_type );
2354  }
2355  }
2356 
2357  const TagType storage = static_cast< TagType >( flags & 3 );
2358 
2359  // search for an existing tag
2360  tag_handle = 0;
2361  if( name && *name )
2362  { // not anonymous tag
2363  for( std::list< Tag >::iterator i = tagList.begin(); i != tagList.end(); ++i )
2364  {
2365  if( ( *i )->get_name() == name )
2366  {
2367  tag_handle = *i;
2368  break;
2369  }
2370  }
2371  }
2372 
2373  if( tag_handle )
2374  {
2375  if( flags & MB_TAG_EXCL ) return MB_ALREADY_ALLOCATED;
2376  // user asked that we not check anything
2377  if( flags & MB_TAG_ANY ) return MB_SUCCESS;
2378  // user asked that we also match storage types
2379  if( ( flags & MB_TAG_STORE ) && tag_handle->get_storage_type() != storage ) return MB_TYPE_OUT_OF_RANGE;
2380  // check if data type matches
2381  const DataType extype = tag_handle->get_data_type();
2382  if( extype != data_type )
2383  {
2384  if( flags & MB_TAG_NOOPQ )
2385  return MB_TYPE_OUT_OF_RANGE;
2386  else if( extype != MB_TYPE_OPAQUE && data_type != MB_TYPE_OPAQUE )
2387  return MB_TYPE_OUT_OF_RANGE;
2388  }
2389 
2390  // Require that the size value be zero or MB_VARIABLE_LENGTH
2391  // for variable length tags. The caller passing such a size
2392  // value is sufficient to indicate that the caller is aware
2393  // that it is requesting a variable-length tag, so no need
2394  // to also require/check the MB_TAG_VARLEN bit in the flags.
2395  if( tag_handle->variable_length() )
2396  {
2397  if( size != 0 && size != MB_VARIABLE_LENGTH && !( flags & MB_TAG_VARLEN ) ) return MB_INVALID_SIZE;
2398  }
2399  // But /do/ fail if MB_TAG_VARLEN flag is set and tag is
2400  // not variable length.
2401  else if( flags & MB_TAG_VARLEN )
2402  return MB_TYPE_OUT_OF_RANGE;
2403  // check size for fixed-length tag
2404  else if( tag_handle->get_size() != size )
2405  return MB_INVALID_SIZE;
2406 
2407  // If user passed a default value, check that it matches.
2408  // If user did not pass a default value, assume they're OK
2409  // with the existing one.
2410  // If tag does not have a default value but the user passed
2411  // one, allow it only if the tag is dense and the passed value
2412  // is all zero bytes because dense tags have an implicit default
2413  // value of all zeros in some cases.
2414  if( default_value && !( flags & MB_TAG_DFTOK ) &&
2415  !( tag_handle->equals_default_value( default_value, size ) ||
2416  ( !tag_handle->get_default_value() && tag_handle->get_storage_type() == MB_TAG_DENSE &&
2417  is_zero_bytes( default_value, size ) ) ) )
2418  return MB_ALREADY_ALLOCATED;
2419 
2420  return MB_SUCCESS;
2421  }
2422 
2423  // MB_TAG_EXCL implies MB_TAG_CREAT
2424  if( !( flags & ( MB_TAG_CREAT | MB_TAG_EXCL ) ) ) return MB_TAG_NOT_FOUND;
2425 
2426  // if a non-opaque non-bit type was specified, then the size
2427  // must be multiple of the size of the type
2428  if( ( !( flags & MB_TAG_VARLEN ) || default_value ) &&
2429  ( size <= 0 || ( size % TagInfo::size_from_data_type( data_type ) ) != 0 ) )
2430  return MB_INVALID_SIZE;
2431 
2432  // if MB_TYPE_BIT may be used only with MB_TAG_BIT
2433  // if (storage != MB_TAG_BIT && data_type == MB_TYPE_BIT)
2434  // return MB_INVALID_ARG;
2435  if( data_type == MB_TYPE_BIT ) flags &= ~(unsigned)( MB_TAG_DENSE | MB_TAG_SPARSE );
2436 
2437  // create the tag
2438  switch( flags & ( MB_TAG_DENSE | MB_TAG_SPARSE | MB_TAG_MESH | MB_TAG_VARLEN ) )
2439  {
2440  case MB_TAG_DENSE | MB_TAG_VARLEN:
2441  tag_handle = VarLenDenseTag::create_tag( sequenceManager, mError, name, data_type, default_value, size );
2442  break;
2443  case MB_TAG_DENSE:
2444  tag_handle = DenseTag::create_tag( sequenceManager, mError, name, size, data_type, default_value );
2445  break;
2447  tag_handle = new VarLenSparseTag( name, data_type, default_value, size );
2448  break;
2449  case MB_TAG_SPARSE:
2450  tag_handle = new SparseTag( name, size, data_type, default_value );
2451  break;
2452  case MB_TAG_MESH | MB_TAG_VARLEN:
2453  tag_handle = new MeshTag( name, MB_VARIABLE_LENGTH, data_type, default_value, size );
2454  break;
2455  case MB_TAG_MESH:
2456  tag_handle = new MeshTag( name, size, data_type, default_value, size );
2457  break;
2458  case MB_TAG_BIT:
2459  if( MB_TYPE_BIT != data_type && MB_TYPE_OPAQUE != data_type ) return MB_TYPE_OUT_OF_RANGE;
2460  tag_handle = BitTag::create_tag( name, size, default_value );
2461  break;
2462  default: // some illegal combination (multiple storage types, variable-length bit tag, etc.)
2463  return MB_TYPE_OUT_OF_RANGE;
2464  }
2465 
2466  if( !tag_handle ) return MB_INVALID_SIZE;
2467 
2468  if( created ) *created = true;
2469  tagList.push_back( tag_handle );
2470  return MB_SUCCESS;
2471 }
2472 
2474  int size,
2475  DataType data_type,
2476  Tag& tag_handle,
2477  unsigned flags,
2478  const void* default_value ) const
2479 {
2480  // If caller specified MB_TAG_EXCL, then we must fail because
2481  // this const function can never create a tag. We need to test
2482  // this here because the non-const version of this function
2483  // assumes MB_TAG_CREAT if MB_TAG_EXCL is specified.
2484  if( flags & MB_TAG_EXCL )
2485  {
2486  // anonymous tag?
2487  if( !name || !*name ) return MB_TAG_NOT_FOUND;
2488 
2489  // search for an existing tag
2490  tag_handle = 0;
2491  for( std::list< Tag >::const_iterator i = tagList.begin(); i != tagList.end(); ++i )
2492  {
2493  if( ( *i )->get_name() == name )
2494  {
2495  tag_handle = *i;
2496  return MB_ALREADY_ALLOCATED;
2497  }
2498  }
2499 
2500  return MB_TAG_NOT_FOUND;
2501  }
2502 
2503  return const_cast< Core* >( this )->tag_get_handle( name, size, data_type, tag_handle,
2504  flags & ~(unsigned)MB_TAG_CREAT, default_value );
2505 }
2506 
2507 //! removes the tag from the entity
2508 ErrorCode Core::tag_delete_data( Tag tag_handle, const EntityHandle* entity_handles, int num_entities )
2509 {
2510  assert( valid_tag_handle( tag_handle ) );
2512  return tag_handle->remove_data( sequenceManager, mError, entity_handles, num_entities );
2513 }
2514 
2515 //! removes the tag from the entity
2516 ErrorCode Core::tag_delete_data( Tag tag_handle, const Range& entity_handles )
2517 {
2518  assert( valid_tag_handle( tag_handle ) );
2519  return tag_handle->remove_data( sequenceManager, mError, entity_handles );
2520 }
2521 
2522 //! removes the tag from MB
2524 {
2525  std::list< TagInfo* >::iterator i = std::find( tagList.begin(), tagList.end(), tag_handle );
2526  if( i == tagList.end() ) return MB_TAG_NOT_FOUND;
2527 
2528  MB_CHK_SET_ERR( tag_handle->release_all_data( sequenceManager, mError, true ), "can't release all data" );
2529 
2530  tagList.erase( i );
2531  delete tag_handle;
2532  return MB_SUCCESS;
2533 }
2534 
2536  Range::const_iterator iter,
2538  int& count,
2539  void*& data_ptr,
2540  bool allocate )
2541 {
2542  Range::const_iterator init = iter;
2543  assert( valid_tag_handle( tag_handle ) );
2544  ErrorCode result = tag_handle->tag_iterate( sequenceManager, mError, iter, end, data_ptr, allocate );
2545  if( MB_SUCCESS == result ) count = iter - init;
2546  return result;
2547 }
2548 
2549 //! gets the tag name string for the tag_handle
2550 ErrorCode Core::tag_get_name( const Tag tag_handle, std::string& tag_name ) const
2551 {
2552  if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
2553  tag_name = tag_handle->get_name();
2554  return MB_SUCCESS;
2555 }
2556 
2557 ErrorCode Core::tag_get_handle( const char* tag_name, Tag& tag_handle ) const
2558 {
2559  return tag_get_handle( tag_name, 0, MB_TYPE_OPAQUE, tag_handle, MB_TAG_ANY );
2560 }
2561 
2562 //! get size of tag in bytes
2563 ErrorCode Core::tag_get_bytes( const Tag tag_handle, int& tag_size ) const
2564 {
2565  if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
2566 
2567  if( tag_handle->variable_length() )
2568  {
2569  tag_size = MB_VARIABLE_LENGTH;
2570  return MB_VARIABLE_DATA_LENGTH;
2571  }
2572  else if( tag_handle->get_storage_type() == MB_TAG_BIT )
2573  {
2574  tag_size = 1;
2575  return MB_SUCCESS;
2576  }
2577  else
2578  {
2579  tag_size = tag_handle->get_size();
2580  return MB_SUCCESS;
2581  }
2582 }
2583 
2584 //! get size of tag in $values
2585 ErrorCode Core::tag_get_length( const Tag tag_handle, int& tag_size ) const
2586 {
2587  if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
2588 
2589  if( tag_handle->variable_length() )
2590  {
2591  tag_size = MB_VARIABLE_LENGTH;
2592  return MB_VARIABLE_DATA_LENGTH;
2593  }
2594  else
2595  {
2596  tag_size = tag_handle->get_size() / TagInfo::size_from_data_type( tag_handle->get_data_type() );
2597  return MB_SUCCESS;
2598  }
2599 }
2600 
2601 ErrorCode Core::tag_get_data_type( const Tag handle, DataType& data_type ) const
2602 {
2603  if( !valid_tag_handle( handle ) ) return MB_TAG_NOT_FOUND;
2604 
2605  data_type = handle->get_data_type();
2606  return MB_SUCCESS;
2607 }
2608 
2609 //! get default value of the tag
2610 ErrorCode Core::tag_get_default_value( const Tag tag_handle, void* def_value ) const
2611 {
2612  if( !valid_tag_handle( tag_handle ) ) return MB_TAG_NOT_FOUND;
2613 
2614  if( tag_handle->variable_length() ) return MB_VARIABLE_DATA_LENGTH;
2615 
2616  if( !tag_handle->get_default_value() ) return MB_ENTITY_NOT_FOUND;
2617 
2618  memcpy( def_value, tag_handle->get_default_value(), tag_handle->get_default_value_size() );
2619  return MB_SUCCESS;
2620 }
2621 
2622 ErrorCode Core::tag_get_default_value( Tag tag, const void*& ptr, int& size ) const
2623 {
2624  if( !valid_tag_handle( tag ) ) return MB_ENTITY_NOT_FOUND;
2625 
2626  if( !tag->get_default_value() ) return MB_ENTITY_NOT_FOUND;
2627 
2628  ptr = tag->get_default_value();
2630  return MB_SUCCESS;
2631 }
2632 
2633 //! get type of tag (sparse, dense, etc.; 0 = dense, 1 = sparse, 2 = bit, 3 = static)
2634 ErrorCode Core::tag_get_type( const Tag tag_handle, TagType& tag_type ) const
2635 {
2636  assert( valid_tag_handle( tag_handle ) );
2637  tag_type = tag_handle->get_storage_type();
2638  return MB_SUCCESS;
2639 }
2640 
2641 //! get handles for all tags defined
2642 ErrorCode Core::tag_get_tags( std::vector< Tag >& tag_handles ) const
2643 {
2644  std::copy( tagList.begin(), tagList.end(), std::back_inserter( tag_handles ) );
2645  return MB_SUCCESS;
2646 }
2647 
2648 //! Get handles for all tags defined on this entity
2649 ErrorCode Core::tag_get_tags_on_entity( const EntityHandle entity, std::vector< Tag >& tag_handles ) const
2650 {
2651  for( std::list< TagInfo* >::const_iterator i = tagList.begin(); i != tagList.end(); ++i )
2652  if( ( *i )->is_tagged( sequenceManager, entity ) ) tag_handles.push_back( *i );
2653  return MB_SUCCESS;
2654 }
2655 
2657 {
2658  const int negone = -1;
2659  if( 0 == materialTag )
2660  tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, materialTag, MB_TAG_CREAT | MB_TAG_SPARSE, &negone );
2661  return materialTag;
2662 }
2663 
2665 {
2666  const int negone = -1;
2667  if( 0 == neumannBCTag )
2668  tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, neumannBCTag, MB_TAG_CREAT | MB_TAG_SPARSE, &negone );
2669  return neumannBCTag;
2670 }
2671 
2673 {
2674  const int negone = -1;
2675  if( 0 == dirichletBCTag )
2676  tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, dirichletBCTag, MB_TAG_CREAT | MB_TAG_SPARSE,
2677  &negone );
2678  return dirichletBCTag;
2679 }
2680 
2682 {
2683  const int negone = -1;
2684  if( 0 == globalIdTag )
2685  tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, globalIdTag, MB_TAG_CREAT | MB_TAG_DENSE, &negone );
2686  return globalIdTag;
2687 }
2688 
2690 {
2691  const int negone = -1;
2692  if( 0 == geomDimensionTag )
2693  tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomDimensionTag, MB_TAG_CREAT | MB_TAG_SPARSE,
2694  &negone );
2695  return geomDimensionTag;
2696 }
2697 
2698 //! creates an element based on the type and connectivity. returns a handle and error code
2699 ErrorCode Core::create_element( const EntityType entity_type,
2700  const EntityHandle* connectivity,
2701  const int num_nodes,
2702  EntityHandle& element_handle )
2703 {
2704  // make sure we have enough vertices for this entity type
2705  if( num_nodes < CN::VerticesPerEntity( entity_type ) ) return MB_FAILURE;
2706 
2707  ErrorCode status = sequence_manager()->create_element( entity_type, connectivity, num_nodes, element_handle );
2708  if( MB_SUCCESS == status ) status = aEntityFactory->notify_create_entity( element_handle, connectivity, num_nodes );
2709 
2710 #ifdef MOAB_HAVE_AHF
2711  mesh_modified = true;
2712 #endif
2713 
2714  return status;
2715 }
2716 
2717 //! creates a vertex based on coordinates, returns a handle and error code
2718 ErrorCode Core::create_vertex( const double coords[3], EntityHandle& entity_handle )
2719 {
2720  // get an available vertex handle
2721  return sequence_manager()->create_vertex( coords, entity_handle );
2722 }
2723 
2724 ErrorCode Core::create_vertices( const double* coordinates, const int nverts, Range& entity_handles )
2725 {
2726  // Create vertices
2727  ReadUtilIface* read_iface;
2728  ErrorCode result = Interface::query_interface( read_iface );
2729  MB_CHK_ERR( result );
2730 
2731  std::vector< double* > arrays;
2732  EntityHandle start_handle_out = 0;
2733  result = read_iface->get_node_coords( 3, nverts, MB_START_ID, start_handle_out, arrays );
2734  Interface::release_interface( read_iface );
2735  MB_CHK_ERR( result );
2736  // Cppcheck warning (false positive): variable arrays is assigned a value that is never used
2737  for( int i = 0; i < nverts; i++ )
2738  {
2739  arrays[0][i] = coordinates[3 * i];
2740  arrays[1][i] = coordinates[3 * i + 1];
2741  arrays[2][i] = coordinates[3 * i + 2];
2742  }
2743 
2744  entity_handles.clear();
2745  entity_handles.insert( start_handle_out, start_handle_out + nverts - 1 );
2746 
2747  return MB_SUCCESS;
2748 }
2749 
2750 //! merges two entities
2752  EntityHandle entity_to_remove,
2753  bool auto_merge,
2754  bool delete_removed_entity )
2755 {
2756  if( auto_merge ) return MB_FAILURE;
2757 
2758  // The two entities to merge must not be the same entity.
2759  if( entity_to_keep == entity_to_remove ) return MB_FAILURE;
2760 
2761  // The two entities to merge must be of the same type
2762  EntityType type_to_keep = TYPE_FROM_HANDLE( entity_to_keep );
2763 
2764  if( type_to_keep != TYPE_FROM_HANDLE( entity_to_remove ) ) return MB_TYPE_OUT_OF_RANGE;
2765 
2766  // Make sure both entities exist before trying to merge.
2767  EntitySequence* seq = 0;
2768  ErrorCode result, status;
2769  status = sequence_manager()->find( entity_to_keep, seq );
2770  if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
2771  status = sequence_manager()->find( entity_to_remove, seq );
2772  if( seq == 0 || status != MB_SUCCESS ) return MB_ENTITY_NOT_FOUND;
2773 
2774  // If auto_merge is not set, all sub-entities should
2775  // be merged if the entities are to be merged.
2776  int ent_dim = CN::Dimension( type_to_keep );
2777  if( ent_dim > 0 )
2778  {
2779  std::vector< EntityHandle > conn, conn2;
2780 
2781  result = get_connectivity( &entity_to_keep, 1, conn );
2782  MB_CHK_ERR( result );
2783  result = get_connectivity( &entity_to_remove, 1, conn2 );
2784  MB_CHK_ERR( result );
2785 
2786  // Check to see if we can merge before pulling adjacencies.
2787  int dum1, dum2;
2788  if( !auto_merge &&
2789  ( conn.size() != conn2.size() || !CN::ConnectivityMatch( &conn[0], &conn2[0], conn.size(), dum1, dum2 ) ) )
2790  return MB_FAILURE;
2791  }
2792 
2793  result = aEntityFactory->merge_adjust_adjacencies( entity_to_keep, entity_to_remove );
2794 
2795  if( MB_SUCCESS == result && delete_removed_entity ) result = delete_entities( &entity_to_remove, 1 );
2796 
2797  return result;
2798 }
2799 
2800 //! deletes an entity range
2802 {
2803  ErrorCode result = MB_SUCCESS, temp_result;
2804  Range failed_ents;
2805 
2806  for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i )
2807  {
2808  temp_result = ( *i )->remove_data( sequenceManager, mError, range );
2809  // ok if the error is tag_not_found, some ents may not have every tag on them
2810  if( MB_SUCCESS != temp_result && MB_TAG_NOT_FOUND != temp_result ) result = temp_result;
2811  }
2812 
2813  for( Range::const_reverse_iterator rit = range.rbegin(); rit != range.rend(); ++rit )
2814  {
2815 
2816  // tell AEntityFactory that this element is going away
2817  temp_result = aEntityFactory->notify_delete_entity( *rit );
2818  if( MB_SUCCESS != temp_result )
2819  {
2820  result = temp_result;
2821  failed_ents.insert( *rit );
2822  continue;
2823  }
2824 
2825  if( TYPE_FROM_HANDLE( *rit ) == MBENTITYSET )
2826  {
2827  if( MeshSet* ptr = get_mesh_set( sequence_manager(), *rit ) )
2828  {
2829  int j, count;
2830  const EntityHandle* rel;
2831  ptr->clear( *rit, a_entity_factory() );
2832  rel = ptr->get_parents( count );
2833  for( j = 0; j < count; ++j )
2834  remove_child_meshset( rel[j], *rit );
2835  rel = ptr->get_children( count );
2836  for( j = 0; j < count; ++j )
2837  remove_parent_meshset( rel[j], *rit );
2838  }
2839  }
2840  }
2841 
2842  if( !failed_ents.empty() )
2843  {
2844  Range dum_range = subtract( range, failed_ents );
2845  // don't test for success, since we'll return failure in this case
2846  sequence_manager()->delete_entities( mError, dum_range );
2847  }
2848  else
2849  // now delete the entities
2850  result = sequence_manager()->delete_entities( mError, range );
2851 
2852  return result;
2853 }
2854 
2855 //! deletes an entity vector
2856 ErrorCode Core::delete_entities( const EntityHandle* entities, const int num_entities )
2857 {
2858  ErrorCode result = MB_SUCCESS, temp_result;
2859  Range failed_ents;
2860 
2861  for( std::list< TagInfo* >::iterator i = tagList.begin(); i != tagList.end(); ++i )
2862  {
2863  temp_result = ( *i )->remove_data( sequenceManager, mError, entities, num_entities );
2864  // ok if the error is tag_not_found, some ents may not have every tag on them
2865  if( MB_SUCCESS != temp_result && MB_TAG_NOT_FOUND != temp_result ) result = temp_result;
2866  }
2867 
2868  for( int i = 0; i < num_entities; i++ )
2869  {
2870 
2871  // tell AEntityFactory that this element is going away
2872  bool failed = false;
2873  temp_result = aEntityFactory->notify_delete_entity( entities[i] );
2874  if( MB_SUCCESS != temp_result )
2875  {
2876  result = temp_result;
2877  failed = true;
2878  }
2879 
2880  if( TYPE_FROM_HANDLE( entities[i] ) == MBENTITYSET )
2881  {
2882  if( MeshSet* ptr = get_mesh_set( sequence_manager(), entities[i] ) )
2883  {
2884  int j, count;
2885  const EntityHandle* rel;
2886  ptr->clear( entities[i], a_entity_factory() );
2887  rel = ptr->get_parents( count );
2888  for( j = 0; j < count; ++j )
2889  remove_child_meshset( rel[j], entities[i] );
2890  rel = ptr->get_children( count );
2891  for( j = 0; j < count; ++j )
2892  remove_parent_meshset( rel[j], entities[i] );
2893  }
2894  }
2895 
2896  if( failed )
2897  // don't test for success, since we'll return failure in this case
2898  sequence_manager()->delete_entity( mError, entities[i] );
2899  else
2900  {
2901  // now delete the entity
2902  temp_result = sequence_manager()->delete_entity( mError, entities[i] );
2903  if( MB_SUCCESS != temp_result ) result = temp_result;
2904  }
2905  }
2906 
2907  return result;
2908 }
2909 
2910 ErrorCode Core::list_entities( const EntityHandle* entities, const int num_entities ) const
2911 {
2912  Range temp_range;
2913  ErrorCode result = MB_SUCCESS;
2914  if( NULL == entities && num_entities == 0 )
2915  {
2916  // just list the numbers of each entity type
2917  int num_ents;
2918  std::cout << std::endl;
2919  std::cout << "Number of entities per type: " << std::endl;
2920  for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
2921  {
2922  result = get_number_entities_by_type( 0, this_type, num_ents );
2923  std::cout << CN::EntityTypeName( this_type ) << ": " << num_ents << std::endl;
2924  }
2925  std::cout << std::endl;
2926 
2927  return MB_SUCCESS;
2928  }
2929  else if( NULL == entities && num_entities < 0 )
2930  {
2931 
2932  // list all entities of all types
2933  std::cout << std::endl;
2934  for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
2935  {
2936  result = get_entities_by_type( 0, this_type, temp_range );
2937  }
2938 
2939  return list_entities( temp_range );
2940  }
2941  else if( NULL == entities && num_entities > 0 )
2942  {
2943 
2944  // list all entities of type == num_entities
2945  std::cout << std::endl;
2946  result = get_entities_by_type( 0, (EntityType)num_entities, temp_range );
2947 
2948  return list_entities( temp_range );
2949  }
2950  else
2951  {
2952  ErrorCode tmp_result;
2953  for( int i = 0; i < num_entities; i++ )
2954  {
2955  EntityType this_type = TYPE_FROM_HANDLE( entities[i] );
2956  std::cout << CN::EntityTypeName( this_type ) << " " << ID_FROM_HANDLE( entities[i] ) << ":" << endl;
2957 
2958  tmp_result = ( const_cast< Core* >( this ) )->list_entity( entities[i] );
2959  if( MB_SUCCESS != tmp_result ) result = tmp_result;
2960  }
2961  }
2962 
2963  return result;
2964 }
2965 
2966 ErrorCode Core::list_entities( const Range& temp_range ) const
2967 {
2968  ErrorCode result = MB_SUCCESS, tmp_result;
2969 
2970  for( Range::const_iterator rit = temp_range.begin(); rit != temp_range.end(); ++rit )
2971  {
2972  EntityType this_type = TYPE_FROM_HANDLE( *rit );
2973  std::cout << CN::EntityTypeName( this_type ) << " " << ID_FROM_HANDLE( *rit ) << ":" << endl;
2974 
2975  tmp_result = ( const_cast< Core* >( this ) )->list_entity( *rit );
2976  if( MB_SUCCESS != tmp_result ) result = tmp_result;
2977  }
2978 
2979  return result;
2980 }
2981 
2983 {
2984  ErrorCode result;
2985  HandleVec adj_vec;
2986 
2987  if( !is_valid( entity ) )
2988  {
2989  std::cout << "(invalid)" << std::endl;
2990  return MB_SUCCESS;
2991  }
2992 
2993  if( 0 != globalIdTag )
2994  {
2995  int dum;
2996  result = tag_get_data( globalIdTag, &entity, 1, &dum );
2997  if( MB_SUCCESS == result ) std::cout << "Global id = " << dum << std::endl;
2998  }
2999 
3000  // list entity
3001  EntityType this_type = TYPE_FROM_HANDLE( entity );
3002  if( this_type == MBVERTEX )
3003  {
3004  double coords[3];
3005  result = get_coords( &( entity ), 1, coords );
3006  MB_CHK_ERR( result );
3007  std::cout << "Coordinates: (" << coords[0] << ", " << coords[1] << ", " << coords[2] << ")" << std::endl;
3008  }
3009  else if( this_type == MBENTITYSET )
3010  this->print( entity, "" );
3011 
3012  std::cout << " Adjacencies:" << std::endl;
3013  bool some = false;
3014  int multiple = 0;
3015  for( int dim = 0; dim <= 3; dim++ )
3016  {
3017  if( dim == CN::Dimension( this_type ) ) continue;
3018  adj_vec.clear();
3019  // use const_cast here 'cuz we're in a const function and we're passing 'false' for
3020  // create_if_missing, so we know we won't change anything
3021  result = ( const_cast< Core* >( this ) )->get_adjacencies( &( entity ), 1, dim, false, adj_vec );
3022  if( MB_FAILURE == result ) continue;
3023  for( HandleVec::iterator adj_it = adj_vec.begin(); adj_it != adj_vec.end(); ++adj_it )
3024  {
3025  if( adj_it != adj_vec.begin() )
3026  std::cout << ", ";
3027  else
3028  std::cout << " ";
3029  std::cout << CN::EntityTypeName( TYPE_FROM_HANDLE( *adj_it ) ) << " " << ID_FROM_HANDLE( *adj_it );
3030  }
3031  if( !adj_vec.empty() )
3032  {
3033  std::cout << std::endl;
3034  some = true;
3035  }
3036  if( MB_MULTIPLE_ENTITIES_FOUND == result ) multiple += dim;
3037  }
3038  if( !some ) std::cout << "(none)" << std::endl;
3039  const EntityHandle* explicit_adjs;
3040  int num_exp;
3041  aEntityFactory->get_adjacencies( entity, explicit_adjs, num_exp );
3042  if( NULL != explicit_adjs && 0 != num_exp )
3043  {
3044  std::cout << " Explicit adjacencies: ";
3045  for( int i = 0; i < num_exp; i++ )
3046  {
3047  if( i != 0 ) std::cout << ", ";
3048  std::cout << CN::EntityTypeName( TYPE_FROM_HANDLE( explicit_adjs[i] ) ) << " "
3049  << ID_FROM_HANDLE( explicit_adjs[i] );
3050  }
3051  std::cout << std::endl;
3052  }
3053  if( multiple != 0 ) std::cout << " (MULTIPLE = " << multiple << ")" << std::endl;
3054 
3055  result = print_entity_tags( std::string(), entity, MB_TAG_DENSE );
3056 
3057  std::cout << std::endl;
3058 
3059  return result;
3060 }
3061 
3063  const bool mid_side,
3064  const bool mid_face,
3065  const bool mid_volume,
3066  Interface::HONodeAddedRemoved* function_object )
3067 {
3068  HigherOrderFactory fact( this, function_object );
3069  return fact.convert( meshset, mid_side, mid_face, mid_volume );
3070 }
3071 
3072 //! function to get the side number given two elements; returns
3073 //! MB_FAILURE if child not related to parent; does *not* create adjacencies
3074 //! between parent and child
3076  const EntityHandle child,
3077  int& sd_number,
3078  int& sense,
3079  int& offset ) const
3080 {
3081  // get the connectivity of parent and child
3082  const EntityHandle *parent_conn = NULL, *child_conn = NULL;
3083  int num_parent_vertices = 0, num_child_vertices = 0;
3084  ErrorCode result = get_connectivity( parent, parent_conn, num_parent_vertices, true );
3085  if( MB_NOT_IMPLEMENTED == result )
3086  {
3087  static std::vector< EntityHandle > tmp_connect( CN::MAX_NODES_PER_ELEMENT );
3088  result = get_connectivity( parent, parent_conn, num_parent_vertices, true, &tmp_connect );
3089  }
3090  if( MB_SUCCESS != result ) return result;
3091 
3092  if( TYPE_FROM_HANDLE( child ) == MBVERTEX )
3093  {
3094  int child_index = std::find( parent_conn, parent_conn + num_parent_vertices, child ) - parent_conn;
3095  if( child_index == num_parent_vertices )
3096  {
3097  sd_number = -1;
3098  sense = 0;
3099  return MB_FAILURE;
3100  }
3101  else
3102  {
3103  sd_number = child_index;
3104  sense = 1;
3105  return MB_SUCCESS;
3106  }
3107  }
3108 
3109  if( TYPE_FROM_HANDLE( parent ) == MBPOLYHEDRON )
3110  {
3111  // find the child in the parent_conn connectivity list, and call it a day ..
3112  // it should work only for faces within a conn list
3113  for( int i = 0; i < num_parent_vertices; i++ )
3114  if( child == parent_conn[i] )
3115  {
3116  sd_number = i;
3117  sense = 1; // always
3118  offset = 0;
3119  return MB_SUCCESS;
3120  }
3121  return MB_FAILURE;
3122  }
3123  result = get_connectivity( child, child_conn, num_child_vertices, true );
3124  MB_CHK_ERR( result );
3125 
3126  // call handle vector-based function
3127  if( TYPE_FROM_HANDLE( parent ) != MBPOLYGON && TYPE_FROM_HANDLE( parent ) != MBPOLYHEDRON )
3128  {
3129 
3130  // find indices into parent_conn for each entry in child_conn
3131  int child_conn_indices[10];
3132  assert( (unsigned)num_child_vertices <= sizeof( child_conn_indices ) / sizeof( child_conn_indices[0] ) );
3133  for( int i = 0; i < num_child_vertices; ++i )
3134  {
3135  child_conn_indices[i] =
3136  std::find( parent_conn, parent_conn + num_parent_vertices, child_conn[i] ) - parent_conn;
3137  if( child_conn_indices[i] >= num_parent_vertices )
3138  {
3139  sd_number = -1;
3140  return MB_FAILURE;
3141  }
3142  }
3143 
3144  int temp_result = CN::SideNumber( TYPE_FROM_HANDLE( parent ), child_conn_indices, num_child_vertices,
3145  CN::Dimension( TYPE_FROM_HANDLE( child ) ), sd_number, sense, offset );
3146  return ( 0 == temp_result ? MB_SUCCESS : MB_FAILURE );
3147  }
3148  else if( TYPE_FROM_HANDLE( parent ) == MBPOLYGON )
3149  {
3150  // find location of 1st vertex; this works even for padded vertices
3151  const EntityHandle* first_v = std::find( parent_conn, parent_conn + num_parent_vertices, child_conn[0] );
3152  if( first_v == parent_conn + num_parent_vertices ) return MB_ENTITY_NOT_FOUND;
3153  sd_number = first_v - parent_conn;
3154  offset = sd_number;
3155  if( TYPE_FROM_HANDLE( child ) == MBVERTEX )
3156  {
3157  sense = 0;
3158  return MB_SUCCESS;
3159  }
3160  else if( TYPE_FROM_HANDLE( child ) == MBPOLYGON )
3161  {
3162  bool match = CN::ConnectivityMatch( parent_conn, child_conn, num_parent_vertices, sense, offset );
3163  sd_number = 0;
3164  if( match )
3165  return MB_SUCCESS;
3166  else
3167  return MB_ENTITY_NOT_FOUND;
3168  }
3169  else if( TYPE_FROM_HANDLE( child ) == MBEDGE )
3170  {
3171  // determine the actual number of vertices, for the padded case
3172  // the padded case could be like ABCDEFFF; num_parent_vertices=8,
3173  // actual_num_parent_vertices=6
3174  int actual_num_parent_vertices = num_parent_vertices;
3175  while( actual_num_parent_vertices >= 3 &&
3176  ( parent_conn[actual_num_parent_vertices - 2] == parent_conn[actual_num_parent_vertices - 1] ) )
3177  actual_num_parent_vertices--;
3178 
3179  if( parent_conn[( sd_number + 1 ) % num_parent_vertices] == child_conn[1] )
3180  sense = 1;
3181  else if( parent_conn[( sd_number + num_parent_vertices - 1 ) % num_parent_vertices] ==
3182  child_conn[1] ) // this will also cover edge AF for padded case, side will
3183  // be 0, sense -1
3184  sense = -1;
3185  // if edge FA in above example, we should return sd_number = 5, sense 1
3186  else if( ( sd_number == actual_num_parent_vertices - 1 ) && ( child_conn[1] == parent_conn[0] ) )
3187  sense = 1;
3188  else
3189  return MB_ENTITY_NOT_FOUND;
3190  return MB_SUCCESS;
3191  }
3192  }
3193 
3194  return MB_FAILURE;
3195 }
3196 
3197 //! given an entity and the connectivity and type of one of its subfacets, find the
3198 //! high order node on that subfacet, if any
3200  const EntityHandle* subfacet_conn,
3201  const EntityType subfacet_type,
3202  EntityHandle& hon ) const
3203 {
3204  hon = 0;
3205 
3206  EntityType parent_type = TYPE_FROM_HANDLE( parent_handle );
3207 
3208  // get the parent's connectivity
3209  const EntityHandle* parent_conn = NULL;
3210  int num_parent_vertices = 0;
3211  ErrorCode result = get_connectivity( parent_handle, parent_conn, num_parent_vertices, false );
3212  MB_CHK_ERR( result );
3213 
3214  // find whether this entity has ho nodes
3215  int mid_nodes[4];
3216  CN::HasMidNodes( parent_type, num_parent_vertices, mid_nodes );
3217 
3218  // check whether this entity has mid nodes on this dimension subfacet;
3219  // use dimension-1 because vertices don't have mid nodes
3220  if( !mid_nodes[CN::Dimension( subfacet_type )] ) return MB_SUCCESS;
3221 
3222  // ok, we have mid nodes; now must compute expected index in connectivity array;
3223  // ho nodes stored for edges, faces then entity
3224 
3225  // offset starts with # corner vertices
3226  int offset = CN::VerticesPerEntity( parent_type );
3227  int i;
3228 
3229  for( i = 0; i < CN::Dimension( subfacet_type ) - 1; i++ )
3230  // for each dimension lower than that of the subfacet we're looking for,
3231  // if this entity has midnodes in that dimension, increment offset by #
3232  // of subfacets of that dimension; use dimension-1 in loop because
3233  // canon numbering table only has 2 positions, for edges and faces;
3234  if( mid_nodes[i + 1] ) offset += CN::mConnectivityMap[parent_type][i].num_sub_elements;
3235 
3236  // now add the index of this subfacet; only need to if it's not the highest dimension
3237  if( subfacet_type != parent_type )
3238  {
3239 
3240  // find indices into parent_conn for each entry in child_conn
3241  unsigned subfacet_size = CN::VerticesPerEntity( subfacet_type );
3242  int subfacet_indices[10];
3243  assert( subfacet_size <= sizeof( subfacet_indices ) / sizeof( subfacet_indices[0] ) );
3244  for( unsigned j = 0; j < subfacet_size; ++j )
3245  {
3246  subfacet_indices[j] =
3247  std::find( parent_conn, parent_conn + num_parent_vertices, subfacet_conn[j] ) - parent_conn;
3248  if( subfacet_indices[j] >= num_parent_vertices )
3249  {
3250  return MB_FAILURE;
3251  }
3252  }
3253 
3254  int dum, side_no, temp_offset;
3255  int temp_result =
3256  CN::SideNumber( parent_type, subfacet_indices, subfacet_size, subfacet_type, side_no, dum, temp_offset );
3257  if( temp_result != 0 ) return MB_FAILURE;
3258 
3259  offset += side_no;
3260  }
3261 
3262  // offset shouldn't be off the end of the connectivity vector
3263  if( offset >= num_parent_vertices ) return MB_INDEX_OUT_OF_RANGE;
3264 
3265  hon = parent_conn[offset];
3266 
3267  return MB_SUCCESS;
3268 }
3269 
3270 //! given an entity and a target dimension & side number, get that entity
3272  const int dim,
3273  const int sd_number,
3274  EntityHandle& target_entity ) const
3275 {
3276  // get a handle on the connectivity
3277  const EntityHandle* verts;
3278  int num_verts;
3279  ErrorCode result = get_connectivity( source_entity, verts, num_verts );
3280  MB_CHK_ERR( result );
3281 
3282  // special case for vertices
3283  if( dim == 0 )
3284  {
3285  if( sd_number < num_verts )
3286  {
3287  target_entity = verts[sd_number];
3288  return MB_SUCCESS;
3289  }
3290 
3291  else
3292  return MB_INDEX_OUT_OF_RANGE;
3293  }
3294 
3295  // get the vertices comprising the target entity
3296  Range side_verts, target_ents;
3297  const EntityType source_type = TYPE_FROM_HANDLE( source_entity );
3298  // first get the indices
3299  std::vector< int > vertex_indices;
3300 
3301  int temp_result = CN::AdjacentSubEntities( source_type, &sd_number, 1, dim, 0, vertex_indices );
3302  if( 0 != temp_result ) return MB_FAILURE;
3303  // now get the actual vertices
3304  for( unsigned int i = 0; i < vertex_indices.size(); i++ )
3305  side_verts.insert( verts[vertex_indices[i]] );
3306 
3307  // now look for an entity of the correct type
3308  // use const_cast here 'cuz we're in a const function and we're passing 'false' for
3309  // create_if_missing, so we know we won't change anything
3310  result = ( const_cast< Core* >( this ) )->get_adjacencies( side_verts, dim, false, target_ents );
3311  if( MB_SUCCESS != result && MB_MULTIPLE_ENTITIES_FOUND != result ) return result;
3312 
3313  if( !target_ents.empty() && TYPE_FROM_HANDLE( *( target_ents.begin() ) ) != MBVERTEX &&
3314  TYPE_FROM_HANDLE( *( target_ents.begin() ) ) !=
3315  CN::mConnectivityMap[source_type][dim - 1].target_type[sd_number] )
3316  return MB_ENTITY_NOT_FOUND;
3317 
3318  if( !target_ents.empty() ) target_entity = *( target_ents.begin() );
3319 
3320  return result;
3321 }
3322 
3323 //-------------------------Set Functions---------------------//
3324 
3325 ErrorCode Core::create_meshset( const unsigned int setoptions, EntityHandle& ms_handle, int )
3326 {
3327  return sequence_manager()->create_mesh_set( setoptions, ms_handle );
3328 }
3329 
3330 ErrorCode Core::get_meshset_options( const EntityHandle ms_handle, unsigned int& setoptions ) const
3331 {
3332  if( !ms_handle )
3333  { // root set
3334  setoptions = MESHSET_SET | MESHSET_TRACK_OWNER;
3335  return MB_SUCCESS;
3336  }
3337 
3338  const MeshSet* set = get_mesh_set( sequence_manager(), ms_handle );
3339  if( !set ) return MB_ENTITY_NOT_FOUND;
3340 
3341  setoptions = set->flags();
3342  return MB_SUCCESS;
3343 }
3344 
3345 ErrorCode Core::set_meshset_options( const EntityHandle ms_handle, const unsigned int setoptions )
3346 {
3347  MeshSet* set = get_mesh_set( sequence_manager(), ms_handle );
3348  if( !set ) return MB_ENTITY_NOT_FOUND;
3349 
3350  return set->set_flags( setoptions, ms_handle, a_entity_factory() );
3351 }
3352 
3353 ErrorCode Core::clear_meshset( const EntityHandle* ms_handles, const int num_meshsets )
3354 {
3355  ErrorCode result = MB_SUCCESS;
3356  for( int i = 0; i < num_meshsets; ++i )
3357  {
3358  MeshSet* set = get_mesh_set( sequence_manager(), ms_handles[i] );
3359  if( set )
3360  set->clear( ms_handles[i], a_entity_factory() );
3361  else
3362  result = MB_ENTITY_NOT_FOUND;
3363  }
3364 
3365  return result;
3366 }
3367 
3369 {
3370  ErrorCode result = MB_SUCCESS;
3371  for( Range::iterator i = ms_handles.begin(); i != ms_handles.end(); ++i )
3372  {
3373  MeshSet* set = get_mesh_set( sequence_manager(), *i );
3374  if( set )
3375  set->clear( *i, a_entity_factory() );
3376  else
3377  result = MB_ENTITY_NOT_FOUND;
3378  }
3379 
3380  return result;
3381 }
3382 
3384 {
3385  MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 );
3386  MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 );
3387  if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND;
3388 
3389  return set1->subtract( set2, meshset1, a_entity_factory() );
3390 }
3391 
3393 {
3394  MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 );
3395  MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 );
3396  if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND;
3397 
3398  return set1->intersect( set2, meshset1, a_entity_factory() );
3399 }
3400 
3402 {
3403  MeshSet* set1 = get_mesh_set( sequence_manager(), meshset1 );
3404  MeshSet* set2 = get_mesh_set( sequence_manager(), meshset2 );
3405  if( !set1 || !set2 ) return MB_ENTITY_NOT_FOUND;
3406 
3407  return set1->unite( set2, meshset1, a_entity_factory() );
3408 }
3409 
3410 ErrorCode Core::add_entities( EntityHandle meshset, const Range& entities )
3411 {
3412  MeshSet* set = get_mesh_set( sequence_manager(), meshset );
3413  if( set )
3414  return set->add_entities( entities, meshset, a_entity_factory() );
3415  else
3416  return MB_ENTITY_NOT_FOUND;
3417 }
3418 
3419 ErrorCode Core::add_entities( EntityHandle meshset, const EntityHandle* entities, const int num_entities )
3420 {
3421  MeshSet* set = get_mesh_set( sequence_manager(), meshset );
3422  if( set )
3423  return set->add_entities( entities, num_entities, meshset, a_entity_factory() );
3424  else
3425  return MB_ENTITY_NOT_FOUND;
3426 }
3427 
3428 //! remove a range of entities from a meshset
3430 {
3431  MeshSet* set = get_mesh_set( sequence_manager(), meshset );
3432  if( set )
3433  return set->remove_entities( entities, meshset, a_entity_factory() );
3434  else
3435  return MB_ENTITY_NOT_FOUND;
3436 }
3437 
3438 //! remove a vector of entities from a meshset
3439 ErrorCode Core::remove_entities( EntityHandle meshset, const EntityHandle* entities, const int num_entities )
3440 {
3441  MeshSet* set = get_mesh_set( sequence_manager(), meshset );
3442  if( set )
3443  return set->remove_entities( entities, num_entities, meshset, a_entity_factory() );
3444  else
3445  return MB_ENTITY_NOT_FOUND;
3446 }
3447 
3448 //! return true if all entities are contained in set
3450  const EntityHandle* entities,
3451  int num_entities,
3452  const int operation_type )
3453 {
3454  if( !meshset ) // root
3455  return true;
3456  else if( MeshSet* set = get_mesh_set( sequence_manager(), meshset ) )
3457  return set->contains_entities( entities, num_entities, operation_type );
3458  else
3459  return false;
3460 }
3461 
3462 // replace entities in a meshset
3464  const EntityHandle* old_entities,
3465  const EntityHandle* new_entities,
3466  int num_entities )
3467 {
3468  MeshSet* set = get_mesh_set( sequence_manager(), meshset );
3469  if( set )
3470  return set->replace_entities( meshset, old_entities, new_entities, num_entities, a_entity_factory() );
3471  else
3472  return MB_ENTITY_NOT_FOUND;
3473 }
3474 
3476  std::vector< EntityHandle >& parents,
3477  const int num_hops ) const
3478 {
3479  if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
3480 
3481  const EntitySequence* seq;
3482  ErrorCode rval = sequence_manager()->find( meshset, seq );
3483  if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
3484  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
3485 
3486  return mseq->get_parents( sequence_manager(), meshset, parents, num_hops );
3487 }
3488 
3489 ErrorCode Core::get_parent_meshsets( const EntityHandle meshset, Range& parents, const int num_hops ) const
3490 {
3491  if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
3492 
3493  std::vector< EntityHandle > parent_vec;
3494  ErrorCode result = get_parent_meshsets( meshset, parent_vec, num_hops );
3495  MB_CHK_ERR( result );
3496  std::sort( parent_vec.begin(), parent_vec.end() );
3497  std::copy( parent_vec.rbegin(), parent_vec.rend(), range_inserter( parents ) );
3498  return MB_SUCCESS;
3499 }
3500 
3502  std::vector< EntityHandle >& children,
3503  const int num_hops ) const
3504 {
3505  if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
3506 
3507  const EntitySequence* seq;
3508  ErrorCode rval = sequence_manager()->find( meshset, seq );
3509  if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
3510  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
3511 
3512  return mseq->get_children( sequence_manager(), meshset, children, num_hops );
3513 }
3514 
3515 ErrorCode Core::get_child_meshsets( const EntityHandle meshset, Range& children, const int num_hops ) const
3516 {
3517  if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
3518 
3519  std::vector< EntityHandle > child_vec;
3520  ErrorCode result = get_child_meshsets( meshset, child_vec, num_hops );
3521  MB_CHK_ERR( result );
3522  std::sort( child_vec.begin(), child_vec.end() );
3523  std::copy( child_vec.rbegin(), child_vec.rend(), range_inserter( children ) );
3524  return MB_SUCCESS;
3525 }
3526 
3528  std::vector< EntityHandle >& children,
3529  const int num_hops ) const
3530 {
3531  if( 0 == meshset )
3532  {
3533  return get_entities_by_type( meshset, MBENTITYSET, children );
3534  }
3535 
3536  const EntitySequence* seq;
3537  ErrorCode rval = sequence_manager()->find( meshset, seq );
3538  if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
3539  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
3540 
3541  return mseq->get_contained_sets( sequence_manager(), meshset, children, num_hops );
3542 }
3543 
3544 ErrorCode Core::get_contained_meshsets( const EntityHandle meshset, Range& children, const int num_hops ) const
3545 {
3546  if( 0 == meshset )
3547  {
3548  return get_entities_by_type( meshset, MBENTITYSET, children );
3549  }
3550 
3551  std::vector< EntityHandle > child_vec;
3552  ErrorCode result = get_contained_meshsets( meshset, child_vec, num_hops );
3553  MB_CHK_ERR( result );
3554  std::sort( child_vec.begin(), child_vec.end() );
3555  std::copy( child_vec.rbegin(), child_vec.rend(), range_inserter( children ) );
3556  return MB_SUCCESS;
3557 }
3558 
3559 ErrorCode Core::num_parent_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const
3560 {
3561  if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
3562 
3563  const EntitySequence* seq;
3564  ErrorCode rval = sequence_manager()->find( meshset, seq );
3565  if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
3566  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
3567 
3568  return mseq->num_parents( sequence_manager(), meshset, *number, num_hops );
3569 }
3570 
3571 ErrorCode Core::num_child_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const
3572 {
3573  if( 0 == meshset ) return MB_ENTITY_NOT_FOUND;
3574 
3575  const EntitySequence* seq;
3576  ErrorCode rval = sequence_manager()->find( meshset, seq );
3577  if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
3578  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
3579 
3580  return mseq->num_children( sequence_manager(), meshset, *number, num_hops );
3581 }
3582 
3583 ErrorCode Core::num_contained_meshsets( const EntityHandle meshset, int* number, const int num_hops ) const
3584 {
3585  if( 0 == meshset )
3586  {
3587  return get_number_entities_by_type( 0, MBENTITYSET, *number );
3588  }
3589 
3590  const EntitySequence* seq;
3591  ErrorCode rval = sequence_manager()->find( meshset, seq );
3592  if( MB_SUCCESS != rval ) return MB_ENTITY_NOT_FOUND;
3593  const MeshSetSequence* mseq = reinterpret_cast< const MeshSetSequence* >( seq );
3594 
3595  return mseq->num_contained_sets( sequence_manager(), meshset, *number, num_hops );
3596 }
3597 
3599 {
3600  MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
3601  MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent_meshset );
3602  if( !set_ptr || !parent_ptr ) return MB_ENTITY_NOT_FOUND;
3603 
3604  set_ptr->add_parent( parent_meshset );
3605  return MB_SUCCESS;
3606 }
3607 
3608 ErrorCode Core::add_parent_meshsets( EntityHandle meshset, const EntityHandle* parents, int count )
3609 {
3610  MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
3611  if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
3612 
3613  for( int i = 0; i < count; ++i )
3614  if( !get_mesh_set( sequence_manager(), parents[i] ) ) return MB_ENTITY_NOT_FOUND;
3615 
3616  for( int i = 0; i < count; ++i )
3617  set_ptr->add_parent( parents[i] );
3618  return MB_SUCCESS;
3619 }
3620 
3622 {
3623  MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
3624  MeshSet* child_ptr = get_mesh_set( sequence_manager(), child_meshset );
3625  if( !set_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND;
3626 
3627  set_ptr->add_child( child_meshset );
3628  return MB_SUCCESS;
3629 }
3630 
3631 ErrorCode Core::add_child_meshsets( EntityHandle meshset, const EntityHandle* children, int count )
3632 {
3633  MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
3634  if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
3635 
3636  for( int i = 0; i < count; ++i )
3637  if( !get_mesh_set( sequence_manager(), children[i] ) ) return MB_ENTITY_NOT_FOUND;
3638 
3639  for( int i = 0; i < count; ++i )
3640  set_ptr->add_child( children[i] );
3641  return MB_SUCCESS;
3642 }
3643 
3645 {
3646  MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent );
3647  MeshSet* child_ptr = get_mesh_set( sequence_manager(), child );
3648  if( !parent_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND;
3649 
3650  parent_ptr->add_child( child );
3651  child_ptr->add_parent( parent );
3652  return MB_SUCCESS;
3653 }
3654 
3656 {
3657  MeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent );
3658  MeshSet* child_ptr = get_mesh_set( sequence_manager(), child );
3659  if( !parent_ptr || !child_ptr ) return MB_ENTITY_NOT_FOUND;
3660 
3661  parent_ptr->remove_child( child );
3662  child_ptr->remove_parent( parent );
3663  return MB_SUCCESS;
3664 }
3665 
3667 {
3668  MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
3669  if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
3670  set_ptr->remove_parent( parent_meshset );
3671  return MB_SUCCESS;
3672 }
3673 
3675 {
3676  MeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
3677  if( !set_ptr ) return MB_ENTITY_NOT_FOUND;
3678  set_ptr->remove_child( child_meshset );
3679  return MB_SUCCESS;
3680 }
3681 
3682 ErrorCode Core::get_last_error( std::string& info ) const
3683 {
3685  return MB_SUCCESS;
3686 }
3687 
3688 std::string Core::get_error_string( const ErrorCode code ) const
3689 {
3690  return (unsigned)code <= (unsigned)MB_FAILURE ? ErrorCodeStr[code] : "INVALID ERROR CODE";
3691 }
3692 
3693 void Core::print( const EntityHandle ms_handle, const char* prefix, bool first_call ) const
3694 {
3695  // get the entities
3696  Range entities;
3697 
3698  if( 0 != ms_handle )
3699  {
3700  get_entities_by_handle( ms_handle, entities );
3701  std::cout << prefix << "MBENTITYSET " << ID_FROM_HANDLE( ms_handle ) << std::endl;
3702  }
3703  else
3704  {
3705  get_entities_by_dimension( 0, 3, entities );
3706  if( entities.empty() ) get_entities_by_dimension( 0, 2, entities );
3707  if( entities.empty() ) get_entities_by_dimension( 0, 1, entities );
3708  get_entities_by_dimension( 0, 0, entities );
3709  get_entities_by_type( 0, MBENTITYSET, entities );
3710  std::cout << prefix << "--: " << std::endl;
3711  }
3712 
3713  std::string indent_prefix = prefix;
3714  indent_prefix += " ";
3715  entities.print( indent_prefix.c_str() );
3716 
3717  if( !first_call || !ms_handle ) return;
3718 
3719  // print parent/children
3720  Range temp;
3721  this->get_parent_meshsets( ms_handle, temp );
3722  std::cout << " Parent sets: ";
3723  if( temp.empty() )
3724  std::cout << "(none)" << std::endl;
3725  else
3726  {
3727  for( Range::iterator rit = temp.begin(); rit != temp.end(); ++rit )
3728  {
3729  if( rit != temp.begin() ) std::cout << ", ";
3730  std::cout << ID_FROM_HANDLE( *rit );
3731  }
3732  std::cout << std::endl;
3733  }
3734 
3735  temp.clear();
3736  this->get_child_meshsets( ms_handle, temp );
3737  std::cout << " Child sets: ";
3738  if( temp.empty() )
3739  std::cout << "(none)" << std::endl;
3740  else
3741  {
3742  for( Range::iterator rit = temp.begin(); rit != temp.end(); ++rit )
3743  {
3744  if( rit != temp.begin() ) std::cout << ", ";
3745  std::cout << ID_FROM_HANDLE( *rit );
3746  }
3747  std::cout << std::endl;
3748  }
3749 
3750  // print all sparse tags
3751  print_entity_tags( indent_prefix, ms_handle, MB_TAG_SPARSE );
3752 }
3753 
3754 ErrorCode Core::print_entity_tags( std::string indent_prefix, const EntityHandle handle, TagType tp ) const
3755 {
3756  std::vector< Tag > set_tags;
3757  ErrorCode result = this->tag_get_tags_on_entity( handle, set_tags );
3758  std::cout << indent_prefix << ( tp == MB_TAG_SPARSE ? "Sparse tags:" : "Dense tags:" ) << std::endl;
3759  indent_prefix += " ";
3760 
3761  for( std::vector< Tag >::iterator vit = set_tags.begin(); vit != set_tags.end(); ++vit )
3762  {
3763  TagType this_type;
3764  result = this->tag_get_type( *vit, this_type );
3765  if( MB_SUCCESS != result || tp != this_type ) continue;
3766  DataType this_data_type;
3767  result = this->tag_get_data_type( *vit, this_data_type );
3768  if( MB_SUCCESS != result ) continue;
3769  int this_size;
3770  result = this->tag_get_length( *vit, this_size );
3771  if( MB_SUCCESS != result ) continue;
3772  // use double since this is largest single-valued tag
3773  std::vector< double > dbl_vals( this_size );
3774  std::vector< int > int_vals( this_size );
3775  std::vector< EntityHandle > hdl_vals( this_size );
3776  std::string tag_name;
3777  result = this->tag_get_name( *vit, tag_name );
3778  if( MB_SUCCESS != result ) continue;
3779  switch( this_data_type )
3780  {
3781  case MB_TYPE_INTEGER:
3782  result = this->tag_get_data( *vit, &handle, 1, &int_vals[0] );
3783  if( MB_SUCCESS != result ) continue;
3784  std::cout << indent_prefix << tag_name << " = ";
3785  if( this_size < 10 )
3786  for( int i = 0; i < this_size; i++ )
3787  std::cout << int_vals[i] << " ";
3788  else
3789  std::cout << int_vals[0] << "... (mult values)";
3790  std::cout << std::endl;
3791  break;
3792  case MB_TYPE_DOUBLE:
3793  result = this->tag_get_data( *vit, &handle, 1, &dbl_vals[0] );
3794  if( MB_SUCCESS != result ) continue;
3795  std::cout << indent_prefix << tag_name << " = ";
3796  if( this_size < 10 )
3797  for( int i = 0; i < this_size; i++ )
3798  std::cout << dbl_vals[i] << " ";
3799  else
3800  std::cout << dbl_vals[0] << "... (mult values)";
3801  std::cout << std::endl;
3802  break;
3803  case MB_TYPE_HANDLE:
3804  result = this->tag_get_data( *vit, &handle, 1, &hdl_vals[0] );
3805  if( MB_SUCCESS != result ) continue;
3806  std::cout << indent_prefix << tag_name << " = ";
3807  if( this_size < 10 )
3808  for( int i = 0; i < this_size; i++ )
3809  std::cout << hdl_vals[i] << " ";
3810  else
3811  std::cout << hdl_vals[0] << "... (mult values)";
3812  std::cout << std::endl;
3813  break;
3814  case MB_TYPE_OPAQUE:
3815  if( NAME_TAG_SIZE == this_size )
3816  {
3817  char dum_tag[NAME_TAG_SIZE];
3818  result = this->tag_get_data( *vit, &handle, 1, &dum_tag );
3819  if( MB_SUCCESS != result ) continue;
3820  // insert NULL just in case there isn't one
3821  dum_tag[NAME_TAG_SIZE - 1] = '\0';
3822  std::cout << indent_prefix << tag_name << " = " << dum_tag << std::endl;
3823  }
3824  break;
3825  case MB_TYPE_BIT:
3826  break;
3827  }
3828  }
3829 
3830  return MB_SUCCESS;
3831 }
3832 
3834 {
3835  // run through all entities, checking adjacencies and reverse-evaluating them
3836  Range all_ents;
3837  ErrorCode result = get_entities_by_handle( 0, all_ents );
3838  MB_CHK_ERR( result );
3839 
3840  for( Range::iterator rit = all_ents.begin(); rit != all_ents.end(); ++rit )
3841  {
3842  result = check_adjacencies( &( *rit ), 1 );
3843  MB_CHK_ERR( result );
3844  }
3845 
3846  return MB_SUCCESS;
3847 }
3848 
3849 ErrorCode Core::check_adjacencies( const EntityHandle* ents, int num_ents )
3850 {
3851 
3852  ErrorCode result = MB_SUCCESS, tmp_result;
3853  std::ostringstream oss;
3854 
3855  for( int i = 0; i < num_ents; i++ )
3856  {
3857  EntityHandle this_ent = ents[i];
3858  std::ostringstream ent_str;
3859  ent_str << CN::EntityTypeName( TYPE_FROM_HANDLE( this_ent ) ) << " " << ID_FROM_HANDLE( this_ent ) << ": ";
3860  int this_dim = dimension_from_handle( this_ent );
3861 
3862  if( !is_valid( this_ent ) )
3863  {
3864  std::cerr << ent_str.str() << "Not a valid entity." << std::endl;
3865  result = MB_FAILURE;
3866  }
3867 
3868  else
3869  {
3870  if( TYPE_FROM_HANDLE( this_ent ) == MBENTITYSET ) continue;
3871 
3872  // get adjacencies for this entity
3873  Range adjs;
3874  for( int dim = 0; dim <= 3; dim++ )
3875  {
3876  if( dim == this_dim ) continue;
3877  tmp_result = get_adjacencies( &this_ent, 1, dim, false, adjs, Interface::UNION );
3878  if( MB_SUCCESS != tmp_result )
3879  {
3880  oss << ent_str.str() << "Failed to get adjacencies for dimension " << dim << "." << std::endl;
3881  result = tmp_result;
3882  }
3883  }
3884  if( !oss.str().empty() )
3885  {
3886  std::cerr << oss.str();
3887  oss.str( "" );
3888  }
3889 
3890  // now check and reverse-evaluate them
3891  for( Range::iterator rit = adjs.begin(); rit != adjs.end(); ++rit )
3892  {
3893  EntitySequence* seq = 0;
3894  tmp_result = sequence_manager()->find( *rit, seq );
3895  if( seq == 0 || tmp_result != MB_SUCCESS )
3896  {
3897  oss << ent_str.str() << "Adjacent entity " << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " "
3898  << ID_FROM_HANDLE( *rit ) << " is invalid." << std::endl;
3899  result = tmp_result;
3900  }
3901  else
3902  {
3903  Range rev_adjs;
3904  tmp_result = get_adjacencies( &( *rit ), 1, this_dim, false, rev_adjs );
3905  if( MB_SUCCESS != tmp_result )
3906  {
3907  oss << ent_str.str() << "Failed to get reverse adjacency from "
3908  << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " " << ID_FROM_HANDLE( *rit );
3909  if( MB_MULTIPLE_ENTITIES_FOUND == tmp_result )
3910  oss << " (MULTIPLE)" << std::endl;
3911  else
3912  oss << " (" << tmp_result << ")" << std::endl;
3913  result = tmp_result;
3914  }
3915  else if( rev_adjs.find( this_ent ) == rev_adjs.end() )
3916  {
3917  oss << ent_str.str() << "Failed to find adjacency to this entity from "
3918  << CN::EntityTypeName( TYPE_FROM_HANDLE( *rit ) ) << " " << ID_FROM_HANDLE( *rit ) << "."
3919  << std::endl;
3920  result = tmp_result;
3921  }
3922  }
3923  if( !oss.str().empty() )
3924  {
3925  std::cerr << oss.str();
3926  oss.str( "" );
3927  }
3928  }
3929  }
3930  }
3931 
3932  return result;
3933 }
3934 
3935 bool Core::is_valid( const EntityHandle this_ent ) const
3936 {
3937  const EntitySequence* seq = 0;
3938  ErrorCode result = sequence_manager()->find( this_ent, seq );
3939  return seq != 0 && result == MB_SUCCESS;
3940 }
3941 
3943  EntityType ent_type,
3944  int ent_dim,
3945  int chunk_size,
3946  bool check_valid,
3947  SetIterator*& set_iter )
3948 {
3949  // check the type of set
3950  unsigned int setoptions;
3951  if( meshset )
3952  {
3953  MB_CHK_SET_ERR( get_meshset_options( meshset, setoptions ), "can't get meshset options" );
3954  }
3955 
3956  if( !meshset || ( setoptions & MESHSET_SET ) )
3957  set_iter = new( std::nothrow ) RangeSetIterator( this, meshset, chunk_size, ent_type, ent_dim, check_valid );
3958  else
3959  set_iter = new( std::nothrow ) VectorSetIterator( this, meshset, chunk_size, ent_type, ent_dim, check_valid );
3960 
3961  setIterators.push_back( set_iter );
3962  return MB_SUCCESS;
3963 }
3964 
3965 /** \brief Remove the set iterator from the instance's list
3966  * This function is called from the SetIterator destructor, and should not be called directly
3967  * from anywhere else.
3968  * \param set_iter Set iterator being removed
3969  */
3971 {
3972  std::vector< SetIterator* >::iterator vit = std::find( setIterators.begin(), setIterators.end(), set_iter );
3973  if( vit == setIterators.end() )
3974  {
3975  MB_SET_ERR( MB_FAILURE, "Didn't find that iterator" );
3976  }
3977 
3978  setIterators.erase( vit );
3979 
3980  return MB_SUCCESS;
3981 }
3982 
3983 /** \brief Get all set iterators associated with the set passed in
3984  * \param meshset Meshset for which iterators are requested
3985  * \param set_iters Set iterators for the set
3986  */
3987 ErrorCode Core::get_set_iterators( EntityHandle meshset, std::vector< SetIterator* >& set_iters )
3988 {
3989  for( std::vector< SetIterator* >::const_iterator vit = setIterators.begin(); vit != setIterators.end(); ++vit )
3990  if( ( *vit )->ent_set() == meshset ) set_iters.push_back( *vit );
3991  return MB_SUCCESS;
3992 }
3993 
3995  type_memstorage* total_storage,
3996  type_memstorage* total_amortized_storage,
3997  type_memstorage* entity_storage,
3998  type_memstorage* amortized_entity_storage,
3999  type_memstorage* adjacency_storage,
4000  type_memstorage* amortized_adjacency_storage,
4001  const Tag* tag_array,
4002  unsigned num_tags,
4003  type_memstorage* tag_storage,
4004  type_memstorage* amortized_tag_storage )
4005 {
4006  // Figure out which values we need to calculate
4007  type_memstorage i_entity_storage, ia_entity_storage, i_adjacency_storage, ia_adjacency_storage, i_tag_storage,
4008  ia_tag_storage;
4009  type_memstorage *total_tag_storage = 0, *amortized_total_tag_storage = 0;
4010  if( !tag_array )
4011  {
4012  total_tag_storage = tag_storage;
4013  amortized_total_tag_storage = amortized_tag_storage;
4014  }
4015  if( total_storage || total_amortized_storage )
4016  {
4017  if( !entity_storage ) entity_storage = &i_entity_storage;
4018  if( !amortized_entity_storage ) amortized_entity_storage = &ia_entity_storage;
4019  if( !adjacency_storage ) adjacency_storage = &i_adjacency_storage;
4020  if( !amortized_adjacency_storage ) amortized_adjacency_storage = &ia_adjacency_storage;
4021  }
4022  else
4023  {
4024  if( entity_storage || amortized_entity_storage )
4025  {
4026  if( !amortized_entity_storage )
4027  amortized_entity_storage = &ia_entity_storage;
4028  else if( !entity_storage )
4029  entity_storage = &i_entity_storage;
4030  }
4031  if( adjacency_storage || amortized_adjacency_storage )
4032  {
4033  if( !amortized_adjacency_storage )
4034  amortized_adjacency_storage = &ia_adjacency_storage;
4035  else if( !adjacency_storage )
4036  adjacency_storage = &i_adjacency_storage;
4037  }
4038  }
4039  if( !total_tag_storage && total_storage ) total_tag_storage = &i_tag_storage;
4040  if( !amortized_total_tag_storage && total_amortized_storage ) amortized_total_tag_storage = &ia_tag_storage;
4041 
4042  // get entity storage
4043  if( amortized_entity_storage )
4044  {
4045  if( ents )
4046  sequenceManager->get_memory_use( *ents, *entity_storage, *amortized_entity_storage );
4047  else
4048  sequenceManager->get_memory_use( *entity_storage, *amortized_entity_storage );
4049  }
4050 
4051  // get adjacency storage
4052  if( amortized_adjacency_storage )
4053  {
4054  if( ents )
4055  aEntityFactory->get_memory_use( *ents, *adjacency_storage, *amortized_adjacency_storage );
4056  else
4057 #ifdef MOAB_HAVE_AHF
4058  ahfRep->get_memory_use( *adjacency_storage, *amortized_adjacency_storage );
4059 #else
4060  aEntityFactory->get_memory_use( *adjacency_storage, *amortized_adjacency_storage );
4061 #endif
4062  }
4063 
4064  // get storage for requested list of tags
4065  if( tag_array )
4066  {
4067  for( unsigned i = 0; i < num_tags; ++i )
4068  {
4069  if( !valid_tag_handle( tag_array[i] ) ) continue;
4070 
4071  unsigned long total = 0, per_ent = 0;
4072  tag_array[i]->get_memory_use( sequenceManager, total, per_ent );
4073 
4074  if( ents )
4075  {
4076  size_t count = 0, count2 = 0;
4077  tag_array[i]->num_tagged_entities( sequenceManager, count, MBMAXTYPE, ents );
4078  if( tag_storage ) tag_storage[i] = count * per_ent;
4079  if( amortized_tag_storage )
4080  {
4081  tag_array[i]->num_tagged_entities( sequenceManager, count2 );
4082  if( count2 )
4083  amortized_tag_storage[i] = static_cast< type_memstorage >( total * count * 1.0 / count2 );
4084  }
4085  }
4086  else
4087  {
4088  size_t count = 0;
4089  if( tag_storage )
4090  {
4091  tag_array[i]->num_tagged_entities( sequenceManager, count );
4092  tag_storage[i] = count * per_ent;
4093  }
4094  if( amortized_tag_storage ) amortized_tag_storage[i] = total;
4095  }
4096  }
4097  }
4098 
4099  // get storage for all tags
4100  if( total_tag_storage || amortized_total_tag_storage )
4101  {
4102  if( amortized_total_tag_storage ) *amortized_total_tag_storage = 0;
4103  if( total_tag_storage ) *total_tag_storage = 0;
4104 
4105  std::vector< Tag > tags;
4106  tag_get_tags( tags );
4107  for( std::list< TagInfo* >::const_iterator i = tagList.begin(); i != tagList.end(); ++i )
4108  {
4109  unsigned long total = 0, per_ent = 0;
4110  ( *i )->get_memory_use( sequenceManager, total, per_ent );
4111 
4112  if( ents )
4113  {
4114  size_t count = 0, count2 = 0;
4115  ( *i )->num_tagged_entities( sequenceManager, count, MBMAXTYPE, ents );
4116  if( total_tag_storage ) *total_tag_storage += count * per_ent;
4117  if( amortized_total_tag_storage )
4118  {
4119  ( *i )->num_tagged_entities( sequenceManager, count2 );
4120  if( count2 )
4121  *amortized_total_tag_storage += static_cast< type_memstorage >( total * count * 1.0 / count2 );
4122  }
4123  }
4124  else
4125  {
4126  size_t count = 0;
4127  if( total_tag_storage )
4128  {
4129  ( *i )->num_tagged_entities( sequenceManager, count );
4130  *total_tag_storage += count * per_ent;
4131  }
4132  if( amortized_total_tag_storage ) *amortized_total_tag_storage += total;
4133  }
4134  }
4135  }
4136 
4137  // calculate totals
4138  if( total_storage ) *total_storage = *entity_storage + *adjacency_storage + *total_tag_storage;
4139 
4140  if( total_amortized_storage )
4141  *total_amortized_storage =
4142  *amortized_entity_storage + *amortized_adjacency_storage + *amortized_total_tag_storage;
4143 }
4144 
4146  unsigned long num_ents,
4147  type_memstorage* total_storage,
4148  type_memstorage* total_amortized_storage,
4149  type_memstorage* entity_storage,
4150  type_memstorage* amortized_entity_storage,
4151  type_memstorage* adjacency_storage,
4152  type_memstorage* amortized_adjacency_storage,
4153  const Tag* tag_array,
4154  unsigned num_tags,
4155  type_memstorage* tag_storage,
4156  type_memstorage* amortized_tag_storage )
4157 {
4158  Range range;
4159 
4160  // If non-empty entity list, call range version of function
4161  if( ent_array )
4162  {
4163  if( num_ents > 20 )
4164  {
4165  std::vector< EntityHandle > list( num_ents );
4166  std::copy( ent_array, ent_array + num_ents, list.begin() );
4167  std::sort( list.begin(), list.end() );
4168  Range::iterator j = range.begin();
4169  for( std::vector< EntityHandle >::reverse_iterator i = list.rbegin(); i != list.rend(); ++i )
4170  j = range.insert( j, *i, *i );
4171  }
4172  else
4173  {
4174  std::copy( ent_array, ent_array + num_ents, range_inserter( range ) );
4175  }
4176  }
4177 
4178  estimated_memory_use_internal( ent_array ? &range : 0, total_storage, total_amortized_storage, entity_storage,
4179  amortized_entity_storage, adjacency_storage, amortized_adjacency_storage, tag_array,
4180  num_tags, tag_storage, amortized_tag_storage );
4181 }
4182 
4184  type_memstorage* total_storage,
4185  type_memstorage* total_amortized_storage,
4186  type_memstorage* entity_storage,
4187  type_memstorage* amortized_entity_storage,
4188  type_memstorage* adjacency_storage,
4189  type_memstorage* amortized_adjacency_storage,
4190  const Tag* tag_array,
4191  unsigned num_tags,
4192  type_memstorage* tag_storage,
4193  type_memstorage* amortized_tag_storage )
4194 {
4195  estimated_memory_use_internal( &ents, total_storage, total_amortized_storage, entity_storage,
4196  amortized_entity_storage, adjacency_storage, amortized_adjacency_storage, tag_array,
4197  num_tags, tag_storage, amortized_tag_storage );
4198 }
4199 
4201 {
4202  ErrorCode rval;
4204  const TypeSequenceManager& verts = sequence_manager()->entity_map( MBVERTEX );
4205  if( !verts.empty() )
4206  printf( " Vertex ID X Y Z Adjacencies \n"
4207  " ---------- -------- -------- -------- -----------...\n" );
4208  const EntityHandle* adj;
4209  int nadj;
4210  for( i = verts.begin(); i != verts.end(); ++i )
4211  {
4212  const VertexSequence* seq = static_cast< const VertexSequence* >( *i );
4213  printf( "(Sequence [%d,%d] in SequenceData [%d,%d])\n", (int)ID_FROM_HANDLE( seq->start_handle() ),
4214  (int)ID_FROM_HANDLE( seq->end_handle() ), (int)ID_FROM_HANDLE( seq->data()->start_handle() ),
4215  (int)ID_FROM_HANDLE( seq->data()->end_handle() ) );
4216 
4217  double c[3];
4218  for( EntityHandle h = seq->start_handle(); h <= seq->end_handle(); ++h )
4219  {
4220  rval = seq->get_coordinates( h, c );
4221  if( MB_SUCCESS == rval )
4222  printf( " %10d %8g %8g %8g", (int)ID_FROM_HANDLE( h ), c[0], c[1], c[2] );
4223  else
4224  printf( " %10d < ERROR %4d >", (int)ID_FROM_HANDLE( h ), (int)rval );
4225 
4226  rval = a_entity_factory()->get_adjacencies( h, adj, nadj );
4227  if( MB_SUCCESS != rval )
4228  {
4229  printf( " <ERROR %d>\n", (int)rval );
4230  continue;
4231  }
4232  EntityType pt = MBMAXTYPE;
4233  for( int j = 0; j < nadj; ++j )
4234  {
4235  if( TYPE_FROM_HANDLE( adj[j] ) != pt )
4236  {
4237  pt = TYPE_FROM_HANDLE( adj[j] );
4238  printf( " %s", pt >= MBMAXTYPE ? "INVALID TYPE" : CN::EntityTypeName( pt ) );
4239  }
4240  printf( " %d", (int)ID_FROM_HANDLE( adj[j] ) );
4241  }
4242  printf( "\n" );
4243  }
4244  }
4245 
4246  for( EntityType t = MBEDGE; t < MBENTITYSET; ++t )
4247  {
4248  const TypeSequenceManager& elems = sequence_manager()->entity_map( t );
4249  if( elems.empty() ) continue;
4250 
4251  int clen = 0;
4252  for( i = elems.begin(); i != elems.end(); ++i )
4253  {
4254  int n = static_cast< const ElementSequence* >( *i )->nodes_per_element();
4255  if( n > clen ) clen = n;
4256  }
4257 
4258  clen *= 5;
4259  if( clen < (int)strlen( "Connectivity" ) ) clen = strlen( "Connectivity" );
4260  std::vector< char > dashes( clen, '-' );
4261  dashes.push_back( '\0' );
4262  printf( " %7s ID %-*s Adjacencies\n", CN::EntityTypeName( t ), clen, "Connectivity" );
4263  printf( " ---------- %s -----------...\n", &dashes[0] );
4264 
4265  std::vector< EntityHandle > storage;
4266  const EntityHandle* conn;
4267  int nconn;
4268  for( i = elems.begin(); i != elems.end(); ++i )
4269  {
4270  const ElementSequence* seq = static_cast< const ElementSequence* >( *i );
4271  printf( "(Sequence [%d,%d] in SequenceData [%d,%d])\n", (int)ID_FROM_HANDLE( seq->start_handle() ),
4272  (int)ID_FROM_HANDLE( seq->end_handle() ), (int)ID_FROM_HANDLE( seq->data()->start_handle() ),
4273  (int)ID_FROM_HANDLE( seq->data()->end_handle() ) );
4274 
4275  for( EntityHandle h = seq->start_handle(); h <= seq->end_handle(); ++h )
4276  {
4277  printf( " %10d", (int)ID_FROM_HANDLE( h ) );
4278  rval = get_connectivity( h, conn, nconn, false, &storage );
4279  if( MB_SUCCESS != rval )
4280  printf( " <ERROR %2d>%*s", (int)rval, clen - 10, "" );
4281  else
4282  {
4283  for( int j = 0; j < nconn; ++j )
4284  printf( " %4d", (int)ID_FROM_HANDLE( conn[j] ) );
4285  printf( "%*s", clen - 5 * nconn, "" );
4286  }
4287 
4288  rval = a_entity_factory()->get_adjacencies( h, adj, nadj );
4289  if( MB_SUCCESS != rval )
4290  {
4291  printf( " <ERROR %d>\n", (int)rval );
4292  continue;
4293  }
4294  EntityType pt = MBMAXTYPE;
4295  for( int j = 0; j < nadj; ++j )
4296  {
4297  if( TYPE_FROM_HANDLE( adj[j] ) != pt )
4298  {
4299  pt = TYPE_FROM_HANDLE( adj[j] );
4300  printf( " %s", pt >= MBMAXTYPE ? "INVALID TYPE" : CN::EntityTypeName( pt ) );
4301  }
4302  printf( " %d", (int)ID_FROM_HANDLE( adj[j] ) );
4303  }
4304  printf( "\n" );
4305  }
4306  }
4307  }
4308 }
4309 
4311  const HomCoord& coord_max,
4312  EntityType entity_type,
4313  EntityID start_id_hint,
4314  EntityHandle& first_handle_out,
4315  EntitySequence*& sequence_out )
4316 {
4317  // NR: Previously, the structured element sequences were created via direct call to
4318  // the sequence manager instead of using the same from the ScdInterface which
4319  // creates the associated scd bounding box after element sequence creation.
4320 
4321  if( !scdInterface ) scdInterface = new ScdInterface( this );
4322  ScdBox* newBox = NULL;
4323  MB_CHK_SET_ERR( scdInterface->create_scd_sequence( coord_min, coord_max, entity_type,
4324  /*starting_id*/ (int)start_id_hint, newBox ),
4325  "can't create scd sequence" );
4326 
4327  if( MBVERTEX == entity_type )
4328  first_handle_out = newBox->get_vertex( coord_min );
4329  else
4330  first_handle_out = newBox->get_element( coord_min );
4331  return sequence_manager()->find( first_handle_out, sequence_out );
4332 }
4333 
4335  EntitySequence* elem_seq,
4336  const HomCoord& p1,
4337  const HomCoord& q1,
4338  const HomCoord& p2,
4339  const HomCoord& q2,
4340  const HomCoord& p3,
4341  const HomCoord& q3,
4342  bool bb_input,
4343  const HomCoord* bb_min,
4344  const HomCoord* bb_max )
4345 {
4346  return sequence_manager()->add_vsequence( vert_seq, elem_seq, p1, q1, p2, q2, p3, q3, bb_input, bb_min, bb_max );
4347 }
4348 
4349 } // namespace moab