MOAB: Mesh Oriented datABase  (version 5.5.0)
iMeshP_MOAB.cpp
Go to the documentation of this file.
1 #include "moab/MOABConfig.h"
2 #include "iMeshP_extensions.h"
3 #include "iMesh_MOAB.hpp"
4 #include "moab/Core.hpp"
5 #include "moab/Range.hpp"
6 #include "moab/CN.hpp"
7 #include "moab/MeshTopoUtil.hpp"
8 #include "moab/FileOptions.hpp"
9 #include "moab/ParallelComm.hpp"
10 #include "MBParallelConventions.h"
11 #include "MBIter.hpp"
12 
13 #define IS_BUILDING_MB
14 #include "Internals.hpp"
15 #undef IS_BUILDING_MB
16 
17 #include <cassert>
18 #include <sstream>
19 
20 #ifdef MOAB_HAVE_MPI
21 #include "moab_mpi.h"
22 #endif
23 
24 using namespace moab;
25 
26 /********************* Error Handling **************************/
27 
28 #define FIXME printf( "Warning: function has incomplete implementation: %s\n", __func__ )
29 
30 /******** Type-safe casting between MOAB and ITAPS types *********/
31 
32 #ifndef MOAB_TEMPLATE_FUNC_SPECIALIZATION
33 // if no template specialization, disable some type checking
34 template < typename T, typename S >
35 inline T itaps_cast( S handle )
36 {
37  assert( sizeof( S ) >= sizeof( T ) );
38  return reinterpret_cast< T >( handle );
39 }
40 #else
41 
42 // basic template method : only works to cast to equivalent types (no-op)
43 template < typename T, typename S >
44 inline T itaps_cast( S h )
45 {
46  return h;
47 }
48 // verify size and do reinterpret cast
49 template < typename T >
50 inline T itaps_cast_internal_( EntityHandle h )
51 {
52  assert( sizeof( T ) >= sizeof( EntityHandle ) );
53  return reinterpret_cast< T >( h );
54 }
55 // verify size and do reinterpret cast
56 template < typename T >
57 inline EntityHandle* itaps_cast_ptr_( T* h )
58 {
59  assert( sizeof( T ) == sizeof( EntityHandle ) );
60  return reinterpret_cast< EntityHandle* >( h );
61 }
62 // verify size and do reinterpret cast
63 template < typename T >
64 inline const EntityHandle* itaps_cast_const_ptr_( const T* h )
65 {
66  assert( sizeof( T ) == sizeof( EntityHandle ) );
67  return reinterpret_cast< const EntityHandle* >( h );
68 }
69 // verify set-type handle before cast
70 template < typename T >
71 inline T itaps_set_cast_( EntityHandle h )
72 {
73  assert( TYPE_FROM_HANDLE( h ) == MBENTITYSET );
74  return itaps_cast_internal_< T >( h );
75 }
76 
77 // define conversion routines between itaps handle and EntityHandle types
78 #define DECLARE_ALLOWED_ITAPS_CONVERSION( ITAPS_HANDLE_TYPE ) \
79  template <> \
80  inline ITAPS_HANDLE_TYPE itaps_cast< ITAPS_HANDLE_TYPE, EntityHandle >( EntityHandle h ) \
81  { \
82  return itaps_cast_internal_< ITAPS_HANDLE_TYPE >( h ); \
83  } \
84  \
85  template <> \
86  inline EntityHandle itaps_cast< EntityHandle, ITAPS_HANDLE_TYPE >( ITAPS_HANDLE_TYPE handle ) \
87  { \
88  return reinterpret_cast< EntityHandle >( handle ); \
89  } \
90  \
91  template <> \
92  inline EntityHandle* itaps_cast< EntityHandle*, ITAPS_HANDLE_TYPE* >( ITAPS_HANDLE_TYPE * ptr ) \
93  { \
94  return itaps_cast_ptr_( ptr ); \
95  } \
96  \
97  template <> \
98  inline const EntityHandle* itaps_cast< const EntityHandle*, const ITAPS_HANDLE_TYPE* >( \
99  const ITAPS_HANDLE_TYPE* ptr ) \
100  { \
101  return itaps_cast_const_ptr_( ptr ); \
102  }
103 
104 // define conversion routines between itaps handle and EntityHandle types
105 // but limit to EntityHandle for MBENTITYSET type.
106 #define DECLARE_ALLOWED_ITAPS_SET_CONVERSION( ITAPS_HANDLE_TYPE ) \
107  template <> \
108  inline ITAPS_HANDLE_TYPE itaps_cast< ITAPS_HANDLE_TYPE, EntityHandle >( EntityHandle h ) \
109  { \
110  return itaps_set_cast_< ITAPS_HANDLE_TYPE >( h ); \
111  } \
112  \
113  template <> \
114  inline EntityHandle itaps_cast< EntityHandle, ITAPS_HANDLE_TYPE >( ITAPS_HANDLE_TYPE handle ) \
115  { \
116  return reinterpret_cast< EntityHandle >( handle ); \
117  } \
118  \
119  template <> \
120  inline EntityHandle* itaps_cast< EntityHandle*, ITAPS_HANDLE_TYPE* >( ITAPS_HANDLE_TYPE * ptr ) \
121  { \
122  return itaps_cast_ptr_( ptr ); \
123  } \
124  \
125  template <> \
126  inline const EntityHandle* itaps_cast< const EntityHandle*, const ITAPS_HANDLE_TYPE* >( \
127  const ITAPS_HANDLE_TYPE* ptr ) \
128  { \
129  return itaps_cast_const_ptr_( ptr ); \
130  }
131 
132 DECLARE_ALLOWED_ITAPS_SET_CONVERSION( iMeshP_PartitionHandle )
133 // DECLARE_ALLOWED_ITAPS_SET_CONVERSION( iMeshP_PartHandle )
134 DECLARE_ALLOWED_ITAPS_SET_CONVERSION( iBase_EntitySetHandle )
135 DECLARE_ALLOWED_ITAPS_CONVERSION( iBase_EntityHandle )
136 
137 template <>
138 inline Tag itaps_cast< Tag, iBase_TagHandle >( iBase_TagHandle h )
139 {
140  return reinterpret_cast< Tag >( h );
141 }
142 template <>
143 inline iBase_TagHandle itaps_cast< iBase_TagHandle, Tag >( Tag h )
144 {
145  return reinterpret_cast< iBase_TagHandle >( h );
146 }
147 
148 #endif
149 
150 #define PCOMM ParallelComm::get_pcomm( MOABI, itaps_cast< EntityHandle >( partition_handle ) )
151 
152 /*** static function implemented in iMesh_MOAB.cpp ***/
153 
154 // Need a different function name for Tag because (currently)
155 // both Tag and iBase_EntityHandle are void**.
157 {
158  assert( sizeof( iBase_TagHandle ) >= sizeof( Tag ) );
159  return reinterpret_cast< iBase_TagHandle >( t );
160 }
161 
162 /********************* ITAPS arrays **************************/
163 
164 // Handle returning Range in ITAPS array (do ALLOCATE_ARRAY and copy).
165 #define RANGE_TO_ITAPS_ARRAY( RANGE, NAME ) \
166  do \
167  { \
168  ALLOC_CHECK_ARRAY_NOFAIL( NAME, ( RANGE ).size() ); \
169  std::copy( ( RANGE ).begin(), ( RANGE ).end(), itaps_cast< EntityHandle* >( *( NAME ) ) ); \
170  } while( false )
171 
172 static inline ErrorCode get_entities( Interface* iface, EntityHandle set, int type, int topology, Range& entities )
173 {
174  if( topology != iMesh_ALL_TOPOLOGIES )
175  return iface->get_entities_by_type( set, mb_topology_table[topology], entities );
176  else if( type != iBase_ALL_TYPES )
177  return iface->get_entities_by_dimension( set, type, entities );
178  else
179  return iface->get_entities_by_handle( set, entities );
180 }
181 
182 /*
183 static inline ErrorCode remove_not_owned( ParallelComm* pcomm, Range& ents )
184 {
185  ErrorCode rval;
186 
187  std::vector<unsigned char> pstatus(ents.size());
188  rval = pcomm->get_moab()->tag_get_data(pcomm->pstatus_tag(), ents, &pstatus[0]);
189  if (MB_SUCCESS != rval)
190  return rval;
191 
192  Range::iterator i = ents.begin();
193  std::vector<unsigned char>::const_iterator j;
194  for (j = pstatus.begin(); j != pstatus.end(); ++j) {
195  if (*j & PSTATUS_NOT_OWNED)
196  i = ents.erase( i );
197  else
198  ++i;
199  }
200 
201  return MB_SUCCESS;
202 }
203 */
204 
205 static inline ErrorCode count_owned( ParallelComm* pcomm, const Range& ents, int& n )
206 {
207  ErrorCode rval;
208  n = 0;
209 
210  std::vector< unsigned char > pstatus( ents.size() );
211  rval = pcomm->get_moab()->tag_get_data( pcomm->pstatus_tag(), ents, &pstatus[0] );
212  if( MB_SUCCESS != rval ) return rval;
213 
214  std::vector< unsigned char >::const_iterator j;
215  for( j = pstatus.begin(); j != pstatus.end(); ++j )
216  if( !( *j & PSTATUS_NOT_OWNED ) ) ++n;
217 
218  return MB_SUCCESS;
219 }
220 
222  iMeshP_PartHandle set1,
224  int type,
225  int topo,
226  Range& result,
227  int* err )
228 {
229  ErrorCode rval;
230 
231  if( !set1 )
232  {
233  rval = get_entities( MOABI, itaps_cast< EntityHandle >( set2 ), type, topo, result );CHKERR( rval, "Invalid Part handle" );
234  }
235  else if( !set2 )
236  {
237  rval = get_entities( MOABI, itaps_cast< EntityHandle >( set1 ), type, topo, result );CHKERR( rval, "Invalid set handle" );
238  }
239  else
240  {
241  Range r1, r2;
242  rval = get_entities( MOABI, itaps_cast< EntityHandle >( set1 ), type, topo, r1 );CHKERR( rval, "Invalid Part handle" );
243  rval = get_entities( MOABI, itaps_cast< EntityHandle >( set2 ), type, topo, r2 );CHKERR( rval, "Invalid set handle" );
244  result.merge( intersect( r1, r2 ) );
245  }
246 
248 }
249 
250 /********************* Iterators **************************/
251 
253  EntityHandle part_handle,
254  int entity_type,
255  int entity_topology,
256  int adj_part_id,
257  Range& entities_out )
258 {
259  int* adj_part_id_ptr = ( adj_part_id == iMeshP_ALL_PARTS ) ? 0 : &adj_part_id;
260 
261  Range iface_sets;
262  ErrorCode rval = pcomm->get_interface_sets( part_handle, iface_sets, adj_part_id_ptr );
263  if( MB_SUCCESS != rval ) return rval;
264 
265  for( Range::iterator i = iface_sets.begin(); i != iface_sets.end(); ++i )
266  {
267  rval = get_entities( pcomm->get_moab(), *i, entity_type, entity_topology, entities_out );
268  if( MB_SUCCESS != rval ) return rval;
269  }
270 
271  return MB_SUCCESS;
272 }
273 
275 {
276  private:
278  int adjPart;
279 
280  public:
282  EntityHandle part_handle,
283  iBase_EntityType entity_type,
284  iMesh_EntityTopology entity_topology,
285  int adj_part_id,
286  int array_sz )
287  : MBRangeIter( entity_type, entity_topology, part_handle, array_sz ), pComm( pcomm ), adjPart( adj_part_id )
288  {
289  }
290 
292  {
293  iterData.clear();
294  ErrorCode result = get_boundary_entities( pComm, entSet, entType, entTopo, adjPart, iterData );
295  iterPos = iterData.begin();
296  return result;
297  }
298 };
299 
300 template < class Container >
301 class SetIntersectIter : public MBIter< Container >
302 {
303  private:
305 
306  public:
308  iMesh_EntityTopology topology,
309  EntityHandle set,
310  EntityHandle other_set,
311  int array_sz )
312  : MBIter< Container >( type, topology, set, array_sz ), otherSet( other_set )
313  {
314  }
315  virtual ~SetIntersectIter() {}
316 
318  {
319  Range tmp;
320  ErrorCode result;
321  result = mb->get_entities_by_handle( otherSet, tmp );
322  range = intersect( range, tmp );
323  return result;
324  }
325 
326  inline ErrorCode intersect_with_set( Interface* mb, std::vector< EntityHandle >& list )
327  {
328  size_t w = 0;
329  for( size_t r = 0; r < list.size(); ++r )
330  {
331  if( mb->contains_entities( otherSet, &list[r], 1 ) ) list[w++] = list[r];
332  }
333  list.resize( w );
334  return MB_SUCCESS;
335  }
336 
338  {
340  if( MB_SUCCESS != result ) return result;
341 
342  result = intersect_with_set( mb, MBIter< Container >::iterData );
344  return result;
345  }
346 };
347 
348 /********************* iMeshP API **************************/
349 
350 #ifdef __cplusplus
351 extern "C" {
352 #endif
353 
355  /*in*/ MPI_Comm communicator,
356  /*out*/ iMeshP_PartitionHandle* partition_handle,
357  int* err )
358 {
359  *partition_handle = 0;
360 
361  Tag prtn_tag;
362  ErrorCode rval = MOABI->tag_get_handle( PARALLEL_PARTITIONING_TAG_NAME, 1, MB_TYPE_INTEGER, prtn_tag,
363  MB_TAG_SPARSE | MB_TAG_CREAT );CHKERR( rval, "tag creation failed" );
364 
365  EntityHandle handle;
366  rval = MOABI->create_meshset( MESHSET_SET, handle );CHKERR( rval, "set creation failed" );
367  ParallelComm* pcomm = ParallelComm::get_pcomm( MOABI, handle, &communicator );
368  if( !pcomm )
369  {
370  MOABI->delete_entities( &handle, 1 );
372  }
373 
374  // set the value of pcomm id, to the partitioning tag, although this is not used
375  // we just need the tag to be set
376  int pid = pcomm->get_id();
377  rval = MOABI->tag_set_data( prtn_tag, &handle, 1, &pid );CHKERR( rval, "tag creation failed" );
378 
379  *partition_handle = itaps_cast< iMeshP_PartitionHandle >( handle );
381 }
382 
383 void iMeshP_destroyPartitionAll( iMesh_Instance instance, iMeshP_PartitionHandle partition_handle, int* err )
384 {
385  ParallelComm* pcomm = PCOMM;
386  if( pcomm ) delete pcomm;
387  EntityHandle handle = itaps_cast< EntityHandle >( partition_handle );
388  ErrorCode rval = MOABI->delete_entities( &handle, 1 );CHKERR( rval, "entity deletion failed" );
390 }
391 
393  const iMeshP_PartitionHandle partition_handle,
394  const iMeshP_PartHandle part_handle,
395  iMeshP_Part* part_id,
396  int* err )
397 {
398  int junk1 = 1, junk2;
399  iMeshP_getPartIdsFromPartHandlesArr( instance, partition_handle, &part_handle, 1, &part_id, &junk1, &junk2, err );
400 }
401 
403  const iMeshP_PartitionHandle partition_handle,
404  iMeshP_Part part_id,
405  iMeshP_PartHandle* part_handle,
406  int* err )
407 {
408  int junk1 = 1, junk2;
409  iMeshP_getPartHandlesFromPartsIdsArr( instance, partition_handle, &part_id, 1, &part_handle, &junk1, &junk2, err );
410 }
411 
413  const iMeshP_PartitionHandle partition_handle,
414  const iMeshP_PartHandle* part_handles,
415  const int part_handles_size,
416  iMeshP_Part** part_ids,
417  int* part_ids_allocated,
418  int* part_ids_size,
419  int* err )
420 {
421  ErrorCode rval;
422  ParallelComm* pcomm = PCOMM;
423  ALLOC_CHECK_ARRAY( part_ids, part_handles_size );
424  for( int i = 0; i < part_handles_size; ++i )
425  {
426  int id;
427  rval = pcomm->get_part_id( itaps_cast< EntityHandle >( part_handles[i] ), id );
428  ( *part_ids )[i] = id;CHKERR( rval, "error getting part id" );
429  }
430  KEEP_ARRAY( part_ids );
432 }
433 
435  const iMeshP_PartitionHandle partition_handle,
436  const iMeshP_Part* part_ids,
437  const int part_ids_size,
438  iMeshP_PartHandle** part_handles,
439  int* part_handles_allocated,
440  int* part_handles_size,
441  int* err )
442 {
443  ErrorCode rval;
444  ParallelComm* pcomm = PCOMM;
445  ALLOC_CHECK_ARRAY( part_handles, part_ids_size );
446  for( int i = 0; i < part_ids_size; ++i )
447  {
448  EntityHandle handle;
449  rval = pcomm->get_part_handle( part_ids[i], handle );CHKERR( rval, "error getting part handle" );
450  ( *part_handles )[i] = itaps_cast< iMeshP_PartHandle >( handle );
451  }
452  KEEP_ARRAY( part_handles );
454 }
455 
457  iMeshP_PartitionHandle partition_handle,
458  MPI_Comm* communicator_out,
459  int* err )
460 {
461  ParallelComm* pcomm = PCOMM;
462  if( !pcomm ) RETURN( iBase_FAILURE );
463  *communicator_out = pcomm->proc_config().proc_comm();
465 }
466 
467 void iMeshP_syncPartitionAll( iMesh_Instance instance, iMeshP_PartitionHandle partition_handle, int* err )
468 {
469  ParallelComm* pcomm = PCOMM;
470  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
471  ErrorCode rval = pcomm->collective_sync_partition();CHKERR( rval, "collective sync failed" );
473 }
474 
475 void iMeshP_getNumPartitions( iMesh_Instance instance, int* num_partitions_out, int* err )
476 {
477  std::vector< ParallelComm* > pcomms;
478  ErrorCode rval = ParallelComm::get_all_pcomm( MOABI, pcomms );CHKERR( rval, "Internal error retreiving PComms" );
479 
480  std::vector< ParallelComm* >::iterator i;
481  *num_partitions_out = 0;
482  for( i = pcomms.begin(); i != pcomms.end(); ++i )
483  if( ( *i )->get_partitioning() ) ( *num_partitions_out )++;
484 
486 }
487 
489  iMeshP_PartitionHandle** partition_handle,
490  int* partition_handle_allocated,
491  int* partition_handle_size,
492  int* err )
493 {
494  std::vector< ParallelComm* > pcomms;
495  ErrorCode rval = ParallelComm::get_all_pcomm( MOABI, pcomms );CHKERR( rval, "Internal error retreiving PComms" );
496 
497  std::vector< ParallelComm* >::iterator i;
498  int count = 0;
499  for( i = pcomms.begin(); i != pcomms.end(); ++i )
500  if( ( *i )->get_partitioning() ) ++count;
501  ALLOC_CHECK_ARRAY_NOFAIL( partition_handle, count );
502 
503  *partition_handle_size = 0;
504  for( i = pcomms.begin(); i != pcomms.end(); ++i )
505  if( ( *i )->get_partitioning() )
506  ( *partition_handle )[( *partition_handle_size )++] =
507  itaps_cast< iMeshP_PartitionHandle >( ( *i )->get_partitioning() );
508 
510 }
511 
513  const iMeshP_PartitionHandle partition_handle,
514  int* num_global_part,
515  int* err )
516 {
517  ParallelComm* pcomm = PCOMM;
518  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
519 
520  ErrorCode rval = pcomm->get_global_part_count( *num_global_part );CHKERR( rval, "PComm::get_global_part_count failed" );
522 }
523 
525  const iMeshP_PartitionHandle partition_handle,
526  int* num_local_part,
527  int* err )
528 {
529  ParallelComm* pcomm = PCOMM;
530  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
531 
532  *num_local_part = pcomm->partition_sets().size();
534 }
535 
537  const iMeshP_PartitionHandle partition_handle,
538  iMeshP_PartHandle** part_handles,
539  int* part_handles_allocated,
540  int* part_handles_size,
541  int* err )
542 {
543  ParallelComm* pcomm = PCOMM;
544  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
545 
546  RANGE_TO_ITAPS_ARRAY( pcomm->partition_sets(), part_handles );
548 }
549 
551  const iMeshP_PartitionHandle partition_handle,
552  const iMeshP_Part part_id,
553  int* rank,
554  int* err )
555 {
556  int junk1 = 1, junk2 = 1;
557  iMeshP_getRankOfPartArr( instance, partition_handle, &part_id, 1, &rank, &junk1, &junk2, err );
558 }
559 
561  const iMeshP_PartitionHandle partition_handle,
562  const iMeshP_Part* part_ids,
563  const int part_ids_size,
564  int** rank,
565  int* rank_allocated,
566  int* rank_size,
567  int* err )
568 {
569  ParallelComm* pcomm = PCOMM;
570  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
571 
572  ALLOC_CHECK_ARRAY( rank, part_ids_size );
573  ErrorCode rval = MB_SUCCESS;
574  for( int i = 0; i < part_ids_size; ++i )
575  {
576  rval = pcomm->get_part_owner( part_ids[i], ( *rank )[i] );CHKERR( rval, "PComm::get_part_owner failed" );
577  }
578  KEEP_ARRAY( rank );
580 }
581 
583  const iMeshP_PartitionHandle partition_handle,
584  const iBase_EntitySetHandle entity_set_handle,
585  const int entity_type,
586  int* num_type,
587  int* err )
588 {
589  ParallelComm* pcomm = PCOMM;
590  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
591 
592  Range entities;
593  ErrorCode rval = get_entities( MOABI, itaps_cast< EntityHandle >( entity_set_handle ), entity_type,
595  int count = 0;
596  if( MB_SUCCESS == rval ) rval = count_owned( pcomm, entities, count );
597 
598  int vals[2] = { count, rval }, sums[2];
599  int ierr = MPI_Allreduce( vals, sums, 2, MPI_INT, MPI_SUM, pcomm->proc_config().proc_comm() );
600  assert( iBase_SUCCESS == 0 );
601  if( ierr || sums[1] ) RETURN( iBase_FAILURE );
602 
603  *num_type = sums[0];
605 }
606 
608  const iMeshP_PartitionHandle partition_handle,
609  const iBase_EntitySetHandle entity_set_handle,
610  const int entity_topology,
611  int* num_topo,
612  int* err )
613 {
614  ParallelComm* pcomm = PCOMM;
615  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
616 
617  Range entities;
618  ErrorCode rval = get_entities( MOABI, itaps_cast< EntityHandle >( entity_set_handle ), iBase_ALL_TYPES,
619  entity_topology, entities );
620  int count = 0;
621  if( MB_SUCCESS == rval ) rval = count_owned( pcomm, entities, count );
622 
623  int vals[2] = { count, rval }, sums[2];
624  int ierr = MPI_Allreduce( vals, sums, 2, MPI_INT, MPI_SUM, pcomm->proc_config().proc_comm() );
625  assert( iBase_SUCCESS == 0 );
626  if( ierr || sums[1] ) RETURN( iBase_FAILURE );
627 
628  *num_topo = sums[0];
630 }
631 
633  iMeshP_PartitionHandle partition_handle,
634  iMeshP_PartHandle* part_handle,
635  int* err )
636 {
637  ParallelComm* pcomm = PCOMM;
638  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
639 
640  EntityHandle h;
641  ErrorCode rval = pcomm->create_part( h );CHKERR( rval, "Part creation failed" );
642  *part_handle = itaps_cast< iMeshP_PartHandle >( h );
644 }
645 
647  iMeshP_PartitionHandle partition_handle,
648  iMeshP_PartHandle part_handle,
649  int* err )
650 {
651  ParallelComm* pcomm = PCOMM;
652  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
653 
654  ErrorCode rval = pcomm->destroy_part( itaps_cast< EntityHandle >( part_handle ) );CHKERR( rval, "Part destruction failed" );
656 }
657 
659  iMeshP_PartitionHandle partition_handle,
660  iMeshP_PartHandle part_handle,
661  int entity_type,
662  int* num_part_nbors,
663  int* err )
664 {
665  int junk1 = 1, junk2 = 1;
666  iMeshP_getNumPartNborsArr( instance, partition_handle, &part_handle, 1, entity_type, &num_part_nbors, &junk1,
667  &junk2, err );
668 }
669 
671  const iMeshP_PartitionHandle partition_handle,
672  const iMeshP_PartHandle* part_handles,
673  const int part_handles_size,
674  int /*entity_type*/,
675  int** num_part_nbors,
676  int* num_part_nbors_allocated,
677  int* num_part_nbors_size,
678  int* err )
679 {
680  ParallelComm* pcomm = PCOMM;
681  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
682 
683  ALLOC_CHECK_ARRAY( num_part_nbors, part_handles_size );
684 
686  ErrorCode rval;
687  for( int i = 0; i < part_handles_size; ++i )
688  {
689  EntityHandle h = itaps_cast< EntityHandle >( part_handles[i] );
690  rval = pcomm->get_part_neighbor_ids( h, neighbors, n );CHKERR( rval, "error getting neighbor ids" );
691  ( *num_part_nbors )[i] = n;
692  }
693 
694  KEEP_ARRAY( num_part_nbors );
696 }
697 
699  const iMeshP_PartitionHandle partition_handle,
700  const iMeshP_PartHandle part_handle,
701  int entity_type,
702  int* num_part_nbors,
703  iMeshP_Part** nbor_part_ids,
704  int* nbor_part_ids_allocated,
705  int* nbor_part_ids_size,
706  int* err )
707 {
708  int junk1 = 1, junk2 = 1;
709  iMeshP_getPartNborsArr( instance, partition_handle, &part_handle, 1, entity_type, &num_part_nbors, &junk1, &junk2,
710  nbor_part_ids, nbor_part_ids_allocated, nbor_part_ids_size, err );
711 }
712 
714  const iMeshP_PartitionHandle partition_handle,
715  const iMeshP_PartHandle* part_handles,
716  const int part_handles_size,
717  int /*entity_type*/,
718  int** num_part_nbors,
719  int* num_part_nbors_allocated,
720  int* num_part_nbors_size,
721  iMeshP_Part** nbor_part_ids,
722  int* nbor_part_ids_allocated,
723  int* nbor_part_ids_size,
724  int* err )
725 {
726  ParallelComm* pcomm = PCOMM;
727  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
728 
729  ALLOC_CHECK_ARRAY( num_part_nbors, part_handles_size );
730 
731  std::vector< int > all_neighbors;
732  int n, pnbor[MAX_SHARING_PROCS];
733  ErrorCode rval;
734  for( int i = 0; i < part_handles_size; ++i )
735  {
736  EntityHandle h = itaps_cast< EntityHandle >( part_handles[i] );
737  rval = pcomm->get_part_neighbor_ids( h, pnbor, n );CHKERR( rval, "error getting neighbor ids" );
738  ( *num_part_nbors )[i] = n;
739  std::copy( pnbor, pnbor + n, std::back_inserter( all_neighbors ) );
740  }
741 
742  ALLOC_CHECK_ARRAY_NOFAIL( nbor_part_ids, all_neighbors.size() );
743  memcpy( *nbor_part_ids, &all_neighbors[0], sizeof( int ) * all_neighbors.size() );
744 
745  KEEP_ARRAY( num_part_nbors );
747 }
748 
750  const iMeshP_PartitionHandle partition_handle,
751  const iMeshP_PartHandle part_handle,
752  const int entity_type,
753  const int entity_topology,
754  const iMeshP_Part target_part_id,
755  int* num_entities,
756  int* err )
757 {
758  Range entities;
759  ErrorCode rval = get_boundary_entities( PCOMM, itaps_cast< EntityHandle >( part_handle ), entity_type,
760  entity_topology, target_part_id, entities );CHKERR( rval, "failed to get boundary entities" );
761  *num_entities = entities.size();
763 }
764 
766  const iMeshP_PartitionHandle partition_handle,
767  const iMeshP_PartHandle part_handle,
768  const int entity_type,
769  const int entity_topology,
770  const iMeshP_Part target_part_id,
771  iBase_EntityHandle** entity_handles,
772  int* entity_handles_allocated,
773  int* entity_handles_size,
774  int* err )
775 {
776  Range entities;
777  ErrorCode rval = get_boundary_entities( PCOMM, itaps_cast< EntityHandle >( part_handle ), entity_type,
778  entity_topology, target_part_id, entities );CHKERR( rval, "failed to get boundary entities" );
779  RANGE_TO_ITAPS_ARRAY( entities, entity_handles );
781 }
782 
784  const iMeshP_PartitionHandle partition_handle,
785  const iMeshP_PartHandle part_handle,
786  const int entity_type,
787  const int entity_topology,
788  const iMeshP_Part nbor_part_id,
789  iBase_EntityIterator* entity_iterator,
790  int* err )
791 {
792  iMeshP_initPartBdryEntArrIter( instance, partition_handle, part_handle, entity_type, entity_topology, 1,
793  nbor_part_id, reinterpret_cast< iBase_EntityArrIterator* >( entity_iterator ), err );
794 }
795 
797  const iMeshP_PartitionHandle partition_handle,
798  const iMeshP_PartHandle part_handle,
799  const int entity_type,
800  const int entity_topology,
801  const int array_size,
802  const iMeshP_Part nbor_part_id,
803  iBase_EntityArrIterator* entity_iterator,
804  int* err )
805 {
806  *entity_iterator =
807  new PartBoundaryIter( PCOMM, itaps_cast< EntityHandle >( part_handle ), (iBase_EntityType)entity_type,
808  (iMesh_EntityTopology)entity_topology, nbor_part_id, array_size );
809  ErrorCode result = ( *entity_iterator )->reset( MOABI );
810  if( MB_SUCCESS != result ) delete *entity_iterator;CHKERR( result, "iMesh_initEntArrIter: ERROR getting entities of proper type or topology." );
812 }
813 
816  const iMeshP_PartHandle part_handle,
817  const iBase_EntitySetHandle entity_set_handle,
818  const int entity_type,
819  int* num_type,
820  int* err )
821 {
822  Range r;
823  set_intersection_query( instance, part_handle, entity_set_handle, entity_type, iMesh_ALL_TOPOLOGIES, r, err );
824  *num_type = r.size();
825 }
826 
828  const iMeshP_PartitionHandle /*partition_handle*/,
829  const iMeshP_PartHandle part_handle,
830  const iBase_EntitySetHandle entity_set_handle,
831  const int entity_topology,
832  int* num_topo,
833  int* err )
834 {
835  Range r;
836  set_intersection_query( instance, part_handle, entity_set_handle, iBase_ALL_TYPES, entity_topology, r, err );
837  *num_topo = r.size();
838 }
839 
841  iMeshP_PartitionHandle partition,
842  iMeshP_PartHandle part,
843  iBase_EntitySetHandle entity_set_handle,
844  int entity_type_requestor,
845  int entity_topology_requestor,
846  int entity_type_requested,
847  iBase_EntityHandle** entity_handles,
848  int* entity_handles_allocated,
849  int* entity_handles_size,
850  iBase_EntityHandle** adj_entity_handles,
851  int* adj_entity_handles_allocated,
852  int* adj_entity_handles_size,
853  int** adj_entity_indices,
854  int* adj_entity_indices_allocated,
855  int* adj_entity_indices_size,
856  int** offset,
857  int* offset_allocated,
858  int* offset_size,
859  int* err )
860 {
861  const int allocated_entity_handles = ( *entity_handles_allocated == 0 );
862  const int allocated_indices = ( *adj_entity_indices_allocated == 0 );
863  const int allocated_offset = ( *offset_allocated == 0 );
864 
865  // get source entities
866  iMeshP_getEntities( instance, partition, part, entity_set_handle, entity_type_requestor, entity_topology_requestor,
867  entity_handles, entity_handles_allocated, entity_handles_size, err );
868  if( iBase_SUCCESS != *err ) return;
869 
870  // get adjacencies
871  iBase_EntityHandle* all_adj_handles = 0;
872  int size = 0, alloc = 0;
873  iMesh_getEntArrAdj( instance, *entity_handles, *entity_handles_size, entity_type_requested, &all_adj_handles,
874  &alloc, &size, offset, offset_allocated, offset_size, err );
875  if( *err != iBase_SUCCESS )
876  {
877  if( allocated_entity_handles )
878  {
879  free( *entity_handles );
880  *entity_handles = 0;
881  *entity_handles_allocated = 0;
882  }
883  return;
884  }
885 
886  // allocate or check size of adj_entity_indices
887  *adj_entity_indices_size = size;
888  if( allocated_indices )
889  {
890  *adj_entity_indices = (int*)malloc( sizeof( iBase_EntityHandle ) * size );
891  if( !*adj_entity_indices )
893  else
894  *adj_entity_indices_allocated = size;
895  }
896  else if( *adj_entity_indices_allocated < size )
897  {
899  }
900  if( iBase_SUCCESS != *err )
901  {
902  free( all_adj_handles );
903  if( allocated_entity_handles )
904  {
905  free( *entity_handles );
906  *entity_handles = 0;
907  *entity_handles_allocated = 0;
908  }
909  if( allocated_offset )
910  {
911  free( *offset );
912  *offset = 0;
913  *offset_allocated = 0;
914  }
915  return;
916  }
917 
918  // Now create an array of unique sorted handles from all_adj_handles.
919  // We need to create a copy because we still need all_adj_handles. We
920  // will eventually need to copy the resulting unique list into
921  // adj_entity_handles, so if adj_entity_handles is already allocated and
922  // of sufficient size, use it rather than allocating another temporary.
923  iBase_EntityHandle* unique_adj = 0;
924  if( *adj_entity_handles_allocated >= size )
925  {
926  unique_adj = *adj_entity_handles;
927  }
928  else
929  {
930  unique_adj = (iBase_EntityHandle*)malloc( sizeof( iBase_EntityHandle ) * size );
931  }
932  std::copy( all_adj_handles, all_adj_handles + size, unique_adj );
933  std::sort( unique_adj, unique_adj + size );
934  *adj_entity_handles_size = std::unique( unique_adj, unique_adj + size ) - unique_adj;
935 
936  // If we created a temporary array for unique_adj rather than using
937  // already allocated space in adj_entity_handles, allocate adj_entity_handles
938  // and copy the unique handle list into it
939  if( *adj_entity_handles != unique_adj )
940  {
941  if( !*adj_entity_handles_allocated )
942  {
943  *adj_entity_handles =
944  (iBase_EntityHandle*)malloc( sizeof( iBase_EntityHandle ) * *adj_entity_handles_size );
945  if( !*adj_entity_handles )
947  else
948  *adj_entity_handles_allocated = *adj_entity_handles_size;
949  }
950  else if( *adj_entity_handles_allocated < *adj_entity_handles_size )
952  if( iBase_SUCCESS != *err )
953  {
954  free( unique_adj );
955  free( all_adj_handles );
956  if( allocated_entity_handles )
957  {
958  free( *entity_handles );
959  *entity_handles = 0;
960  *entity_handles_allocated = 0;
961  }
962  if( allocated_offset )
963  {
964  free( *offset );
965  *offset = 0;
966  *offset_allocated = 0;
967  }
968  if( allocated_indices )
969  {
970  free( *adj_entity_indices );
971  *adj_entity_indices = 0;
972  *adj_entity_indices_allocated = 0;
973  }
974  return;
975  }
976 
977  std::copy( unique_adj, unique_adj + *adj_entity_handles_size, *adj_entity_handles );
978  free( unique_adj );
979  unique_adj = *adj_entity_handles;
980  }
981 
982  // convert from adjacency list to indices into unique_adj
983  for( int i = 0; i < *adj_entity_indices_size; ++i )
984  ( *adj_entity_indices )[i] =
985  std::lower_bound( unique_adj, unique_adj + *adj_entity_handles_size, all_adj_handles[i] ) - unique_adj;
986  free( all_adj_handles );
987 }
988 
991  const iMeshP_PartHandle part_handle,
992  const iBase_EntitySetHandle entity_set_handle,
993  const int entity_type,
994  const int entity_topology,
995  iBase_EntityHandle** entity_handles,
996  int* entity_handles_allocated,
997  int* entity_handles_size,
998  int* err )
999 {
1000  Range r;
1001  set_intersection_query( instance, part_handle, entity_set_handle, entity_type, entity_topology, r, err );
1002  if( iBase_SUCCESS != *err ) return;
1003 
1004  RANGE_TO_ITAPS_ARRAY( r, entity_handles );
1005  RETURN( iBase_SUCCESS );
1006 }
1007 
1009  const iMeshP_PartitionHandle /*partition_handle*/,
1010  const iMeshP_PartHandle part_handle,
1011  const iBase_EntitySetHandle entity_set_handle,
1012  const int entity_type_requestor,
1013  const int entity_topology_requestor,
1014  const int entity_type_requested,
1015  iBase_EntityHandle** adj_entity_handles,
1016  int* adj_entity_handles_allocated,
1017  int* adj_entity_handles_size,
1018  int** offset,
1019  int* offset_allocated,
1020  int* offset_size,
1021  int** in_entity_set,
1022  int* in_entity_set_allocated,
1023  int* in_entity_set_size,
1024  int* err )
1025 {
1026  ErrorCode rval;
1027  Range r;
1028  set_intersection_query( instance, part_handle, entity_set_handle, entity_type_requestor, entity_topology_requestor,
1029  r, err );
1030  if( iBase_SUCCESS != *err ) return;
1031 
1032  // count adjacencies
1033  std::vector< EntityHandle > tmp_storage;
1034  int num_adj = 0;
1035  int num_conn;
1036  const EntityHandle* conn_ptr;
1037  for( Range::iterator i = r.begin(); i != r.end(); ++i )
1038  {
1039  if( entity_type_requested || TYPE_FROM_HANDLE( *i ) == MBPOLYHEDRON )
1040  {
1041  tmp_storage.clear();
1042  rval = MOABI->get_adjacencies( &*i, 1, entity_type_requested, false, tmp_storage );CHKERR( rval, "get_adjacencies failed" );
1043  num_adj += tmp_storage.size();
1044  }
1045  else
1046  {
1047  rval = MOABI->get_connectivity( *i, conn_ptr, num_conn, false, &tmp_storage );CHKERR( rval, "get_connectivity failed" );
1048  num_adj += num_conn;
1049  }
1050  }
1051 
1052  // get adjacencies
1053  ALLOC_CHECK_ARRAY( adj_entity_handles, num_adj );
1054  ALLOC_CHECK_ARRAY( offset, r.size() );
1055  int arr_pos = 0;
1056  int* offset_iter = *offset;
1057  for( Range::iterator i = r.begin(); i != r.end(); ++i )
1058  {
1059  *offset_iter = arr_pos;
1060  ++offset_iter;
1061 
1062  tmp_storage.clear();
1063  rval = MOABI->get_adjacencies( &*i, 1, entity_type_requested, false, tmp_storage );CHKERR( rval, "get_adjacencies failed" );
1064  for( std::vector< EntityHandle >::iterator j = tmp_storage.begin(); j != tmp_storage.end(); ++j )
1065  {
1066  ( *adj_entity_handles )[arr_pos] = itaps_cast< iBase_EntityHandle >( *j );
1067  ++arr_pos;
1068  }
1069  }
1070 
1071  // get in_entity_set
1072  iMesh_isEntArrContained( instance, entity_set_handle, *adj_entity_handles, *adj_entity_handles_size, in_entity_set,
1073  in_entity_set_allocated, in_entity_set_size, err );
1074 
1075  if( iBase_SUCCESS == *err )
1076  {
1077  KEEP_ARRAY( adj_entity_handles );
1078  KEEP_ARRAY( offset );
1079  }
1080 }
1081 
1083  const iMeshP_PartitionHandle partition_handle,
1084  const iMeshP_PartHandle part_handle,
1085  const iBase_EntitySetHandle entity_set_handle,
1086  const int requested_entity_type,
1087  const int requested_entity_topology,
1088  iBase_EntityIterator* entity_iterator,
1089  int* err )
1090 {
1091  iMeshP_initEntArrIter( instance, partition_handle, part_handle, entity_set_handle, requested_entity_type,
1092  requested_entity_topology, 1,
1093  reinterpret_cast< iBase_EntityArrIterator* >( entity_iterator ), err );
1094 }
1095 
1097  const iMeshP_PartitionHandle /*partition_handle*/,
1098  const iMeshP_PartHandle part_handle,
1099  const iBase_EntitySetHandle entity_set_handle,
1100  const int requested_entity_type,
1101  const int requested_entity_topology,
1102  const int requested_array_size,
1103  iBase_EntityArrIterator* entArr_iterator,
1104  int* err )
1105 {
1106  if( !entity_set_handle || entity_set_handle == part_handle )
1107  {
1108  iMesh_initEntArrIter( instance, part_handle, requested_entity_type, requested_entity_topology,
1109  requested_array_size,
1110  0, // TODO: update this function for "resilient" arg
1111  entArr_iterator, err );
1112  }
1113  else
1114  {
1115  unsigned flags;
1116  ErrorCode result = MOABI->get_meshset_options( itaps_cast< EntityHandle >( entity_set_handle ), flags );CHKERR( result, "Invalid entity set handle" );
1117  if( flags & MESHSET_ORDERED )
1118  *entArr_iterator = new SetIntersectIter< std::vector< EntityHandle > >(
1119  (iBase_EntityType)requested_entity_type, (iMesh_EntityTopology)requested_entity_topology,
1120  itaps_cast< EntityHandle >( entity_set_handle ), itaps_cast< EntityHandle >( part_handle ),
1121  requested_array_size );
1122  else
1123  *entArr_iterator =
1124  new SetIntersectIter< Range >( (iBase_EntityType)requested_entity_type,
1125  (iMesh_EntityTopology)requested_entity_topology,
1126  itaps_cast< EntityHandle >( entity_set_handle ),
1127  itaps_cast< EntityHandle >( part_handle ), requested_array_size );
1128  result = ( *entArr_iterator )->reset( MOABI );
1129  if( MB_SUCCESS != result ) delete *entArr_iterator;CHKERR( result, "iMesh_initEntArrIter: ERROR getting entities of proper type or topology." );
1130  RETURN( iBase_SUCCESS );
1131  }
1132 }
1133 
1135  const iMeshP_PartitionHandle partition_handle,
1136  const iBase_EntityHandle entity_handle,
1137  iMeshP_Part* part_id,
1138  int* err )
1139 {
1140  int junk1 = 1, junk2 = 1;
1141  iMeshP_getEntOwnerPartArr( instance, partition_handle, &entity_handle, 1, &part_id, &junk1, &junk2, err );
1142 }
1143 
1145  const iMeshP_PartitionHandle partition_handle,
1146  const iBase_EntityHandle* entity_handles,
1147  const int entity_handles_size,
1148  iMeshP_Part** part_ids,
1149  int* part_ids_allocated,
1150  int* part_ids_size,
1151  int* err )
1152 {
1153  ParallelComm* pcomm = PCOMM;
1154  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1155 
1156  int id;
1157  ALLOC_CHECK_ARRAY( part_ids, entity_handles_size );
1158  ErrorCode rval = MB_SUCCESS;
1159  for( int i = 0; i < entity_handles_size; ++i )
1160  {
1161  EntityHandle h = itaps_cast< EntityHandle >( entity_handles[i] );
1162  rval = pcomm->get_owning_part( h, id );
1163  ( *part_ids )[i] = id;CHKERR( rval, "Failet get part owner" );
1164  }
1165  KEEP_ARRAY( part_ids );
1166  RETURN( iBase_SUCCESS );
1167 }
1168 
1170  const iMeshP_PartitionHandle partition_handle,
1171  const iMeshP_PartHandle part_handle,
1172  const iBase_EntityHandle entity_handle,
1173  int* is_owner,
1174  int* err )
1175 {
1176  int junk1 = 1, junk2 = 1;
1177  iMeshP_isEntOwnerArr( instance, partition_handle, part_handle, &entity_handle, 1, &is_owner, &junk1, &junk2, err );
1178 }
1179 
1181  const iMeshP_PartitionHandle partition_handle,
1182  const iMeshP_PartHandle part_handle,
1183  const iBase_EntityHandle* entity_handles,
1184  const int entity_handles_size,
1185  int** is_owner,
1186  int* is_owner_allocated,
1187  int* is_owner_size,
1188  int* err )
1189 {
1190  ErrorCode rval;
1191  ParallelComm* pcomm = PCOMM;
1192  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1193 
1194  int id;
1195  rval = pcomm->get_part_id( itaps_cast< EntityHandle >( part_handle ), id );CHKERR( rval, "error getting part id" );
1196 
1197  ALLOC_CHECK_ARRAY( is_owner, entity_handles_size );
1198  *is_owner_size = entity_handles_size;
1199 
1200  int owner;
1201  for( int i = 0; i < entity_handles_size; ++i )
1202  {
1203  rval = pcomm->get_owner( itaps_cast< EntityHandle >( entity_handles[i] ), owner );CHKERR( rval, "error getting owner" );
1204  ( *is_owner )[i] = ( owner == id );
1205  }
1206 
1207  KEEP_ARRAY( is_owner );
1208  RETURN( iBase_SUCCESS );
1209 }
1210 
1212  /*in*/ const iMeshP_PartitionHandle partition_handle,
1213  /*in*/ const iMeshP_PartHandle part_handle,
1214  /*in*/ const iBase_EntityHandle entity_handle,
1215  /*out*/ int* par_status, // Values=INTERNAL,BOUNDARY,GHOST
1216  int* err )
1217 {
1218  int junk1 = 1, junk2 = 1;
1219  iMeshP_getEntStatusArr( instance, partition_handle, part_handle, &entity_handle, 1, &par_status, &junk1, &junk2,
1220  err );
1221 }
1222 
1224  /*in*/ const iMeshP_PartitionHandle partition_handle,
1225  /*in*/ const iMeshP_PartHandle /*part_handle*/,
1226  /*in*/ const iBase_EntityHandle* entity_handles,
1227  /*in*/ const int entity_handles_size,
1228  /*inout*/ int** par_status, // Values=INTERNAL,BOUNDARY,GHOST
1229  /*inout*/ int* par_status_allocated,
1230  /*inout*/ int* par_status_size,
1231  int* err )
1232 {
1233  ParallelComm* pcomm = PCOMM;
1234  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1235 
1236  std::vector< unsigned char > pstatus( entity_handles_size );
1237  ErrorCode result = MOABI->tag_get_data( pcomm->pstatus_tag(), itaps_cast< const EntityHandle* >( entity_handles ),
1238  entity_handles_size, &pstatus[0] );CHKERR( result, "error getting pstatus_tag" );
1239 
1240  ALLOC_CHECK_ARRAY( par_status, entity_handles_size );
1241  for( int i = 0; i < entity_handles_size; i++ )
1242  {
1243  if( !pstatus[i] )
1244  ( *par_status )[i] = iMeshP_INTERNAL;
1245  else if( pstatus[i] & PSTATUS_GHOST )
1246  ( *par_status )[i] = iMeshP_GHOST;
1247  else if( pstatus[i] & PSTATUS_INTERFACE )
1248  ( *par_status )[i] = iMeshP_BOUNDARY;
1249  }
1250 
1251  KEEP_ARRAY( par_status );
1252  RETURN( iBase_SUCCESS );
1253 }
1254 
1256  const iMeshP_PartitionHandle partition_handle,
1257  const iBase_EntityHandle entity_handle,
1258  int* num_copies_ent,
1259  int* err )
1260 {
1261  ParallelComm* pcomm = PCOMM;
1262  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1263 
1264  int ids[MAX_SHARING_PROCS];
1265  ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, *num_copies_ent );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
1266  RETURN( iBase_SUCCESS );
1267 }
1268 
1270  const iMeshP_PartitionHandle partition_handle,
1271  const iBase_EntityHandle entity_handle,
1272  iMeshP_Part** part_ids,
1273  int* part_ids_allocated,
1274  int* part_ids_size,
1275  int* err )
1276 {
1277  ParallelComm* pcomm = PCOMM;
1278  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1279 
1280  int ids[MAX_SHARING_PROCS], num_ids;
1281  ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, num_ids );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
1282  ALLOC_CHECK_ARRAY_NOFAIL( part_ids, num_ids );
1283  std::copy( ids, ids + num_ids, *part_ids );
1284  RETURN( iBase_SUCCESS );
1285 }
1286 
1288  const iMeshP_PartitionHandle partition_handle,
1289  const iBase_EntityHandle entity_handle,
1290  iMeshP_Part** part_ids,
1291  int* part_ids_allocated,
1292  int* part_ids_size,
1293  iBase_EntityHandle** copies_entity_handles,
1294  int* copies_entity_handles_allocated,
1295  int* copies_entity_handles_size,
1296  int* err )
1297 {
1298  ParallelComm* pcomm = PCOMM;
1299  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1300 
1301  int ids[MAX_SHARING_PROCS], num_ids;
1303  ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, num_ids, handles );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
1304  ALLOC_CHECK_ARRAY_NOFAIL( part_ids, num_ids );
1305  ALLOC_CHECK_ARRAY_NOFAIL( copies_entity_handles, num_ids );
1306  for( int i = 0; i < num_ids; ++i )
1307  {
1308  ( *part_ids )[i] = ids[i];
1309  ( *copies_entity_handles )[i] = itaps_cast< iBase_EntityHandle >( handles[i] );
1310  }
1311  RETURN( iBase_SUCCESS );
1312 }
1313 
1315  const iMeshP_PartitionHandle partition_handle,
1316  const iBase_EntityHandle entity_handle,
1317  const iMeshP_Part part_id,
1318  iBase_EntityHandle* copy_entity_handle,
1319  int* err )
1320 {
1321  ParallelComm* pcomm = PCOMM;
1322  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1323 
1324  int ids[MAX_SHARING_PROCS], num_ids;
1326  ErrorCode rval = pcomm->get_sharing_parts( itaps_cast< EntityHandle >( entity_handle ), ids, num_ids, handles );CHKERR( rval, "ParallelComm::get_sharing_parts failed" );
1327  int idx = std::find( ids, ids + num_ids, part_id ) - ids;
1328  if( idx == num_ids ) RETURN( iBase_FAILURE );
1329 
1330  *copy_entity_handle = itaps_cast< iBase_EntityHandle >( handles[idx] );
1331  RETURN( iBase_SUCCESS );
1332 }
1333 
1335  const iMeshP_PartitionHandle partition_handle,
1336  const iBase_EntityHandle entity_handle,
1337  iMeshP_Part* owner_part_id,
1338  iBase_EntityHandle* owner_entity_handle,
1339  int* err )
1340 {
1341  ParallelComm* pcomm = PCOMM;
1342  if( !pcomm ) ERROR( iBase_FAILURE, "No PComm" );
1343 
1344  int id;
1345  EntityHandle h;
1346  ErrorCode rval = pcomm->get_owning_part( itaps_cast< EntityHandle >( entity_handle ), id, &h );CHKERR( rval, "Failed to get owner" );
1347  *owner_part_id = id;
1348  *owner_entity_handle = itaps_cast< iBase_EntityHandle >( h );
1349  RETURN( iBase_SUCCESS );
1350 }
1351 
1355  int,
1356  int*,
1357  int* err )
1358 {
1359  FIXME;
1361 }
1362 
1364 {
1365  FIXME;
1367 }
1368 
1370  const iMeshP_PartitionHandle,
1373  int*,
1374  int*,
1375  int* err )
1376 {
1377  FIXME;
1379 }
1380 
1382 {
1383  FIXME;
1385 }
1386 
1390  int*,
1391  int*,
1392  int* err )
1393 {
1394  FIXME;
1396 }
1397 
1399  const iMeshP_PartitionHandle partition_handle,
1400  const iBase_EntityHandle* entity_handles,
1401  const int entity_handles_size,
1402  const iMeshP_Part* target_part_ids,
1403  int command_code,
1404  int update_ghost,
1405  iMeshP_RequestHandle* /*request*/,
1406  int* err )
1407 {
1408  if( command_code == 1 )
1409  {
1410  std::cerr << "Entity migration option is not supported." << std::endl;
1412  }
1413 
1414  if( update_ghost == 1 )
1415  {
1416  std::cerr << "Gost update option is not supported." << std::endl;
1418  }
1419 
1420  // make exchange entity and processor list
1421  ErrorCode rval;
1422  ParallelComm* pcomm = PCOMM;
1423  std::vector< unsigned int > exchange_procs;
1424  std::vector< Range* > exchange_ents;
1425 
1426  for( int i = 0; i < entity_handles_size; i++ )
1427  {
1428  int ind = -1;
1429  // iMeshP_Part target_p = target_part_ids[i];
1430  int target_p;
1431  rval = pcomm->get_part_owner( target_part_ids[i], target_p );CHKERR( rval, "ParallelComm::get_part_owner failed" );
1432 
1433  std::vector< unsigned int >::iterator vit = std::find( exchange_procs.begin(), exchange_procs.end(), target_p );
1434  if( vit == exchange_procs.end() )
1435  {
1436  ind = exchange_procs.size();
1437  exchange_procs.push_back( target_p );
1438  exchange_ents.push_back( new Range );
1439  }
1440  else
1441  ind = vit - exchange_procs.begin();
1442 
1443  exchange_ents[ind]->insert( itaps_cast< EntityHandle >( entity_handles[i] ) );
1444  }
1445 
1446  std::vector< MPI_Request > recv_ent_reqs, recv_remoteh_reqs;
1447  rval = pcomm->exchange_owned_meshs( exchange_procs, exchange_ents, recv_ent_reqs, recv_remoteh_reqs, true );CHKERR( rval, "ParallelComm::exchange_owned_meshs failed" );
1448 
1449  // delete exchange list
1450  std::vector< Range* >::iterator vit;
1451  for( vit = exchange_ents.begin(); vit != exchange_ents.end(); ++vit )
1452  delete( *vit );
1453 
1454  RETURN( iBase_SUCCESS );
1455 }
1456 
1458  const iMeshP_PartitionHandle,
1459  const iMeshP_PartHandle,
1460  const iBase_EntityHandle,
1462  int* err )
1463 {
1464  FIXME;
1466 }
1467 
1469 {
1470  FIXME;
1472 }
1473 
1475  const iMeshP_PartitionHandle,
1476  const iBase_EntityHandle*,
1477  const int,
1478  const iBase_EntityHandle*,
1479  const int,
1480  const int*,
1481  const int,
1482  int* err )
1483 {
1484  FIXME;
1486 }
1487 
1489  const iMeshP_PartitionHandle,
1490  const iMeshP_Part,
1491  const iBase_EntityHandle,
1493  int* err )
1494 {
1495  FIXME;
1497 }
1498 
1500  const iMeshP_PartitionHandle,
1501  const iMeshP_Part,
1502  const iBase_EntityHandle,
1503  int* err )
1504 {
1505  FIXME;
1507 }
1508 
1509 void iMeshP_syncMeshAll( iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, int* err )
1510 {
1511  ParallelComm* pcomm = PCOMM;
1512  ErrorCode rval = pcomm->resolve_shared_ents( itaps_cast< EntityHandle >( partition_handle ), -1, -1 );CHKERR( rval, "update failed" );
1513  RETURN( iBase_SUCCESS );
1514 }
1515 
1517  const iMeshP_PartitionHandle partition_handle,
1518  iBase_TagHandle source_tag,
1519  iBase_TagHandle dest_tag,
1520  int entity_type,
1521  int entity_topo,
1522  int* err )
1523 {
1524  ParallelComm* pcomm = PCOMM;
1525  DimensionPair types;
1526  if( entity_topo != iMesh_ALL_TOPOLOGIES )
1527  types.first = types.second = mb_topology_table[entity_topo];
1528  else if( entity_type != iBase_ALL_TYPES )
1529  // types = CN::TypeDimensionMap[entity_type];
1530  types = CN::getDimPair( entity_type );
1531  else
1532  {
1533  types.first = MBVERTEX;
1534  types.second = MBENTITYSET;
1535  --types.second;
1536  }
1537 
1538  std::vector< Tag > src_tags( 1, itaps_cast< Tag >( source_tag ) );
1539  std::vector< Tag > dst_tags( 1, itaps_cast< Tag >( dest_tag ) );
1540 
1541  ErrorCode rval;
1542  Range entities;
1543  for( EntityType t = types.first; t <= types.second; ++t )
1544  {
1545  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" );
1546  }
1547 
1548  rval = pcomm->exchange_tags( src_tags, dst_tags, entities );CHKERR( rval, "tag data communication failed" );
1549  RETURN( iBase_SUCCESS );
1550 }
1551 
1553  const iMeshP_PartitionHandle partition_handle,
1554  iBase_TagHandle source_tag,
1555  iBase_TagHandle dest_tag,
1557  int entities_size,
1558  int* err )
1559 {
1560 
1561  Range range;
1562  const EntityHandle* ents = itaps_cast< const EntityHandle* >( entities );
1563  std::copy( ents, ents + entities_size, range_inserter( range ) );
1564 
1565  std::vector< Tag > src_tags( 1, itaps_cast< Tag >( source_tag ) );
1566  std::vector< Tag > dst_tags( 1, itaps_cast< Tag >( dest_tag ) );
1567  ParallelComm* pcomm = PCOMM;
1568  ErrorCode rval = pcomm->exchange_tags( src_tags, dst_tags, range );CHKERR( rval, "tag data communication failed" );
1569  RETURN( iBase_SUCCESS );
1570 }
1571 
1573  const iMeshP_PartitionHandle,
1576  int,
1577  int,
1579  int* err )
1580 {
1581  FIXME;
1583 }
1584 
1586  const iMeshP_PartitionHandle,
1589  const iBase_EntityHandle*,
1590  int,
1592  int* err )
1593 {
1594  FIXME;
1596 }
1597 
1599  iMeshP_PartitionHandle partition_handle,
1600  int ghost_dim,
1601  int bridge_dim,
1602  int num_layers,
1603  int include_copies,
1604  int* err )
1605 {
1606  if( include_copies )
1607  {
1608  FIXME;
1610  }
1611 
1612  ParallelComm* pcomm = PCOMM;
1613  ErrorCode rval;
1614  if( iBase_ALL_TYPES == ghost_dim ) ghost_dim = -1;
1615  rval = pcomm->exchange_ghost_cells( ghost_dim, bridge_dim, num_layers, 0, true );CHKERR( rval, "ghost exchange failed" );
1616  RETURN( iBase_SUCCESS );
1617 }
1618 
1620 {
1621  FIXME;
1623 }
1624 
1626  const iMeshP_PartitionHandle,
1627  int*,
1628  int*,
1629  int**,
1630  int**,
1631  int**,
1632  int* err )
1633 {
1634  FIXME;
1636 }
1637 
1638 // append the specified option if it isn't already there; returns whether this
1639 // function actually appended it or not
1640 static bool append_option( std::string& opt, const char* option, const char* default_value = 0 )
1641 {
1642  std::string::size_type i;
1643 
1644  const char sep = ' ';
1645 
1646  if( strchr( option, sep ) || ( default_value && strchr( default_value, sep ) ) )
1647  {
1648  // options can't have a separator in them; XXX work around this
1649  return false; // iBase_INVALID_ARGUMENT;
1650  }
1651 
1652  // search for the required option
1653  std::string search( &sep, 1 );
1654  search += option;
1655  const std::string::size_type sl = search.length();
1656  i = opt.find( search );
1657  while( i != std::string::npos )
1658  {
1659  std::string::size_type end = i + sl;
1660  if( end == opt.size() || opt[end] == sep || opt[end] == '=' ) break;
1661  i = end;
1662  }
1663 
1664  // if string already contained the option, just return
1665  if( i != std::string::npos ) return false;
1666 
1667  opt += search;
1668  if( default_value )
1669  {
1670  opt += "=";
1671  opt += default_value;
1672  }
1673 
1674  return true;
1675 }
1676 
1678  const iMeshP_PartitionHandle partition,
1679  const iBase_EntitySetHandle entity_set_handle,
1680  const char* name,
1681  const char* options,
1682  int* err,
1683  int name_len,
1684  int options_len )
1685 {
1686  ErrorCode rval;
1687 
1688  // create partition set if user didn't give us one.
1689  EntityHandle partitioning;
1690  if( partition )
1691  {
1692  partitioning = itaps_cast< EntityHandle >( partition );
1693  }
1694  else
1695  {
1696  rval = MOABI->create_meshset( MESHSET_SET, partitioning );CHKERR( rval, "failed to create meshset" );
1697  }
1698 
1699  // get ParallelComm for partition
1700  MPI_Comm default_comm = MPI_COMM_WORLD;
1701  ParallelComm* pcomm = ParallelComm::get_pcomm( MOABI, partitioning, &default_comm );
1702  if( !pcomm )
1703  {
1704  RETURN( iBase_FAILURE );
1705  }
1706 
1707  // add necessary values to options string
1708  std::string opt = std::string( options, options + options_len );
1709 
1710  if( append_option( opt, "moab:PARALLEL" ) )
1711  {
1712  // only append these other ones if the parallel option wasn't there originally
1713  append_option( opt, "moab:PARTITION_DISTRIBUTE" );
1714  append_option( opt, "moab:PARALLEL_RESOLVE_SHARED_ENTS" );
1715  std::ostringstream id;
1716  id << pcomm->get_id();
1717  append_option( opt, "moab:PCOMM", id.str().c_str() );
1718  }
1719 
1720  // load the file
1721  iMesh_load( instance, entity_set_handle, name, opt.c_str(), err, name_len, opt.length() );
1722  if( *err ) return;
1723 
1724  rval = pcomm->collective_sync_partition();CHKERR( rval, "collective sync failed" );
1725  RETURN( iBase_SUCCESS );
1726 }
1727 
1729  const iMeshP_PartitionHandle partition,
1730  const iBase_EntitySetHandle entity_set_handle,
1731  const char* name,
1732  const char* options,
1733  int* err,
1734  const int name_len,
1735  int options_len )
1736 {
1737  EntityHandle set;
1738  set = entity_set_handle ? itaps_cast< EntityHandle >( entity_set_handle ) : itaps_cast< EntityHandle >( partition );
1739  iMesh_save( instance, itaps_cast< iBase_EntitySetHandle >( set ), name, options, err, name_len, options_len );
1740 }
1741 
1742 // Map from processes to parts:
1743 // Given a partition handle and a process rank,
1744 // return the part handles owned by the process.
1745 // COMMUNICATION: None++.
1747  const iMeshP_PartitionHandle partition_handle,
1748  /*in*/ const int /*rank*/,
1749  /*inout*/ iMeshP_PartHandle** part_handles,
1750  /*inout*/ int* part_handles_allocated,
1751  /*out*/ int* part_handles_size,
1752  int* err )
1753 {
1754  EntityHandle p = itaps_cast< EntityHandle >( partition_handle );
1756  if( !pc ) RETURN( iBase_ERROR_MAP[MB_FAILURE] );
1757 
1758  Range part_sets;
1759 
1760  ALLOC_CHECK_ARRAY_NOFAIL( part_handles, pc->partition_sets().size() );
1761  Range::iterator rit;
1762  int i;
1763  for( i = 0, rit = pc->partition_sets().begin(); rit != pc->partition_sets().end(); ++rit, i++ )
1764  ( *part_handles )[i] = itaps_cast< iMeshP_PartHandle >( *rit );
1765 
1766  RETURN( iBase_SUCCESS );
1767 }
1768 
1770  const iMeshP_PartitionHandle partition_handle,
1771  /*in*/ const int* rank,
1772  /*in*/ const int rank_size,
1773  /*inout*/ iMeshP_PartHandle** part_handles,
1774  /*inout*/ int* part_handles_allocated,
1775  /*out*/ int* part_handles_size,
1776  int* err )
1777 {
1778  EntityHandle p = itaps_cast< EntityHandle >( partition_handle );
1780  if( !pc ) RETURN( iBase_ERROR_MAP[MB_FAILURE] );
1781 
1782  if( rank[0] != (int)pc->proc_config().proc_rank() || rank_size > 1 )
1783  {
1785  }
1786 
1787  iMeshP_getPartsOnRank( instance, partition_handle, rank[0], part_handles, part_handles_allocated, part_handles_size,
1788  err );
1789 }
1790 
1791 /** \brief Assign a global id space to entities
1792  * Assign a global id space to entities and vertices, and optionally intermediate-dimension entities
1793  *
1794  * COMMUNICATION: Collective.
1795  */
1797  const iMeshP_PartitionHandle partition,
1798  const iBase_EntitySetHandle this_set,
1799  const int dimension,
1800  const int start_id,
1801  const int largest_dim_only,
1802  const int parallel,
1803  const int owned_only,
1804  int* err )
1805 {
1806  ErrorCode rval;
1807 
1808  // get partition set
1809  EntityHandle partitionset = itaps_cast< EntityHandle >( partition );
1810  if( !partitionset )
1811  {
1812  rval = MB_FAILURE;CHKERR( rval, "failed to get partition set" );
1813  }
1814 
1815  EntityHandle this_mb_set = itaps_cast< EntityHandle >( this_set );
1816 
1817  // get ParallelComm for partition
1818  MPI_Comm default_comm;
1819  ParallelComm* pcomm = ParallelComm::get_pcomm( MOABI, partitionset, &default_comm );
1820  if( !pcomm )
1821  {
1822  RETURN( iBase_FAILURE );
1823  }
1824 
1825  rval = pcomm->assign_global_ids( this_mb_set, dimension, start_id, largest_dim_only, parallel, owned_only );
1826 
1827  RETURN( rval );
1828 }
1829 
1830 void iMeshP_getCommunicator( iMesh_Instance instance, int* fcomm, MPI_Comm* ccomm, int* err )
1831 {
1832  *ccomm = MPI_Comm_f2c( *fcomm );
1833  RETURN( iBase_SUCCESS );
1834 }
1835 
1836 #ifdef __cplusplus
1837 } // extern "C"
1838 #endif