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