1cdef class Group: 2 3 """ 4 Group 5 """ 6 7 def __cinit__(self): 8 self.ob_mpi = MPI_GROUP_NULL 9 10 def __dealloc__(self): 11 if not (self.flags & PyMPI_OWNED): return 12 CHKERR( del_Group(&self.ob_mpi) ) 13 14 def __richcmp__(self, other, int op): 15 if not isinstance(self, Group): return NotImplemented 16 if not isinstance(other, Group): return NotImplemented 17 cdef Group s = <Group>self, o = <Group>other 18 if op == Py_EQ: return (s.ob_mpi == o.ob_mpi) 19 elif op == Py_NE: return (s.ob_mpi != o.ob_mpi) 20 else: raise TypeError("only '==' and '!='") 21 22 def __bool__(self): 23 return self.ob_mpi != MPI_GROUP_NULL 24 25 # Group Accessors 26 # --------------- 27 28 def Get_size(self): 29 """ 30 Return the size of a group 31 """ 32 cdef int size = -1 33 CHKERR( MPI_Group_size(self.ob_mpi, &size) ) 34 return size 35 36 property size: 37 """number of processes in group""" 38 def __get__(self): 39 return self.Get_size() 40 41 def Get_rank(self): 42 """ 43 Return the rank of this process in a group 44 """ 45 cdef int rank = -1 46 CHKERR( MPI_Group_rank(self.ob_mpi, &rank) ) 47 return rank 48 49 property rank: 50 """rank of this process in group""" 51 def __get__(self): 52 return self.Get_rank() 53 54 @classmethod 55 def Translate_ranks(cls, 56 Group group1 not None, ranks1, 57 Group group2=None): 58 """ 59 Translate the ranks of processes in 60 one group to those in another group 61 """ 62 cdef MPI_Group grp1 = MPI_GROUP_NULL 63 cdef MPI_Group grp2 = MPI_GROUP_NULL 64 cdef int n = 0, *iranks1 = NULL, *iranks2 = NULL 65 cdef object ranks_ = getarray_int(ranks1, &n, &iranks1) 66 cdef object ranks2 = newarray_int(n, &iranks2) 67 # 68 grp1 = group1.ob_mpi 69 if group2 is not None: 70 grp2 = group2.ob_mpi 71 else: 72 CHKERR( MPI_Comm_group(MPI_COMM_WORLD, &grp2) ) 73 try: 74 CHKERR( MPI_Group_translate_ranks(grp1, n, iranks1, 75 grp2, iranks2) ) 76 finally: 77 if group2 is None: 78 CHKERR( MPI_Group_free(&grp2) ) 79 # 80 return ranks2 81 82 @classmethod 83 def Compare(cls, 84 Group group1 not None, 85 Group group2 not None): 86 """ 87 Compare two groups 88 """ 89 cdef int flag = MPI_UNEQUAL 90 CHKERR( MPI_Group_compare(group1.ob_mpi, group2.ob_mpi, &flag) ) 91 return flag 92 93 # Group Constructors 94 # ------------------ 95 96 def Dup(self): 97 """ 98 Duplicate a group 99 """ 100 cdef Group group = <Group>type(self)() 101 CHKERR( MPI_Group_union(self.ob_mpi, MPI_GROUP_EMPTY, &group.ob_mpi) ) 102 return group 103 104 @classmethod 105 def Union(cls, 106 Group group1 not None, 107 Group group2 not None): 108 """ 109 Produce a group by combining 110 two existing groups 111 """ 112 cdef Group group = <Group>cls() 113 CHKERR( MPI_Group_union( 114 group1.ob_mpi, group2.ob_mpi, &group.ob_mpi) ) 115 return group 116 117 @classmethod 118 def Intersect(cls, 119 Group group1 not None, 120 Group group2 not None): 121 """ 122 Produce a group as the intersection 123 of two existing groups 124 """ 125 cdef Group group = <Group>cls() 126 CHKERR( MPI_Group_intersection( 127 group1.ob_mpi, group2.ob_mpi, &group.ob_mpi) ) 128 return group 129 130 @classmethod 131 def Difference(cls, 132 Group group1 not None, 133 Group group2 not None): 134 """ 135 Produce a group from the difference 136 of two existing groups 137 """ 138 cdef Group group = <Group>cls() 139 CHKERR( MPI_Group_difference( 140 group1.ob_mpi, group2.ob_mpi, &group.ob_mpi) ) 141 return group 142 143 def Incl(self, ranks): 144 """ 145 Produce a group by reordering an existing 146 group and taking only listed members 147 """ 148 cdef int n = 0, *iranks = NULL 149 ranks = getarray_int(ranks, &n, &iranks) 150 cdef Group group = <Group>type(self)() 151 CHKERR( MPI_Group_incl(self.ob_mpi, n, iranks, &group.ob_mpi) ) 152 return group 153 154 def Excl(self, ranks): 155 """ 156 Produce a group by reordering an existing 157 group and taking only unlisted members 158 """ 159 cdef int n = 0, *iranks = NULL 160 ranks = getarray_int(ranks, &n, &iranks) 161 cdef Group group = <Group>type(self)() 162 CHKERR( MPI_Group_excl(self.ob_mpi, n, iranks, &group.ob_mpi) ) 163 return group 164 165 def Range_incl(self, ranks): 166 """ 167 Create a new group from ranges of 168 of ranks in an existing group 169 """ 170 cdef int *p = NULL, (*ranges)[3]# = NULL ## XXX cython fails 171 ranges = NULL 172 cdef int i = 0, n = <int>len(ranks) 173 cdef tmp1 = allocate(n, sizeof(int[3]), <void**>&ranges) 174 for i from 0 <= i < n: 175 p = <int*> ranges[i] 176 p[0], p[1], p[2] = ranks[i] 177 cdef Group group = <Group>type(self)() 178 CHKERR( MPI_Group_range_incl(self.ob_mpi, n, ranges, &group.ob_mpi) ) 179 return group 180 181 def Range_excl(self, ranks): 182 """ 183 Create a new group by excluding ranges 184 of processes from an existing group 185 """ 186 cdef int *p = NULL, (*ranges)[3]# = NULL ## XXX cython fails 187 ranges = NULL 188 cdef int i = 0, n = <int>len(ranks) 189 cdef tmp1 = allocate(n, sizeof(int[3]), <void**>&ranges) 190 for i from 0 <= i < n: 191 p = <int*> ranges[i] 192 p[0], p[1], p[2] = ranks[i] 193 cdef Group group = <Group>type(self)() 194 CHKERR( MPI_Group_range_excl(self.ob_mpi, n, ranges, &group.ob_mpi) ) 195 return group 196 197 # Group Destructor 198 # ---------------- 199 200 def Free(self): 201 """ 202 Free a group 203 """ 204 if self.ob_mpi != MPI_GROUP_EMPTY: 205 CHKERR( MPI_Group_free(&self.ob_mpi) ) 206 elif self is not __GROUP_EMPTY__: 207 self.ob_mpi = MPI_GROUP_NULL 208 else: CHKERR( MPI_ERR_GROUP ) 209 210 # Fortran Handle 211 # -------------- 212 213 def py2f(self): 214 """ 215 """ 216 return MPI_Group_c2f(self.ob_mpi) 217 218 @classmethod 219 def f2py(cls, arg): 220 """ 221 """ 222 cdef Group group = <Group>cls() 223 group.ob_mpi = MPI_Group_f2c(arg) 224 return group 225 226 227 228cdef Group __GROUP_NULL__ = new_Group ( MPI_GROUP_NULL ) 229cdef Group __GROUP_EMPTY__ = new_Group ( MPI_GROUP_EMPTY ) 230 231 232# Predefined group handles 233# ------------------------ 234 235GROUP_NULL = __GROUP_NULL__ #: Null group handle 236GROUP_EMPTY = __GROUP_EMPTY__ #: Empty group handle 237