MOAB: Mesh Oriented datABase  (version 5.4.0)
iMeshP_MOAB.cpp
Go to the documentation of this file.
00001 #include "moab/MOABConfig.h"
00002 #include "iMeshP_extensions.h"
00003 #include "iMesh_MOAB.hpp"
00004 #include "moab/Core.hpp"
00005 #include "moab/Range.hpp"
00006 #include "moab/CN.hpp"
00007 #include "moab/MeshTopoUtil.hpp"
00008 #include "moab/FileOptions.hpp"
00009 #include "moab/ParallelComm.hpp"
00010 #include "MBParallelConventions.h"
00011 #include "MBIter.hpp"
00012 
00013 #define IS_BUILDING_MB
00014 #include "Internals.hpp"
00015 #undef IS_BUILDING_MB
00016 
00017 #include <cassert>
00018 #include <sstream>
00019 
00020 #ifdef MOAB_HAVE_MPI
00021 #include "moab_mpi.h"
00022 #endif
00023 
00024 using namespace moab;
00025 
00026 /********************* Error Handling **************************/
00027 
00028 #define FIXME printf( "Warning: function has incomplete implementation: %s\n", __func__ )
00029 
00030 /******** Type-safe casting between MOAB and ITAPS types *********/
00031 
00032 #ifndef MOAB_TEMPLATE_FUNC_SPECIALIZATION
00033 // if no template specialization, disable some type checking
00034 template < typename T, typename S >
00035 inline T itaps_cast( S handle )
00036 {
00037     assert( sizeof( S ) >= sizeof( T ) );
00038     return reinterpret_cast< T >( handle );
00039 }
00040 #else
00041 
00042 // basic template method : only works to cast to equivalent types (no-op)
00043 template < typename T, typename S >
00044 inline T itaps_cast( S h )
00045 {
00046     return h;
00047 }
00048 // verify size and do reinterpret cast
00049 template < typename T >
00050 inline T itaps_cast_internal_( EntityHandle h )
00051 {
00052     assert( sizeof( T ) >= sizeof( EntityHandle ) );
00053     return reinterpret_cast< T >( h );
00054 }
00055 // verify size and do reinterpret cast
00056 template < typename T >
00057 inline EntityHandle* itaps_cast_ptr_( T* h )
00058 {
00059     assert( sizeof( T ) == sizeof( EntityHandle ) );
00060     return reinterpret_cast< EntityHandle* >( h );
00061 }
00062 // verify size and do reinterpret cast
00063 template < typename T >
00064 inline const EntityHandle* itaps_cast_const_ptr_( const T* h )
00065 {
00066     assert( sizeof( T ) == sizeof( EntityHandle ) );
00067     return reinterpret_cast< const EntityHandle* >( h );
00068 }
00069 // verify set-type handle before cast
00070 template < typename T >
00071 inline T itaps_set_cast_( EntityHandle h )
00072 {
00073     assert( TYPE_FROM_HANDLE( h ) == MBENTITYSET );
00074     return itaps_cast_internal_< T >( h );
00075 }
00076 
00077 // define conversion routines between itaps handle and EntityHandle types
00078 #define DECLARE_ALLOWED_ITAPS_CONVERSION( ITAPS_HANDLE_TYPE )                                       \
00079     template <>                                                                                     \
00080     inline ITAPS_HANDLE_TYPE itaps_cast< ITAPS_HANDLE_TYPE, EntityHandle >( EntityHandle h )        \
00081     {                                                                                               \
00082         return itaps_cast_internal_< ITAPS_HANDLE_TYPE >( h );                                      \
00083     }                                                                                               \
00084                                                                                                     \
00085     template <>                                                                                     \
00086     inline EntityHandle itaps_cast< EntityHandle, ITAPS_HANDLE_TYPE >( ITAPS_HANDLE_TYPE handle )   \
00087     {                                                                                               \
00088         return reinterpret_cast< EntityHandle >( handle );                                          \
00089     }                                                                                               \
00090                                                                                                     \
00091     template <>                                                                                     \
00092     inline EntityHandle* itaps_cast< EntityHandle*, ITAPS_HANDLE_TYPE* >( ITAPS_HANDLE_TYPE * ptr ) \
00093     {                                                                                               \
00094         return itaps_cast_ptr_( ptr );                                                              \
00095     }                                                                                               \
00096                                                                                                     \
00097     template <>                                                                                     \
00098     inline const EntityHandle* itaps_cast< const EntityHandle*, const ITAPS_HANDLE_TYPE* >(         \
00099         const ITAPS_HANDLE_TYPE* ptr )                                                              \
00100     {                                                                                               \
00101         return itaps_cast_const_ptr_( ptr );                                                        \
00102     }
00103 
00104 // define conversion routines between itaps handle and EntityHandle types
00105 // but limit to EntityHandle for MBENTITYSET type.
00106 #define DECLARE_ALLOWED_ITAPS_SET_CONVERSION( ITAPS_HANDLE_TYPE )                                   \
00107     template <>                                                                                     \
00108     inline ITAPS_HANDLE_TYPE itaps_cast< ITAPS_HANDLE_TYPE, EntityHandle >( EntityHandle h )        \
00109     {                                                                                               \
00110         return itaps_set_cast_< ITAPS_HANDLE_TYPE >( h );                                           \
00111     }                                                                                               \
00112                                                                                                     \
00113     template <>                                                                                     \
00114     inline EntityHandle itaps_cast< EntityHandle, ITAPS_HANDLE_TYPE >( ITAPS_HANDLE_TYPE handle )   \
00115     {                                                                                               \
00116         return reinterpret_cast< EntityHandle >( handle );                                          \
00117     }                                                                                               \
00118                                                                                                     \
00119     template <>                                                                                     \
00120     inline EntityHandle* itaps_cast< EntityHandle*, ITAPS_HANDLE_TYPE* >( ITAPS_HANDLE_TYPE * ptr ) \
00121     {                                                                                               \
00122         return itaps_cast_ptr_( ptr );                                                              \
00123     }                                                                                               \
00124                                                                                                     \
00125     template <>                                                                                     \
00126     inline const EntityHandle* itaps_cast< const EntityHandle*, const ITAPS_HANDLE_TYPE* >(         \
00127         const ITAPS_HANDLE_TYPE* ptr )                                                              \
00128     {                                                                                               \
00129         return itaps_cast_const_ptr_( ptr );                                                        \
00130     }
00131 
00132 DECLARE_ALLOWED_ITAPS_SET_CONVERSION( iMeshP_PartitionHandle )
00133 // DECLARE_ALLOWED_ITAPS_SET_CONVERSION( iMeshP_PartHandle )
00134 DECLARE_ALLOWED_ITAPS_SET_CONVERSION( iBase_EntitySetHandle )
00135 DECLARE_ALLOWED_ITAPS_CONVERSION( iBase_EntityHandle )
00136 
00137 template <>
00138 inline Tag itaps_cast< Tag, iBase_TagHandle >( iBase_TagHandle h )
00139 {
00140     return reinterpret_cast< Tag >( h );
00141 }
00142 template <>
00143 inline iBase_TagHandle itaps_cast< iBase_TagHandle, Tag >( Tag h )
00144 {
00145     return reinterpret_cast< iBase_TagHandle >( h );
00146 }
00147 
00148 #endif
00149 
00150 #define PCOMM ParallelComm::get_pcomm( MOABI, itaps_cast< EntityHandle >( partition_handle ) )
00151 
00152 /*** static function implemented in iMesh_MOAB.cpp ***/
00153 
00154 // Need a different function name for Tag because (currently)
00155 // both Tag and iBase_EntityHandle are void**.
00156 iBase_TagHandle itaps_tag_cast( Tag t )
00157 {
00158     assert( sizeof( iBase_TagHandle ) >= sizeof( Tag ) );
00159     return reinterpret_cast< iBase_TagHandle >( t );
00160 }
00161 
00162 /********************* ITAPS arrays **************************/
00163 
00164 // Handle returning Range in ITAPS array (do ALLOCATE_ARRAY and copy).
00165 #define RANGE_TO_ITAPS_ARRAY( RANGE, NAME )                                                        \
00166     do                                                                                             \
00167     {                                                                                              \
00168         ALLOC_CHECK_ARRAY_NOFAIL( NAME, ( RANGE ).size() );                                        \
00169         std::copy( ( RANGE ).begin(), ( RANGE ).end(), itaps_cast< EntityHandle* >( *( NAME ) ) ); \
00170     } while( false )
00171 
00172 static inline ErrorCode get_entities( Interface* iface, EntityHandle set, int type, int topology, Range& entities )
00173 {
00174     if( topology != iMesh_ALL_TOPOLOGIES )
00175         return iface->get_entities_by_type( set, mb_topology_table[topology], entities );
00176     else if( type != iBase_ALL_TYPES )
00177         return iface->get_entities_by_dimension( set, type, entities );
00178     else
00179         return iface->get_entities_by_handle( set, entities );
00180 }
00181 
00182 /*
00183 static inline ErrorCode remove_not_owned( ParallelComm* pcomm, Range& ents )
00184 {
00185   ErrorCode rval;
00186 
00187   std::vector<unsigned char> pstatus(ents.size());
00188   rval = pcomm->get_moab()->tag_get_data(pcomm->pstatus_tag(), ents, &pstatus[0]);
00189   if (MB_SUCCESS != rval)
00190     return rval;
00191 
00192   Range::iterator i = ents.begin();
00193   std::vector<unsigned char>::const_iterator j;
00194   for (j = pstatus.begin(); j != pstatus.end(); ++j) {
00195     if (*j & PSTATUS_NOT_OWNED)
00196       i = ents.erase( i );
00197     else
00198       ++i;
00199   }
00200 
00201   return MB_SUCCESS;
00202 }
00203 */
00204 
00205 static inline ErrorCode count_owned( ParallelComm* pcomm, const Range& ents, int& n )
00206 {
00207     ErrorCode rval;
00208     n = 0;
00209 
00210     std::vector< unsigned char > pstatus( ents.size() );
00211     rval = pcomm->get_moab()->tag_get_data( pcomm->pstatus_tag(), ents, &pstatus[0] );
00212     if( MB_SUCCESS != rval ) return rval;
00213 
00214     std::vector< unsigned char >::const_iterator j;
00215     for( j = pstatus.begin(); j != pstatus.end(); ++j )
00216         if( !( *j & PSTATUS_NOT_OWNED ) ) ++n;
00217 
00218     return MB_SUCCESS;
00219 }
00220 
00221 static void set_intersection_query( iMesh_Instance instance,
00222                                     iMeshP_PartHandle set1,
00223                                     iBase_EntitySetHandle set2,
00224                                     int type,
00225                                     int topo,
00226                                     Range& result,
00227                                     int* err )
00228 {
00229     ErrorCode rval;
00230 
00231     if( !set1 )
00232     {
00233         rval = get_entities( MOABI, itaps_cast< EntityHandle >( set2 ), type, topo, result );CHKERR( rval, "Invalid Part handle" );
00234     }
00235     else if( !set2 )
00236     {
00237         rval = get_entities( MOABI, itaps_cast< EntityHandle >( set1 ), type, topo, result );CHKERR( rval, "Invalid set handle" );
00238     }
00239     else
00240     {
00241         Range r1, r2;
00242         rval = get_entities( MOABI, itaps_cast< EntityHandle >( set1 ), type, topo, r1 );CHKERR( rval, "Invalid Part handle" );
00243         rval = get_entities( MOABI, itaps_cast< EntityHandle >( set2 ), type, topo, r2 );CHKERR( rval, "Invalid set handle" );
00244         result.merge( intersect( r1, r2 ) );
00245     }
00246 
00247     RETURN( iBase_SUCCESS );
00248 }
00249 
00250 /********************* Iterators **************************/
00251 
00252 static ErrorCode get_boundary_entities( ParallelComm* pcomm,
00253                                         EntityHandle part_handle,
00254                                         int entity_type,
00255                                         int entity_topology,
00256                                         int adj_part_id,
00257                                         Range& entities_out )
00258 {
00259     int* adj_part_id_ptr = ( adj_part_id == iMeshP_ALL_PARTS ) ? 0 : &adj_part_id;
00260 
00261     Range iface_sets;
00262     ErrorCode rval = pcomm->get_interface_sets( part_handle, iface_sets, adj_part_id_ptr );
00263     if( MB_SUCCESS != rval ) return rval;
00264 
00265     for( Range::iterator i = iface_sets.begin(); i != iface_sets.end(); ++i )
00266     {
00267         rval = get_entities( pcomm->get_moab(), *i, entity_type, entity_topology, entities_out );
00268         if( MB_SUCCESS != rval ) return rval;
00269     }
00270 
00271     return MB_SUCCESS;
00272 }
00273 
00274 class PartBoundaryIter : public MBRangeIter
00275 {
00276   private:
00277     ParallelComm* pComm;
00278     int adjPart;
00279 
00280   public:
00281     inline PartBoundaryIter( ParallelComm* pcomm,
00282                              EntityHandle part_handle,
00283                              iBase_EntityType entity_type,
00284                              iMesh_EntityTopology entity_topology,
00285                              int adj_part_id,
00286                              int array_sz )
00287         : MBRangeIter( entity_type, entity_topology, part_handle, array_sz ), pComm( pcomm ), adjPart( adj_part_id )
00288     {
00289     }
00290 
00291     virtual ErrorCode reset( Interface* )
00292     {
00293         iterData.clear();
00294         ErrorCode result = get_boundary_entities( pComm, entSet, entType, entTopo, adjPart, iterData );
00295         iterPos          = iterData.begin();
00296         return result;
00297     }
00298 };
00299 
00300 template < class Container >
00301 class SetIntersectIter : public MBIter< Container >
00302 {
00303   private:
00304     EntityHandle otherSet;
00305 
00306   public:
00307     SetIntersectIter( iBase_EntityType type,
00308                       iMesh_EntityTopology topology,
00309                       EntityHandle set,
00310                       EntityHandle other_set,
00311                       int array_sz )
00312         : MBIter< Container >( type, topology, set, array_sz ), otherSet( other_set )
00313     {
00314     }
00315     virtual ~SetIntersectIter() {}
00316 
00317     inline ErrorCode intersect_with_set( Interface* mb, Range& range )
00318     {
00319         Range tmp;
00320         ErrorCode result;
00321         result = mb->get_entities_by_handle( otherSet, tmp );
00322         range  = intersect( range, tmp );
00323         return result;
00324     }
00325 
00326     inline ErrorCode intersect_with_set( Interface* mb, std::vector< EntityHandle >& list )
00327     {
00328         size_t w = 0;
00329         for( size_t r = 0; r < list.size(); ++r )
00330         {
00331             if( mb->contains_entities( otherSet, &list[r], 1 ) ) list[w++] = list[r];
00332         }
00333         list.resize( w );
00334         return MB_SUCCESS;
00335     }
00336 
00337     virtual ErrorCode reset( Interface* mb )
00338     {
00339         ErrorCode result = MBIter< Container >::reset( mb );
00340         if( MB_SUCCESS != result ) return result;
00341 
00342         result                       = intersect_with_set( mb, MBIter< Container >::iterData );
00343         MBIter< Container >::iterPos = MBIter< Container >::iterData.begin();
00344         return result;
00345     }
00346 };
00347 
00348 /********************* iMeshP API **************************/
00349 
00350 #ifdef __cplusplus
00351 extern "C" {
00352 #endif
00353 
00354 void iMeshP_createPartitionAll( iMesh_Instance instance,
00355                                 /*in*/ MPI_Comm communicator,
00356                                 /*out*/ iMeshP_PartitionHandle* partition_handle,
00357                                 int* err )
00358 {
00359     *partition_handle = 0;
00360 
00361     Tag prtn_tag;
00362     ErrorCode rval = MOABI->tag_get_handle( PARALLEL_PARTITIONING_TAG_NAME, 1, MB_TYPE_INTEGER, prtn_tag,
00363                                             MB_TAG_SPARSE | MB_TAG_CREAT );CHKERR( rval, "tag creation failed" );
00364 
00365     EntityHandle handle;
00366     rval = MOABI->create_meshset( MESHSET_SET, handle );CHKERR( rval, "set creation failed" );
00367     ParallelComm* pcomm = ParallelComm::get_pcomm( MOABI, handle, &communicator );
00368     if( !pcomm )
00369     {
00370         MOABI->delete_entities( &handle, 1 );
00371         RETURN( iBase_FAILURE );
00372     }
00373 
00374     // set the value of pcomm id, to the partitioning tag, although this is not used
00375     // we just need the tag to be set
00376     int pid = pcomm->get_id();
00377     rval    = MOABI->tag_set_data( prtn_tag, &handle, 1, &pid );CHKERR( rval, "tag creation failed" );
00378 
00379     *partition_handle = itaps_cast< iMeshP_PartitionHandle >( handle );
00380     RETURN( iBase_SUCCESS );
00381 }
00382 
00383 void iMeshP_destroyPartitionAll( iMesh_Instance instance, iMeshP_PartitionHandle partition_handle, int* err )
00384 {
00385     ParallelComm* pcomm = PCOMM;
00386     if( pcomm ) delete pcomm;
00387     EntityHandle handle = itaps_cast< EntityHandle >( partition_handle );
00388     ErrorCode rval      = MOABI->delete_entities( &handle, 1 );CHKERR( rval, "entity deletion failed" );
00389     RETURN( iBase_SUCCESS );
00390 }
00391 
00392 void iMeshP_getPartIdFromPartHandle( iMesh_Instance instance,
00393                                      const iMeshP_PartitionHandle partition_handle,
00394                                      const iMeshP_PartHandle part_handle,
00395                                      iMeshP_Part* part_id,
00396                                      int* err )
00397 {
00398     int junk1 = 1, junk2;
00399     iMeshP_getPartIdsFromPartHandlesArr( instance, partition_handle, &part_handle, 1, &part_id, &junk1, &junk2, err );
00400 }
00401 
00402 void iMeshP_getPartHandleFromPartId( iMesh_Instance instance,
00403                                      const iMeshP_PartitionHandle partition_handle,
00404                                      iMeshP_Part part_id,
00405                                      iMeshP_PartHandle* part_handle,
00406                                      int* err )
00407 {
00408     int junk1 = 1, junk2;
00409     iMeshP_getPartHandlesFromPartsIdsArr( instance, partition_handle, &part_id, 1, &part_handle, &junk1, &junk2, err );
00410 }
00411 
00412 void iMeshP_getPartIdsFromPartHandlesArr( iMesh_Instance instance,
00413                                           const iMeshP_PartitionHandle partition_handle,
00414                                           const iMeshP_PartHandle* part_handles,
00415                                           const int part_handles_size,
00416                                           iMeshP_Part** part_ids,
00417                                           int* part_ids_allocated,
00418                                           int* part_ids_size,
00419                                           int* err )
00420 {
00421     ErrorCode rval;
00422     ParallelComm* pcomm = PCOMM;
00423     ALLOC_CHECK_ARRAY( part_ids, part_handles_size );
00424     for( int i = 0; i < part_handles_size; ++i )
00425     {
00426         int id;
00427         rval             = pcomm->get_part_id( itaps_cast< EntityHandle >( part_handles[i] ), id );
00428         ( *part_ids )[i] = id;CHKERR( rval, "error getting part id" );
00429     }
00430     KEEP_ARRAY( part_ids );
00431     RETURN( iBase_SUCCESS );
00432 }
00433 
00434 void iMeshP_getPartHandlesFromPartsIdsArr( iMesh_Instance instance,
00435                                            const iMeshP_PartitionHandle partition_handle,
00436                                            const iMeshP_Part* part_ids,
00437                                            const int part_ids_size,
00438                                            iMeshP_PartHandle** part_handles,
00439                                            int* part_handles_allocated,
00440                                            int* part_handles_size,
00441                                            int* err )
00442 {
00443     ErrorCode rval;
00444     ParallelComm* pcomm = PCOMM;
00445     ALLOC_CHECK_ARRAY( part_handles, part_ids_size );
00446     for( int i = 0; i < part_ids_size; ++i )
00447     {
00448         EntityHandle handle;
00449         rval = pcomm->get_part_handle( part_ids[i], handle );CHKERR( rval, "error getting part handle" );
00450         ( *part_handles )[i] = itaps_cast< iMeshP_PartHandle >( handle );
00451     }
00452     KEEP_ARRAY( part_handles );
00453     RETURN( iBase_SUCCESS );
00454 }
00455 
00456 void iMeshP_getPartitionComm( iMesh_Instance instance,
00457                               iMeshP_PartitionHandle partition_handle,
00458                               MPI_Comm* communicator_out,
00459                               int* err )
00460 {
00461     ParallelComm* pcomm = PCOMM;
00462     if( !pcomm ) RETURN( iBase_FAILURE );
00463     *communicator_out = pcomm->proc_config().proc_comm();
00464     RETURN( iBase_SUCCESS );
00465 }
00466 
00467 void iMeshP_syncPartitionAll( iMesh_Instance instance, iMeshP_PartitionHandle partition_handle, int* err )
00468 {
00469     ParallelComm* pcomm = PCOMM;
00470     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00471     ErrorCode rval = pcomm->collective_sync_partition();CHKERR( rval, "collective sync failed" );
00472     RETURN( iBase_SUCCESS );
00473 }
00474 
00475 void iMeshP_getNumPartitions( iMesh_Instance instance, int* num_partitions_out, int* err )
00476 {
00477     std::vector< ParallelComm* > pcomms;
00478     ErrorCode rval = ParallelComm::get_all_pcomm( MOABI, pcomms );CHKERR( rval, "Internal error retreiving PComms" );
00479 
00480     std::vector< ParallelComm* >::iterator i;
00481     *num_partitions_out = 0;
00482     for( i = pcomms.begin(); i != pcomms.end(); ++i )
00483         if( ( *i )->get_partitioning() ) ( *num_partitions_out )++;
00484 
00485     RETURN( iBase_SUCCESS );
00486 }
00487 
00488 void iMeshP_getPartitions( iMesh_Instance instance,
00489                            iMeshP_PartitionHandle** partition_handle,
00490                            int* partition_handle_allocated,
00491                            int* partition_handle_size,
00492                            int* err )
00493 {
00494     std::vector< ParallelComm* > pcomms;
00495     ErrorCode rval = ParallelComm::get_all_pcomm( MOABI, pcomms );CHKERR( rval, "Internal error retreiving PComms" );
00496 
00497     std::vector< ParallelComm* >::iterator i;
00498     int count = 0;
00499     for( i = pcomms.begin(); i != pcomms.end(); ++i )
00500         if( ( *i )->get_partitioning() ) ++count;
00501     ALLOC_CHECK_ARRAY_NOFAIL( partition_handle, count );
00502 
00503     *partition_handle_size = 0;
00504     for( i = pcomms.begin(); i != pcomms.end(); ++i )
00505         if( ( *i )->get_partitioning() )
00506             ( *partition_handle )[( *partition_handle_size )++] =
00507                 itaps_cast< iMeshP_PartitionHandle >( ( *i )->get_partitioning() );
00508 
00509     RETURN( iBase_SUCCESS );
00510 }
00511 
00512 void iMeshP_getNumGlobalParts( iMesh_Instance instance,
00513                                const iMeshP_PartitionHandle partition_handle,
00514                                int* num_global_part,
00515                                int* err )
00516 {
00517     ParallelComm* pcomm = PCOMM;
00518     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00519 
00520     ErrorCode rval = pcomm->get_global_part_count( *num_global_part );CHKERR( rval, "PComm::get_global_part_count failed" );
00521     RETURN( iBase_SUCCESS );
00522 }
00523 
00524 void iMeshP_getNumLocalParts( iMesh_Instance instance,
00525                               const iMeshP_PartitionHandle partition_handle,
00526                               int* num_local_part,
00527                               int* err )
00528 {
00529     ParallelComm* pcomm = PCOMM;
00530     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00531 
00532     *num_local_part = pcomm->partition_sets().size();
00533     RETURN( iBase_SUCCESS );
00534 }
00535 
00536 void iMeshP_getLocalParts( iMesh_Instance instance,
00537                            const iMeshP_PartitionHandle partition_handle,
00538                            iMeshP_PartHandle** part_handles,
00539                            int* part_handles_allocated,
00540                            int* part_handles_size,
00541                            int* err )
00542 {
00543     ParallelComm* pcomm = PCOMM;
00544     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00545 
00546     RANGE_TO_ITAPS_ARRAY( pcomm->partition_sets(), part_handles );
00547     RETURN( iBase_SUCCESS );
00548 }
00549 
00550 void iMeshP_getRankOfPart( iMesh_Instance instance,
00551                            const iMeshP_PartitionHandle partition_handle,
00552                            const iMeshP_Part part_id,
00553                            int* rank,
00554                            int* err )
00555 {
00556     int junk1 = 1, junk2 = 1;
00557     iMeshP_getRankOfPartArr( instance, partition_handle, &part_id, 1, &rank, &junk1, &junk2, err );
00558 }
00559 
00560 void iMeshP_getRankOfPartArr( iMesh_Instance instance,
00561                               const iMeshP_PartitionHandle partition_handle,
00562                               const iMeshP_Part* part_ids,
00563                               const int part_ids_size,
00564                               int** rank,
00565                               int* rank_allocated,
00566                               int* rank_size,
00567                               int* err )
00568 {
00569     ParallelComm* pcomm = PCOMM;
00570     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00571 
00572     ALLOC_CHECK_ARRAY( rank, part_ids_size );
00573     ErrorCode rval = MB_SUCCESS;
00574     for( int i = 0; i < part_ids_size; ++i )
00575     {
00576         rval = pcomm->get_part_owner( part_ids[i], ( *rank )[i] );CHKERR( rval, "PComm::get_part_owner failed" );
00577     }
00578     KEEP_ARRAY( rank );
00579     RETURN( iBase_SUCCESS );
00580 }
00581 
00582 void iMeshP_getNumOfTypeAll( iMesh_Instance instance,
00583                              const iMeshP_PartitionHandle partition_handle,
00584                              const iBase_EntitySetHandle entity_set_handle,
00585                              const int entity_type,
00586                              int* num_type,
00587                              int* err )
00588 {
00589     ParallelComm* pcomm = PCOMM;
00590     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00591 
00592     Range entities;
00593     ErrorCode rval = get_entities( MOABI, itaps_cast< EntityHandle >( entity_set_handle ), entity_type,
00594                                    iMesh_ALL_TOPOLOGIES, entities );
00595     int count      = 0;
00596     if( MB_SUCCESS == rval ) rval = count_owned( pcomm, entities, count );
00597 
00598     int vals[2] = { count, rval }, sums[2];
00599     int ierr    = MPI_Allreduce( vals, sums, 2, MPI_INT, MPI_SUM, pcomm->proc_config().proc_comm() );
00600     assert( iBase_SUCCESS == 0 );
00601     if( ierr || sums[1] ) RETURN( iBase_FAILURE );
00602 
00603     *num_type = sums[0];
00604     RETURN( iBase_SUCCESS );
00605 }
00606 
00607 void iMeshP_getNumOfTopoAll( iMesh_Instance instance,
00608                              const iMeshP_PartitionHandle partition_handle,
00609                              const iBase_EntitySetHandle entity_set_handle,
00610                              const int entity_topology,
00611                              int* num_topo,
00612                              int* err )
00613 {
00614     ParallelComm* pcomm = PCOMM;
00615     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00616 
00617     Range entities;
00618     ErrorCode rval = get_entities( MOABI, itaps_cast< EntityHandle >( entity_set_handle ), iBase_ALL_TYPES,
00619                                    entity_topology, entities );
00620     int count      = 0;
00621     if( MB_SUCCESS == rval ) rval = count_owned( pcomm, entities, count );
00622 
00623     int vals[2] = { count, rval }, sums[2];
00624     int ierr    = MPI_Allreduce( vals, sums, 2, MPI_INT, MPI_SUM, pcomm->proc_config().proc_comm() );
00625     assert( iBase_SUCCESS == 0 );
00626     if( ierr || sums[1] ) RETURN( iBase_FAILURE );
00627 
00628     *num_topo = sums[0];
00629     RETURN( iBase_SUCCESS );
00630 }
00631 
00632 void iMeshP_createPart( iMesh_Instance instance,
00633                         iMeshP_PartitionHandle partition_handle,
00634                         iMeshP_PartHandle* part_handle,
00635                         int* err )
00636 {
00637     ParallelComm* pcomm = PCOMM;
00638     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00639 
00640     EntityHandle h;
00641     ErrorCode rval = pcomm->create_part( h );CHKERR( rval, "Part creation failed" );
00642     *part_handle = itaps_cast< iMeshP_PartHandle >( h );
00643     RETURN( iBase_SUCCESS );
00644 }
00645 
00646 void iMeshP_destroyPart( iMesh_Instance instance,
00647                          iMeshP_PartitionHandle partition_handle,
00648                          iMeshP_PartHandle part_handle,
00649                          int* err )
00650 {
00651     ParallelComm* pcomm = PCOMM;
00652     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00653 
00654     ErrorCode rval = pcomm->destroy_part( itaps_cast< EntityHandle >( part_handle ) );CHKERR( rval, "Part destruction failed" );
00655     RETURN( iBase_SUCCESS );
00656 }
00657 
00658 void iMeshP_getNumPartNbors( iMesh_Instance instance,
00659                              iMeshP_PartitionHandle partition_handle,
00660                              iMeshP_PartHandle part_handle,
00661                              int entity_type,
00662                              int* num_part_nbors,
00663                              int* err )
00664 {
00665     int junk1 = 1, junk2 = 1;
00666     iMeshP_getNumPartNborsArr( instance, partition_handle, &part_handle, 1, entity_type, &num_part_nbors, &junk1,
00667                                &junk2, err );
00668 }
00669 
00670 void iMeshP_getNumPartNborsArr( iMesh_Instance instance,
00671                                 const iMeshP_PartitionHandle partition_handle,
00672                                 const iMeshP_PartHandle* part_handles,
00673                                 const int part_handles_size,
00674                                 int /*entity_type*/,
00675                                 int** num_part_nbors,
00676                                 int* num_part_nbors_allocated,
00677                                 int* num_part_nbors_size,
00678                                 int* err )
00679 {
00680     ParallelComm* pcomm = PCOMM;
00681     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00682 
00683     ALLOC_CHECK_ARRAY( num_part_nbors, part_handles_size );
00684 
00685     int n, neighbors[MAX_SHARING_PROCS];
00686     ErrorCode rval;
00687     for( int i = 0; i < part_handles_size; ++i )
00688     {
00689         EntityHandle h = itaps_cast< EntityHandle >( part_handles[i] );
00690         rval           = pcomm->get_part_neighbor_ids( h, neighbors, n );CHKERR( rval, "error getting neighbor ids" );
00691         ( *num_part_nbors )[i] = n;
00692     }
00693 
00694     KEEP_ARRAY( num_part_nbors );
00695     RETURN( iBase_SUCCESS );
00696 }
00697 
00698 void iMeshP_getPartNbors( iMesh_Instance instance,
00699                           const iMeshP_PartitionHandle partition_handle,
00700                           const iMeshP_PartHandle part_handle,
00701                           int entity_type,
00702                           int* num_part_nbors,
00703                           iMeshP_Part** nbor_part_ids,
00704                           int* nbor_part_ids_allocated,
00705                           int* nbor_part_ids_size,
00706                           int* err )
00707 {
00708     int junk1 = 1, junk2 = 1;
00709     iMeshP_getPartNborsArr( instance, partition_handle, &part_handle, 1, entity_type, &num_part_nbors, &junk1, &junk2,
00710                             nbor_part_ids, nbor_part_ids_allocated, nbor_part_ids_size, err );
00711 }
00712 
00713 void iMeshP_getPartNborsArr( iMesh_Instance instance,
00714                              const iMeshP_PartitionHandle partition_handle,
00715                              const iMeshP_PartHandle* part_handles,
00716                              const int part_handles_size,
00717                              int /*entity_type*/,
00718                              int** num_part_nbors,
00719                              int* num_part_nbors_allocated,
00720                              int* num_part_nbors_size,
00721                              iMeshP_Part** nbor_part_ids,
00722                              int* nbor_part_ids_allocated,
00723                              int* nbor_part_ids_size,
00724                              int* err )
00725 {
00726     ParallelComm* pcomm = PCOMM;
00727     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
00728 
00729     ALLOC_CHECK_ARRAY( num_part_nbors, part_handles_size );
00730 
00731     std::vector< int > all_neighbors;
00732     int n, pnbor[MAX_SHARING_PROCS];
00733     ErrorCode rval;
00734     for( int i = 0; i < part_handles_size; ++i )
00735     {
00736         EntityHandle h = itaps_cast< EntityHandle >( part_handles[i] );
00737         rval           = pcomm->get_part_neighbor_ids( h, pnbor, n );CHKERR( rval, "error getting neighbor ids" );
00738         ( *num_part_nbors )[i] = n;
00739         std::copy( pnbor, pnbor + n, std::back_inserter( all_neighbors ) );
00740     }
00741 
00742     ALLOC_CHECK_ARRAY_NOFAIL( nbor_part_ids, all_neighbors.size() );
00743     memcpy( *nbor_part_ids, &all_neighbors[0], sizeof( int ) * all_neighbors.size() );
00744 
00745     KEEP_ARRAY( num_part_nbors );
00746     RETURN( iBase_SUCCESS );
00747 }
00748 
00749 void iMeshP_getNumPartBdryEnts( iMesh_Instance instance,
00750                                 const iMeshP_PartitionHandle partition_handle,
00751                                 const iMeshP_PartHandle part_handle,
00752                                 const int entity_type,
00753                                 const int entity_topology,
00754                                 const iMeshP_Part target_part_id,
00755                                 int* num_entities,
00756                                 int* err )
00757 {
00758     Range entities;
00759     ErrorCode rval = get_boundary_entities( PCOMM, itaps_cast< EntityHandle >( part_handle ), entity_type,
00760                                             entity_topology, target_part_id, entities );CHKERR( rval, "failed to get boundary entities" );
00761     *num_entities = entities.size();
00762     RETURN( iBase_SUCCESS );
00763 }
00764 
00765 void iMeshP_getPartBdryEnts( iMesh_Instance instance,
00766                              const iMeshP_PartitionHandle partition_handle,
00767                              const iMeshP_PartHandle part_handle,
00768                              const int entity_type,
00769                              const int entity_topology,
00770                              const iMeshP_Part target_part_id,
00771                              iBase_EntityHandle** entity_handles,
00772                              int* entity_handles_allocated,
00773                              int* entity_handles_size,
00774                              int* err )
00775 {
00776     Range entities;
00777     ErrorCode rval = get_boundary_entities( PCOMM, itaps_cast< EntityHandle >( part_handle ), entity_type,
00778                                             entity_topology, target_part_id, entities );CHKERR( rval, "failed to get boundary entities" );
00779     RANGE_TO_ITAPS_ARRAY( entities, entity_handles );
00780     RETURN( iBase_SUCCESS );
00781 }
00782 
00783 void iMeshP_initPartBdryEntIter( iMesh_Instance instance,
00784                                  const iMeshP_PartitionHandle partition_handle,
00785                                  const iMeshP_PartHandle part_handle,
00786                                  const int entity_type,
00787                                  const int entity_topology,
00788                                  const iMeshP_Part nbor_part_id,
00789                                  iBase_EntityIterator* entity_iterator,
00790                                  int* err )
00791 {
00792     iMeshP_initPartBdryEntArrIter( instance, partition_handle, part_handle, entity_type, entity_topology, 1,
00793                                    nbor_part_id, reinterpret_cast< iBase_EntityArrIterator* >( entity_iterator ), err );
00794 }
00795 
00796 void iMeshP_initPartBdryEntArrIter( iMesh_Instance instance,
00797                                     const iMeshP_PartitionHandle partition_handle,
00798                                     const iMeshP_PartHandle part_handle,
00799                                     const int entity_type,
00800                                     const int entity_topology,
00801                                     const int array_size,
00802                                     const iMeshP_Part nbor_part_id,
00803                                     iBase_EntityArrIterator* entity_iterator,
00804                                     int* err )
00805 {
00806     *entity_iterator =
00807         new PartBoundaryIter( PCOMM, itaps_cast< EntityHandle >( part_handle ), (iBase_EntityType)entity_type,
00808                               (iMesh_EntityTopology)entity_topology, nbor_part_id, array_size );
00809     ErrorCode result = ( *entity_iterator )->reset( MOABI );
00810     if( MB_SUCCESS != result ) delete *entity_iterator;CHKERR( result, "iMesh_initEntArrIter: ERROR getting entities of proper type or topology." );
00811     RETURN( iBase_SUCCESS );
00812 }
00813 
00814 void iMeshP_getNumOfType( iMesh_Instance instance,
00815                           const iMeshP_PartitionHandle,
00816                           const iMeshP_PartHandle part_handle,
00817                           const iBase_EntitySetHandle entity_set_handle,
00818                           const int entity_type,
00819                           int* num_type,
00820                           int* err )
00821 {
00822     Range r;
00823     set_intersection_query( instance, part_handle, entity_set_handle, entity_type, iMesh_ALL_TOPOLOGIES, r, err );
00824     *num_type = r.size();
00825 }
00826 
00827 void iMeshP_getNumOfTopo( iMesh_Instance instance,
00828                           const iMeshP_PartitionHandle /*partition_handle*/,
00829                           const iMeshP_PartHandle part_handle,
00830                           const iBase_EntitySetHandle entity_set_handle,
00831                           const int entity_topology,
00832                           int* num_topo,
00833                           int* err )
00834 {
00835     Range r;
00836     set_intersection_query( instance, part_handle, entity_set_handle, iBase_ALL_TYPES, entity_topology, r, err );
00837     *num_topo = r.size();
00838 }
00839 
00840 void iMeshP_getAdjEntIndices( iMesh_Instance instance,
00841                               iMeshP_PartitionHandle partition,
00842                               iMeshP_PartHandle part,
00843                               iBase_EntitySetHandle entity_set_handle,
00844                               int entity_type_requestor,
00845                               int entity_topology_requestor,
00846                               int entity_type_requested,
00847                               iBase_EntityHandle** entity_handles,
00848                               int* entity_handles_allocated,
00849                               int* entity_handles_size,
00850                               iBase_EntityHandle** adj_entity_handles,
00851                               int* adj_entity_handles_allocated,
00852                               int* adj_entity_handles_size,
00853                               int** adj_entity_indices,
00854                               int* adj_entity_indices_allocated,
00855                               int* adj_entity_indices_size,
00856                               int** offset,
00857                               int* offset_allocated,
00858                               int* offset_size,
00859                               int* err )
00860 {
00861     const int allocated_entity_handles = ( *entity_handles_allocated == 0 );
00862     const int allocated_indices        = ( *adj_entity_indices_allocated == 0 );
00863     const int allocated_offset         = ( *offset_allocated == 0 );
00864 
00865     // get source entities
00866     iMeshP_getEntities( instance, partition, part, entity_set_handle, entity_type_requestor, entity_topology_requestor,
00867                         entity_handles, entity_handles_allocated, entity_handles_size, err );
00868     if( iBase_SUCCESS != *err ) return;
00869 
00870     // get adjacencies
00871     iBase_EntityHandle* all_adj_handles = 0;
00872     int size = 0, alloc = 0;
00873     iMesh_getEntArrAdj( instance, *entity_handles, *entity_handles_size, entity_type_requested, &all_adj_handles,
00874                         &alloc, &size, offset, offset_allocated, offset_size, err );
00875     if( *err != iBase_SUCCESS )
00876     {
00877         if( allocated_entity_handles )
00878         {
00879             free( *entity_handles );
00880             *entity_handles           = 0;
00881             *entity_handles_allocated = 0;
00882         }
00883         return;
00884     }
00885 
00886     // allocate or check size of adj_entity_indices
00887     *adj_entity_indices_size = size;
00888     if( allocated_indices )
00889     {
00890         *adj_entity_indices = (int*)malloc( sizeof( iBase_EntityHandle ) * size );
00891         if( !*adj_entity_indices )
00892             *err = iBase_MEMORY_ALLOCATION_FAILED;
00893         else
00894             *adj_entity_indices_allocated = size;
00895     }
00896     else if( *adj_entity_indices_allocated < size )
00897     {
00898         *err = iBase_BAD_ARRAY_DIMENSION;
00899     }
00900     if( iBase_SUCCESS != *err )
00901     {
00902         free( all_adj_handles );
00903         if( allocated_entity_handles )
00904         {
00905             free( *entity_handles );
00906             *entity_handles           = 0;
00907             *entity_handles_allocated = 0;
00908         }
00909         if( allocated_offset )
00910         {
00911             free( *offset );
00912             *offset           = 0;
00913             *offset_allocated = 0;
00914         }
00915         return;
00916     }
00917 
00918     // Now create an array of unique sorted handles from all_adj_handles.
00919     // We need to create a copy because we still need all_adj_handles.  We
00920     // will eventually need to copy the resulting unique list into
00921     // adj_entity_handles, so if adj_entity_handles is already allocated and
00922     // of sufficient size, use it rather than allocating another temporary.
00923     iBase_EntityHandle* unique_adj = 0;
00924     if( *adj_entity_handles_allocated >= size )
00925     {
00926         unique_adj = *adj_entity_handles;
00927     }
00928     else
00929     {
00930         unique_adj = (iBase_EntityHandle*)malloc( sizeof( iBase_EntityHandle ) * size );
00931     }
00932     std::copy( all_adj_handles, all_adj_handles + size, unique_adj );
00933     std::sort( unique_adj, unique_adj + size );
00934     *adj_entity_handles_size = std::unique( unique_adj, unique_adj + size ) - unique_adj;
00935 
00936     // If we created a temporary array for unique_adj rather than using
00937     // already allocated space in adj_entity_handles, allocate adj_entity_handles
00938     // and copy the unique handle list into it
00939     if( *adj_entity_handles != unique_adj )
00940     {
00941         if( !*adj_entity_handles_allocated )
00942         {
00943             *adj_entity_handles =
00944                 (iBase_EntityHandle*)malloc( sizeof( iBase_EntityHandle ) * *adj_entity_handles_size );
00945             if( !*adj_entity_handles )
00946                 *err = iBase_MEMORY_ALLOCATION_FAILED;
00947             else
00948                 *adj_entity_handles_allocated = *adj_entity_handles_size;
00949         }
00950         else if( *adj_entity_handles_allocated < *adj_entity_handles_size )
00951             *err = iBase_BAD_ARRAY_DIMENSION;
00952         if( iBase_SUCCESS != *err )
00953         {
00954             free( unique_adj );
00955             free( all_adj_handles );
00956             if( allocated_entity_handles )
00957             {
00958                 free( *entity_handles );
00959                 *entity_handles           = 0;
00960                 *entity_handles_allocated = 0;
00961             }
00962             if( allocated_offset )
00963             {
00964                 free( *offset );
00965                 *offset           = 0;
00966                 *offset_allocated = 0;
00967             }
00968             if( allocated_indices )
00969             {
00970                 free( *adj_entity_indices );
00971                 *adj_entity_indices           = 0;
00972                 *adj_entity_indices_allocated = 0;
00973             }
00974             return;
00975         }
00976 
00977         std::copy( unique_adj, unique_adj + *adj_entity_handles_size, *adj_entity_handles );
00978         free( unique_adj );
00979         unique_adj = *adj_entity_handles;
00980     }
00981 
00982     // convert from adjacency list to indices into unique_adj
00983     for( int i = 0; i < *adj_entity_indices_size; ++i )
00984         ( *adj_entity_indices )[i] =
00985             std::lower_bound( unique_adj, unique_adj + *adj_entity_handles_size, all_adj_handles[i] ) - unique_adj;
00986     free( all_adj_handles );
00987 }
00988 
00989 void iMeshP_getEntities( iMesh_Instance instance,
00990                          const iMeshP_PartitionHandle,
00991                          const iMeshP_PartHandle part_handle,
00992                          const iBase_EntitySetHandle entity_set_handle,
00993                          const int entity_type,
00994                          const int entity_topology,
00995                          iBase_EntityHandle** entity_handles,
00996                          int* entity_handles_allocated,
00997                          int* entity_handles_size,
00998                          int* err )
00999 {
01000     Range r;
01001     set_intersection_query( instance, part_handle, entity_set_handle, entity_type, entity_topology, r, err );
01002     if( iBase_SUCCESS != *err ) return;
01003 
01004     RANGE_TO_ITAPS_ARRAY( r, entity_handles );
01005     RETURN( iBase_SUCCESS );
01006 }
01007 
01008 void iMeshP_getAdjEntities( iMesh_Instance instance,
01009                             const iMeshP_PartitionHandle /*partition_handle*/,
01010                             const iMeshP_PartHandle part_handle,
01011                             const iBase_EntitySetHandle entity_set_handle,
01012                             const int entity_type_requestor,
01013                             const int entity_topology_requestor,
01014                             const int entity_type_requested,
01015                             iBase_EntityHandle** adj_entity_handles,
01016                             int* adj_entity_handles_allocated,
01017                             int* adj_entity_handles_size,
01018                             int** offset,
01019                             int* offset_allocated,
01020                             int* offset_size,
01021                             int** in_entity_set,
01022                             int* in_entity_set_allocated,
01023                             int* in_entity_set_size,
01024                             int* err )
01025 {
01026     ErrorCode rval;
01027     Range r;
01028     set_intersection_query( instance, part_handle, entity_set_handle, entity_type_requestor, entity_topology_requestor,
01029                             r, err );
01030     if( iBase_SUCCESS != *err ) return;
01031 
01032     // count adjacencies
01033     std::vector< EntityHandle > tmp_storage;
01034     int num_adj = 0;
01035     int num_conn;
01036     const EntityHandle* conn_ptr;
01037     for( Range::iterator i = r.begin(); i != r.end(); ++i )
01038     {
01039         if( entity_type_requested || TYPE_FROM_HANDLE( *i ) == MBPOLYHEDRON )
01040         {
01041             tmp_storage.clear();
01042             rval = MOABI->get_adjacencies( &*i, 1, entity_type_requested, false, tmp_storage );CHKERR( rval, "get_adjacencies failed" );
01043             num_adj += tmp_storage.size();
01044         }
01045         else
01046         {
01047             rval = MOABI->get_connectivity( *i, conn_ptr, num_conn, false, &tmp_storage );CHKERR( rval, "get_connectivity failed" );
01048             num_adj += num_conn;
01049         }
01050     }
01051 
01052     // get adjacencies
01053     ALLOC_CHECK_ARRAY( adj_entity_handles, num_adj );
01054     ALLOC_CHECK_ARRAY( offset, r.size() );
01055     int arr_pos      = 0;
01056     int* offset_iter = *offset;
01057     for( Range::iterator i = r.begin(); i != r.end(); ++i )
01058     {
01059         *offset_iter = arr_pos;
01060         ++offset_iter;
01061 
01062         tmp_storage.clear();
01063         rval = MOABI->get_adjacencies( &*i, 1, entity_type_requested, false, tmp_storage );CHKERR( rval, "get_adjacencies failed" );
01064         for( std::vector< EntityHandle >::iterator j = tmp_storage.begin(); j != tmp_storage.end(); ++j )
01065         {
01066             ( *adj_entity_handles )[arr_pos] = itaps_cast< iBase_EntityHandle >( *j );
01067             ++arr_pos;
01068         }
01069     }
01070 
01071     // get in_entity_set
01072     iMesh_isEntArrContained( instance, entity_set_handle, *adj_entity_handles, *adj_entity_handles_size, in_entity_set,
01073                              in_entity_set_allocated, in_entity_set_size, err );
01074 
01075     if( iBase_SUCCESS == *err )
01076     {
01077         KEEP_ARRAY( adj_entity_handles );
01078         KEEP_ARRAY( offset );
01079     }
01080 }
01081 
01082 void iMeshP_initEntIter( iMesh_Instance instance,
01083                          const iMeshP_PartitionHandle partition_handle,
01084                          const iMeshP_PartHandle part_handle,
01085                          const iBase_EntitySetHandle entity_set_handle,
01086                          const int requested_entity_type,
01087                          const int requested_entity_topology,
01088                          iBase_EntityIterator* entity_iterator,
01089                          int* err )
01090 {
01091     iMeshP_initEntArrIter( instance, partition_handle, part_handle, entity_set_handle, requested_entity_type,
01092                            requested_entity_topology, 1,
01093                            reinterpret_cast< iBase_EntityArrIterator* >( entity_iterator ), err );
01094 }
01095 
01096 void iMeshP_initEntArrIter( iMesh_Instance instance,
01097                             const iMeshP_PartitionHandle /*partition_handle*/,
01098                             const iMeshP_PartHandle part_handle,
01099                             const iBase_EntitySetHandle entity_set_handle,
01100                             const int requested_entity_type,
01101                             const int requested_entity_topology,
01102                             const int requested_array_size,
01103                             iBase_EntityArrIterator* entArr_iterator,
01104                             int* err )
01105 {
01106     if( !entity_set_handle || entity_set_handle == part_handle )
01107     {
01108         iMesh_initEntArrIter( instance, part_handle, requested_entity_type, requested_entity_topology,
01109                               requested_array_size,
01110                               0,  // TODO: update this function for "resilient" arg
01111                               entArr_iterator, err );
01112     }
01113     else
01114     {
01115         unsigned flags;
01116         ErrorCode result = MOABI->get_meshset_options( itaps_cast< EntityHandle >( entity_set_handle ), flags );CHKERR( result, "Invalid entity set handle" );
01117         if( flags & MESHSET_ORDERED )
01118             *entArr_iterator = new SetIntersectIter< std::vector< EntityHandle > >(
01119                 (iBase_EntityType)requested_entity_type, (iMesh_EntityTopology)requested_entity_topology,
01120                 itaps_cast< EntityHandle >( entity_set_handle ), itaps_cast< EntityHandle >( part_handle ),
01121                 requested_array_size );
01122         else
01123             *entArr_iterator =
01124                 new SetIntersectIter< Range >( (iBase_EntityType)requested_entity_type,
01125                                                (iMesh_EntityTopology)requested_entity_topology,
01126                                                itaps_cast< EntityHandle >( entity_set_handle ),
01127                                                itaps_cast< EntityHandle >( part_handle ), requested_array_size );
01128         result = ( *entArr_iterator )->reset( MOABI );
01129         if( MB_SUCCESS != result ) delete *entArr_iterator;CHKERR( result, "iMesh_initEntArrIter: ERROR getting entities of proper type or topology." );
01130         RETURN( iBase_SUCCESS );
01131     }
01132 }
01133 
01134 void iMeshP_getEntOwnerPart( iMesh_Instance instance,
01135                              const iMeshP_PartitionHandle partition_handle,
01136                              const iBase_EntityHandle entity_handle,
01137                              iMeshP_Part* part_id,
01138                              int* err )
01139 {
01140     int junk1 = 1, junk2 = 1;
01141     iMeshP_getEntOwnerPartArr( instance, partition_handle, &entity_handle, 1, &part_id, &junk1, &junk2, err );
01142 }
01143 
01144 void iMeshP_getEntOwnerPartArr( iMesh_Instance instance,
01145                                 const iMeshP_PartitionHandle partition_handle,
01146                                 const iBase_EntityHandle* entity_handles,
01147                                 const int entity_handles_size,
01148                                 iMeshP_Part** part_ids,
01149                                 int* part_ids_allocated,
01150                                 int* part_ids_size,
01151                                 int* err )
01152 {
01153     ParallelComm* pcomm = PCOMM;
01154     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01155 
01156     int id;
01157     ALLOC_CHECK_ARRAY( part_ids, entity_handles_size );
01158     ErrorCode rval = MB_SUCCESS;
01159     for( int i = 0; i < entity_handles_size; ++i )
01160     {
01161         EntityHandle h   = itaps_cast< EntityHandle >( entity_handles[i] );
01162         rval             = pcomm->get_owning_part( h, id );
01163         ( *part_ids )[i] = id;CHKERR( rval, "Failet get part owner" );
01164     }
01165     KEEP_ARRAY( part_ids );
01166     RETURN( iBase_SUCCESS );
01167 }
01168 
01169 void iMeshP_isEntOwner( iMesh_Instance instance,
01170                         const iMeshP_PartitionHandle partition_handle,
01171                         const iMeshP_PartHandle part_handle,
01172                         const iBase_EntityHandle entity_handle,
01173                         int* is_owner,
01174                         int* err )
01175 {
01176     int junk1 = 1, junk2 = 1;
01177     iMeshP_isEntOwnerArr( instance, partition_handle, part_handle, &entity_handle, 1, &is_owner, &junk1, &junk2, err );
01178 }
01179 
01180 void iMeshP_isEntOwnerArr( iMesh_Instance instance,
01181                            const iMeshP_PartitionHandle partition_handle,
01182                            const iMeshP_PartHandle part_handle,
01183                            const iBase_EntityHandle* entity_handles,
01184                            const int entity_handles_size,
01185                            int** is_owner,
01186                            int* is_owner_allocated,
01187                            int* is_owner_size,
01188                            int* err )
01189 {
01190     ErrorCode rval;
01191     ParallelComm* pcomm = PCOMM;
01192     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01193 
01194     int id;
01195     rval = pcomm->get_part_id( itaps_cast< EntityHandle >( part_handle ), id );CHKERR( rval, "error getting part id" );
01196 
01197     ALLOC_CHECK_ARRAY( is_owner, entity_handles_size );
01198     *is_owner_size = entity_handles_size;
01199 
01200     int owner;
01201     for( int i = 0; i < entity_handles_size; ++i )
01202     {
01203         rval = pcomm->get_owner( itaps_cast< EntityHandle >( entity_handles[i] ), owner );CHKERR( rval, "error getting owner" );
01204         ( *is_owner )[i] = ( owner == id );
01205     }
01206 
01207     KEEP_ARRAY( is_owner );
01208     RETURN( iBase_SUCCESS );
01209 }
01210 
01211 void iMeshP_getEntStatus( iMesh_Instance instance,
01212                           /*in*/ const iMeshP_PartitionHandle partition_handle,
01213                           /*in*/ const iMeshP_PartHandle part_handle,
01214                           /*in*/ const iBase_EntityHandle entity_handle,
01215                           /*out*/ int* par_status,  // Values=INTERNAL,BOUNDARY,GHOST
01216                           int* err )
01217 {
01218     int junk1 = 1, junk2 = 1;
01219     iMeshP_getEntStatusArr( instance, partition_handle, part_handle, &entity_handle, 1, &par_status, &junk1, &junk2,
01220                             err );
01221 }
01222 
01223 void iMeshP_getEntStatusArr( iMesh_Instance instance,
01224                              /*in*/ const iMeshP_PartitionHandle partition_handle,
01225                              /*in*/ const iMeshP_PartHandle /*part_handle*/,
01226                              /*in*/ const iBase_EntityHandle* entity_handles,
01227                              /*in*/ const int entity_handles_size,
01228                              /*inout*/ int** par_status,  // Values=INTERNAL,BOUNDARY,GHOST
01229                              /*inout*/ int* par_status_allocated,
01230                              /*inout*/ int* par_status_size,
01231                              int* err )
01232 {
01233     ParallelComm* pcomm = PCOMM;
01234     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01235 
01236     std::vector< unsigned char > pstatus( entity_handles_size );
01237     ErrorCode result = MOABI->tag_get_data( pcomm->pstatus_tag(), itaps_cast< const EntityHandle* >( entity_handles ),
01238                                             entity_handles_size, &pstatus[0] );CHKERR( result, "error getting pstatus_tag" );
01239 
01240     ALLOC_CHECK_ARRAY( par_status, entity_handles_size );
01241     for( int i = 0; i < entity_handles_size; i++ )
01242     {
01243         if( !pstatus[i] )
01244             ( *par_status )[i] = iMeshP_INTERNAL;
01245         else if( pstatus[i] & PSTATUS_GHOST )
01246             ( *par_status )[i] = iMeshP_GHOST;
01247         else if( pstatus[i] & PSTATUS_INTERFACE )
01248             ( *par_status )[i] = iMeshP_BOUNDARY;
01249     }
01250 
01251     KEEP_ARRAY( par_status );
01252     RETURN( iBase_SUCCESS );
01253 }
01254 
01255 void iMeshP_getNumCopies( iMesh_Instance instance,
01256                           const iMeshP_PartitionHandle partition_handle,
01257                           const iBase_EntityHandle entity_handle,
01258                           int* num_copies_ent,
01259                           int* err )
01260 {
01261     ParallelComm* pcomm = PCOMM;
01262     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01263 
01264     int ids[MAX_SHARING_PROCS];
01265     ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, *num_copies_ent );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
01266     RETURN( iBase_SUCCESS );
01267 }
01268 
01269 void iMeshP_getCopyParts( iMesh_Instance instance,
01270                           const iMeshP_PartitionHandle partition_handle,
01271                           const iBase_EntityHandle entity_handle,
01272                           iMeshP_Part** part_ids,
01273                           int* part_ids_allocated,
01274                           int* part_ids_size,
01275                           int* err )
01276 {
01277     ParallelComm* pcomm = PCOMM;
01278     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01279 
01280     int ids[MAX_SHARING_PROCS], num_ids;
01281     ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, num_ids );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
01282     ALLOC_CHECK_ARRAY_NOFAIL( part_ids, num_ids );
01283     std::copy( ids, ids + num_ids, *part_ids );
01284     RETURN( iBase_SUCCESS );
01285 }
01286 
01287 void iMeshP_getCopies( iMesh_Instance instance,
01288                        const iMeshP_PartitionHandle partition_handle,
01289                        const iBase_EntityHandle entity_handle,
01290                        iMeshP_Part** part_ids,
01291                        int* part_ids_allocated,
01292                        int* part_ids_size,
01293                        iBase_EntityHandle** copies_entity_handles,
01294                        int* copies_entity_handles_allocated,
01295                        int* copies_entity_handles_size,
01296                        int* err )
01297 {
01298     ParallelComm* pcomm = PCOMM;
01299     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01300 
01301     int ids[MAX_SHARING_PROCS], num_ids;
01302     EntityHandle handles[MAX_SHARING_PROCS];
01303     ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, num_ids, handles );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
01304     ALLOC_CHECK_ARRAY_NOFAIL( part_ids, num_ids );
01305     ALLOC_CHECK_ARRAY_NOFAIL( copies_entity_handles, num_ids );
01306     for( int i = 0; i < num_ids; ++i )
01307     {
01308         ( *part_ids )[i]              = ids[i];
01309         ( *copies_entity_handles )[i] = itaps_cast< iBase_EntityHandle >( handles[i] );
01310     }
01311     RETURN( iBase_SUCCESS );
01312 }
01313 
01314 void iMeshP_getCopyOnPart( iMesh_Instance instance,
01315                            const iMeshP_PartitionHandle partition_handle,
01316                            const iBase_EntityHandle entity_handle,
01317                            const iMeshP_Part part_id,
01318                            iBase_EntityHandle* copy_entity_handle,
01319                            int* err )
01320 {
01321     ParallelComm* pcomm = PCOMM;
01322     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01323 
01324     int ids[MAX_SHARING_PROCS], num_ids;
01325     EntityHandle handles[MAX_SHARING_PROCS];
01326     ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, num_ids, handles );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
01327     int idx = std::find( ids, ids + num_ids, part_id ) - ids;
01328     if( idx == num_ids ) RETURN( iBase_FAILURE );
01329 
01330     *copy_entity_handle = itaps_cast< iBase_EntityHandle >( handles[idx] );
01331     RETURN( iBase_SUCCESS );
01332 }
01333 
01334 void iMeshP_getOwnerCopy( iMesh_Instance instance,
01335                           const iMeshP_PartitionHandle partition_handle,
01336                           const iBase_EntityHandle entity_handle,
01337                           iMeshP_Part* owner_part_id,
01338                           iBase_EntityHandle* owner_entity_handle,
01339                           int* err )
01340 {
01341     ParallelComm* pcomm = PCOMM;
01342     if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
01343 
01344     int id;
01345     EntityHandle h;
01346     ErrorCode rval = pcomm->get_owning_part( itaps_cast< EntityHandle >( entity_handle ), id, &h );CHKERR( rval, "Failed to get owner" );
01347     *owner_part_id       = id;
01348     *owner_entity_handle = itaps_cast< iBase_EntityHandle >( h );
01349     RETURN( iBase_SUCCESS );
01350 }
01351 
01352 void iMeshP_waitForAnyRequest( iMesh_Instance instance,
01353                                iMeshP_PartitionHandle,
01354                                iMeshP_RequestHandle*,
01355                                int,
01356                                int*,
01357                                int* err )
01358 {
01359     FIXME;
01360     RETURN( iBase_NOT_SUPPORTED );
01361 }
01362 
01363 void iMeshP_waitForAllRequests( iMesh_Instance instance, iMeshP_PartitionHandle, iMeshP_RequestHandle*, int, int* err )
01364 {
01365     FIXME;
01366     RETURN( iBase_NOT_SUPPORTED );
01367 }
01368 
01369 void iMeshP_waitForRequestEnt( iMesh_Instance instance,
01370                                const iMeshP_PartitionHandle,
01371                                iMeshP_RequestHandle,
01372                                iBase_EntityHandle**,
01373                                int*,
01374                                int*,
01375                                int* err )
01376 {
01377     FIXME;
01378     RETURN( iBase_NOT_SUPPORTED );
01379 }
01380 
01381 void iMeshP_testRequest( iMesh_Instance instance, const iMeshP_PartitionHandle, iMeshP_RequestHandle, int*, int* err )
01382 {
01383     FIXME;
01384     RETURN( iBase_NOT_SUPPORTED );
01385 }
01386 
01387 void iMeshP_pollForRequests( iMesh_Instance instance,
01388                              iMeshP_PartitionHandle,
01389                              iMeshP_RequestHandle**,
01390                              int*,
01391                              int*,
01392                              int* err )
01393 {
01394     FIXME;
01395     RETURN( iBase_NOT_SUPPORTED );
01396 }
01397 
01398 void iMeshP_exchEntArrToPartsAll( iMesh_Instance instance,
01399                                   const iMeshP_PartitionHandle partition_handle,
01400                                   const iBase_EntityHandle* entity_handles,
01401                                   const int entity_handles_size,
01402                                   const iMeshP_Part* target_part_ids,
01403                                   int command_code,
01404                                   int update_ghost,
01405                                   iMeshP_RequestHandle* /*request*/,
01406                                   int* err )
01407 {
01408     if( command_code == 1 )
01409     {
01410         std::cerr << "Entity migration option is not supported." << std::endl;
01411         RETURN( iBase_NOT_SUPPORTED );
01412     }
01413 
01414     if( update_ghost == 1 )
01415     {
01416         std::cerr << "Gost update option is not supported." << std::endl;
01417         RETURN( iBase_NOT_SUPPORTED );
01418     }
01419 
01420     // make exchange entity and processor list
01421     ErrorCode rval;
01422     ParallelComm* pcomm = PCOMM;
01423     std::vector< unsigned int > exchange_procs;
01424     std::vector< Range* > exchange_ents;
01425 
01426     for( int i = 0; i < entity_handles_size; i++ )
01427     {
01428         int ind = -1;
01429         // iMeshP_Part target_p = target_part_ids[i];
01430         int target_p;
01431         rval = pcomm->get_part_owner( target_part_ids[i], target_p );CHKERR( rval, "ParallelComm::get_part_owner failed" );
01432 
01433         std::vector< unsigned int >::iterator vit = std::find( exchange_procs.begin(), exchange_procs.end(), target_p );
01434         if( vit == exchange_procs.end() )
01435         {
01436             ind = exchange_procs.size();
01437             exchange_procs.push_back( target_p );
01438             exchange_ents.push_back( new Range );
01439         }
01440         else
01441             ind = vit - exchange_procs.begin();
01442 
01443         exchange_ents[ind]->insert( itaps_cast< EntityHandle >( entity_handles[i] ) );
01444     }
01445 
01446     std::vector< MPI_Request > recv_ent_reqs, recv_remoteh_reqs;
01447     rval = pcomm->exchange_owned_meshs( exchange_procs, exchange_ents, recv_ent_reqs, recv_remoteh_reqs, true );CHKERR( rval, "ParallelComm::exchange_owned_meshs failed" );
01448 
01449     // delete exchange list
01450     std::vector< Range* >::iterator vit;
01451     for( vit = exchange_ents.begin(); vit != exchange_ents.end(); ++vit )
01452         delete( *vit );
01453 
01454     RETURN( iBase_SUCCESS );
01455 }
01456 
01457 void iMeshP_migrateEntity( iMesh_Instance instance,
01458                            const iMeshP_PartitionHandle,
01459                            const iMeshP_PartHandle,
01460                            const iBase_EntityHandle,
01461                            iMeshP_RequestHandle*,
01462                            int* err )
01463 {
01464     FIXME;
01465     RETURN( iBase_NOT_SUPPORTED );
01466 }
01467 
01468 void iMeshP_updateVtxCoords( iMesh_Instance instance, const iMeshP_PartitionHandle, const iBase_EntityHandle, int* err )
01469 {
01470     FIXME;
01471     RETURN( iBase_NOT_SUPPORTED );
01472 }
01473 
01474 void iMeshP_replaceOnPartBdry( iMesh_Instance instance,
01475                                const iMeshP_PartitionHandle,
01476                                const iBase_EntityHandle*,
01477                                const int,
01478                                const iBase_EntityHandle*,
01479                                const int,
01480                                const int*,
01481                                const int,
01482                                int* err )
01483 {
01484     FIXME;
01485     RETURN( iBase_NOT_SUPPORTED );
01486 }
01487 
01488 void iMeshP_addGhostOf( iMesh_Instance instance,
01489                         const iMeshP_PartitionHandle,
01490                         const iMeshP_Part,
01491                         const iBase_EntityHandle,
01492                         iMeshP_RequestHandle*,
01493                         int* err )
01494 {
01495     FIXME;
01496     RETURN( iBase_NOT_SUPPORTED );
01497 }
01498 
01499 void iMeshP_rmvGhostOf( iMesh_Instance instance,
01500                         const iMeshP_PartitionHandle,
01501                         const iMeshP_Part,
01502                         const iBase_EntityHandle,
01503                         int* err )
01504 {
01505     FIXME;
01506     RETURN( iBase_NOT_SUPPORTED );
01507 }
01508 
01509 void iMeshP_syncMeshAll( iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, int* err )
01510 {
01511     ParallelComm* pcomm = PCOMM;
01512     ErrorCode rval      = pcomm->resolve_shared_ents( itaps_cast< EntityHandle >( partition_handle ), -1, -1 );CHKERR( rval, "update failed" );
01513     RETURN( iBase_SUCCESS );
01514 }
01515 
01516 void iMeshP_pushTags( iMesh_Instance instance,
01517                       const iMeshP_PartitionHandle partition_handle,
01518                       iBase_TagHandle source_tag,
01519                       iBase_TagHandle dest_tag,
01520                       int entity_type,
01521                       int entity_topo,
01522                       int* err )
01523 {
01524     ParallelComm* pcomm = PCOMM;
01525     DimensionPair types;
01526     if( entity_topo != iMesh_ALL_TOPOLOGIES )
01527         types.first = types.second = mb_topology_table[entity_topo];
01528     else if( entity_type != iBase_ALL_TYPES )
01529         // types = CN::TypeDimensionMap[entity_type];
01530         types = CN::getDimPair( entity_type );
01531     else
01532     {
01533         types.first  = MBVERTEX;
01534         types.second = MBENTITYSET;
01535         --types.second;
01536     }
01537 
01538     std::vector< Tag > src_tags( 1, itaps_cast< Tag >( source_tag ) );
01539     std::vector< Tag > dst_tags( 1, itaps_cast< Tag >( dest_tag ) );
01540 
01541     ErrorCode rval;
01542     Range entities;
01543     for( EntityType t = types.first; t <= types.second; ++t )
01544     {
01545         rval = MOABI->get_entities_by_type_and_tag( 0, t, &src_tags[0], 0, 1, entities, Interface::UNION );CHKERR( rval, "error getting entities to push" );
01546     }
01547 
01548     rval = pcomm->exchange_tags( src_tags, dst_tags, entities );CHKERR( rval, "tag data communication failed" );
01549     RETURN( iBase_SUCCESS );
01550 }
01551 
01552 void iMeshP_pushTagsEnt( iMesh_Instance instance,
01553                          const iMeshP_PartitionHandle partition_handle,
01554                          iBase_TagHandle source_tag,
01555                          iBase_TagHandle dest_tag,
01556                          const iBase_EntityHandle* entities,
01557                          int entities_size,
01558                          int* err )
01559 {
01560 
01561     Range range;
01562     const EntityHandle* ents = itaps_cast< const EntityHandle* >( entities );
01563     std::copy( ents, ents + entities_size, range_inserter( range ) );
01564 
01565     std::vector< Tag > src_tags( 1, itaps_cast< Tag >( source_tag ) );
01566     std::vector< Tag > dst_tags( 1, itaps_cast< Tag >( dest_tag ) );
01567     ParallelComm* pcomm = PCOMM;
01568     ErrorCode rval      = pcomm->exchange_tags( src_tags, dst_tags, range );CHKERR( rval, "tag data communication failed" );
01569     RETURN( iBase_SUCCESS );
01570 }
01571 
01572 void iMeshP_iPushTags( iMesh_Instance instance,
01573                        const iMeshP_PartitionHandle,
01574                        iBase_TagHandle,
01575                        iBase_TagHandle,
01576                        int,
01577                        int,
01578                        iMeshP_RequestHandle*,
01579                        int* err )
01580 {
01581     FIXME;
01582     RETURN( iBase_NOT_SUPPORTED );
01583 }
01584 
01585 void iMeshP_iPushTagsEnt( iMesh_Instance instance,
01586                           const iMeshP_PartitionHandle,
01587                           iBase_TagHandle,
01588                           iBase_TagHandle,
01589                           const iBase_EntityHandle*,
01590                           int,
01591                           iMeshP_RequestHandle*,
01592                           int* err )
01593 {
01594     FIXME;
01595     RETURN( iBase_NOT_SUPPORTED );
01596 }
01597 
01598 void iMeshP_createGhostEntsAll( iMesh_Instance instance,
01599                                 iMeshP_PartitionHandle partition_handle,
01600                                 int ghost_dim,
01601                                 int bridge_dim,
01602                                 int num_layers,
01603                                 int include_copies,
01604                                 int* err )
01605 {
01606     if( include_copies )
01607     {
01608         FIXME;
01609         RETURN( iBase_NOT_SUPPORTED );
01610     }
01611 
01612     ParallelComm* pcomm = PCOMM;
01613     ErrorCode rval;
01614     if( iBase_ALL_TYPES == ghost_dim ) ghost_dim = -1;
01615     rval = pcomm->exchange_ghost_cells( ghost_dim, bridge_dim, num_layers, 0, true );CHKERR( rval, "ghost exchange failed" );
01616     RETURN( iBase_SUCCESS );
01617 }
01618 
01619 void iMeshP_deleteGhostEntsAll( iMesh_Instance instance, iMeshP_PartitionHandle, int* err )
01620 {
01621     FIXME;
01622     RETURN( iBase_NOT_SUPPORTED );
01623 }
01624 
01625 void iMeshP_ghostEntInfo( const iMesh_Instance instance,
01626                           const iMeshP_PartitionHandle,
01627                           int*,
01628                           int*,
01629                           int**,
01630                           int**,
01631                           int**,
01632                           int* err )
01633 {
01634     FIXME;
01635     RETURN( iBase_NOT_SUPPORTED );
01636 }
01637 
01638 // append the specified option if it isn't already there; returns whether this
01639 // function actually appended it or not
01640 static bool append_option( std::string& opt, const char* option, const char* default_value = 0 )
01641 {
01642     std::string::size_type i;
01643 
01644     const char sep = ' ';
01645 
01646     if( strchr( option, sep ) || ( default_value && strchr( default_value, sep ) ) )
01647     {
01648         // options can't have a separator in them; XXX work around this
01649         return false;  // iBase_INVALID_ARGUMENT;
01650     }
01651 
01652     // search for the required option
01653     std::string search( &sep, 1 );
01654     search += option;
01655     const std::string::size_type sl = search.length();
01656     i                               = opt.find( search );
01657     while( i != std::string::npos )
01658     {
01659         std::string::size_type end = i + sl;
01660         if( end == opt.size() || opt[end] == sep || opt[end] == '=' ) break;
01661         i = end;
01662     }
01663 
01664     // if string already contained the option, just return
01665     if( i != std::string::npos ) return false;
01666 
01667     opt += search;
01668     if( default_value )
01669     {
01670         opt += "=";
01671         opt += default_value;
01672     }
01673 
01674     return true;
01675 }
01676 
01677 void iMeshP_loadAll( iMesh_Instance instance,
01678                      const iMeshP_PartitionHandle partition,
01679                      const iBase_EntitySetHandle entity_set_handle,
01680                      const char* name,
01681                      const char* options,
01682                      int* err,
01683                      int name_len,
01684                      int options_len )
01685 {
01686     ErrorCode rval;
01687 
01688     // create partition set if user didn't give us one.
01689     EntityHandle partitioning;
01690     if( partition )
01691     {
01692         partitioning = itaps_cast< EntityHandle >( partition );
01693     }
01694     else
01695     {
01696         rval = MOABI->create_meshset( MESHSET_SET, partitioning );CHKERR( rval, "failed to create meshset" );
01697     }
01698 
01699     // get ParallelComm for partition
01700     MPI_Comm default_comm = MPI_COMM_WORLD;
01701     ParallelComm* pcomm   = ParallelComm::get_pcomm( MOABI, partitioning, &default_comm );
01702     if( !pcomm )
01703     {
01704         RETURN( iBase_FAILURE );
01705     }
01706 
01707     // add necessary values to options string
01708     std::string opt = std::string( options, options + options_len );
01709 
01710     if( append_option( opt, "moab:PARALLEL" ) )
01711     {
01712         // only append these other ones if the parallel option wasn't there originally
01713         append_option( opt, "moab:PARTITION_DISTRIBUTE" );
01714         append_option( opt, "moab:PARALLEL_RESOLVE_SHARED_ENTS" );
01715         std::ostringstream id;
01716         id << pcomm->get_id();
01717         append_option( opt, "moab:PCOMM", id.str().c_str() );
01718     }
01719 
01720     // load the file
01721     iMesh_load( instance, entity_set_handle, name, opt.c_str(), err, name_len, opt.length() );
01722     if( *err ) return;
01723 
01724     rval = pcomm->collective_sync_partition();CHKERR( rval, "collective sync failed" );
01725     RETURN( iBase_SUCCESS );
01726 }
01727 
01728 void iMeshP_saveAll( iMesh_Instance instance,
01729                      const iMeshP_PartitionHandle partition,
01730                      const iBase_EntitySetHandle entity_set_handle,
01731                      const char* name,
01732                      const char* options,
01733                      int* err,
01734                      const int name_len,
01735                      int options_len )
01736 {
01737     EntityHandle set;
01738     set = entity_set_handle ? itaps_cast< EntityHandle >( entity_set_handle ) : itaps_cast< EntityHandle >( partition );
01739     iMesh_save( instance, itaps_cast< iBase_EntitySetHandle >( set ), name, options, err, name_len, options_len );
01740 }
01741 
01742 //  Map from processes to parts:
01743 //  Given a partition handle and a process rank,
01744 //  return the part handles owned by the process.
01745 //  COMMUNICATION:  None++.
01746 void iMeshP_getPartsOnRank( iMesh_Instance instance,
01747                             const iMeshP_PartitionHandle partition_handle,
01748                             /*in*/ const int /*rank*/,
01749                             /*inout*/ iMeshP_PartHandle** part_handles,
01750                             /*inout*/ int* part_handles_allocated,
01751                             /*out*/ int* part_handles_size,
01752                             int* err )
01753 {
01754     EntityHandle p   = itaps_cast< EntityHandle >( partition_handle );
01755     ParallelComm* pc = ParallelComm::get_pcomm( MOABI, p );
01756     if( !pc ) RETURN( iBase_ERROR_MAP[MB_FAILURE] );
01757 
01758     Range part_sets;
01759 
01760     ALLOC_CHECK_ARRAY_NOFAIL( part_handles, pc->partition_sets().size() );
01761     Range::iterator rit;
01762     int i;
01763     for( i = 0, rit = pc->partition_sets().begin(); rit != pc->partition_sets().end(); ++rit, i++ )
01764         ( *part_handles )[i] = itaps_cast< iMeshP_PartHandle >( *rit );
01765 
01766     RETURN( iBase_SUCCESS );
01767 }
01768 
01769 void iMeshP_getPartsArrOnRank( iMesh_Instance instance,
01770                                const iMeshP_PartitionHandle partition_handle,
01771                                /*in*/ const int* rank,
01772                                /*in*/ const int rank_size,
01773                                /*inout*/ iMeshP_PartHandle** part_handles,
01774                                /*inout*/ int* part_handles_allocated,
01775                                /*out*/ int* part_handles_size,
01776                                int* err )
01777 {
01778     EntityHandle p   = itaps_cast< EntityHandle >( partition_handle );
01779     ParallelComm* pc = ParallelComm::get_pcomm( MOABI, p );
01780     if( !pc ) RETURN( iBase_ERROR_MAP[MB_FAILURE] );
01781 
01782     if( rank[0] != (int)pc->proc_config().proc_rank() || rank_size > 1 )
01783     {
01784         RETURN( iBase_ERROR_MAP[MB_NOT_IMPLEMENTED] );
01785     }
01786 
01787     iMeshP_getPartsOnRank( instance, partition_handle, rank[0], part_handles, part_handles_allocated, part_handles_size,
01788                            err );
01789 }
01790 
01791 /** \brief Assign a global id space to entities
01792  * Assign a global id space to entities and vertices, and optionally intermediate-dimension entities
01793  *
01794  *  COMMUNICATION:  Collective.
01795  */
01796 void iMeshP_assignGlobalIds( iMesh_Instance instance,
01797                              const iMeshP_PartitionHandle partition,
01798                              const iBase_EntitySetHandle this_set,
01799                              const int dimension,
01800                              const int start_id,
01801                              const int largest_dim_only,
01802                              const int parallel,
01803                              const int owned_only,
01804                              int* err )
01805 {
01806     ErrorCode rval;
01807 
01808     // get partition set
01809     EntityHandle partitionset = itaps_cast< EntityHandle >( partition );
01810     if( !partitionset )
01811     {
01812         rval = MB_FAILURE;CHKERR( rval, "failed to get partition set" );
01813     }
01814 
01815     EntityHandle this_mb_set = itaps_cast< EntityHandle >( this_set );
01816 
01817     // get ParallelComm for partition
01818     MPI_Comm default_comm;
01819     ParallelComm* pcomm = ParallelComm::get_pcomm( MOABI, partitionset, &default_comm );
01820     if( !pcomm )
01821     {
01822         RETURN( iBase_FAILURE );
01823     }
01824 
01825     rval = pcomm->assign_global_ids( this_mb_set, dimension, start_id, largest_dim_only, parallel, owned_only );
01826 
01827     RETURN( rval );
01828 }
01829 
01830 void iMeshP_getCommunicator( iMesh_Instance instance, int* fcomm, MPI_Comm* ccomm, int* err )
01831 {
01832     *ccomm = MPI_Comm_f2c( *fcomm );
01833     RETURN( iBase_SUCCESS );
01834 }
01835 
01836 #ifdef __cplusplus
01837 }  // extern "C"
01838 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines