1# -------------------------------------------------------------------- 2 3cdef class Comm: 4 """Communicator object. 5 6 Predefined instances: 7 8 `COMM_NULL` 9 The *null* (or invalid) communicator. 10 `COMM_SELF` 11 The *self* communicator. 12 `COMM_WORLD` 13 The *world* communicator. 14 15 See Also 16 -------- 17 Sys.setDefaultComm, Sys.getDefaultComm 18 19 """ 20 21 # 22 23 def __cinit__(self, comm=None): 24 self.comm = def_Comm(comm, MPI_COMM_NULL) 25 self.isdup = 0 26 if self.comm != MPI_COMM_NULL: 27 self.base = comm 28 else: 29 self.base = None 30 31 def __dealloc__(self): 32 if self.isdup: 33 CHKERR(PetscCommDEALLOC(&self.comm)) 34 self.comm = MPI_COMM_NULL 35 self.isdup = 0 36 self.base = None 37 38 def __richcmp__(self, other, int op): 39 if not isinstance(self, Comm): return NotImplemented 40 if not isinstance(other, Comm): return NotImplemented 41 if op!=2 and op!=3: raise TypeError("only '==' and '!='") 42 cdef Comm s = self 43 cdef Comm o = other 44 cdef int eq = (op == 2) 45 cdef MPI_Comm comm1 = s.comm 46 cdef MPI_Comm comm2 = o.comm 47 cdef int flag = 0 48 if comm1 != MPI_COMM_NULL and comm2 != MPI_COMM_NULL: 49 CHKERR(<PetscErrorCode>MPI_Comm_compare(comm1, comm2, &flag)) 50 if eq: return (flag==<int>MPI_IDENT or flag==<int>MPI_CONGRUENT) 51 else: return (flag!=<int>MPI_IDENT and flag!=<int>MPI_CONGRUENT) 52 else: 53 if eq: return (comm1 == comm2) 54 else: return (comm1 != comm2) 55 56 def __bool__(self) -> bool: 57 return self.comm != MPI_COMM_NULL 58 59 # 60 61 def destroy(self) -> None: 62 """Destroy the communicator. 63 64 Collective. 65 66 See Also 67 -------- 68 petsc.PetscCommDestroy 69 70 """ 71 if self.comm == MPI_COMM_NULL: return 72 if not self.isdup: 73 raise ValueError("communicator not owned") 74 CHKERR(PetscCommDestroy(&self.comm)) 75 self.comm = MPI_COMM_NULL 76 self.isdup = 0 77 self.base = None 78 79 def duplicate(self) -> Self: 80 """Duplicate the communicator. 81 82 Collective. 83 84 See Also 85 -------- 86 petsc.PetscCommDuplicate 87 88 """ 89 if self.comm == MPI_COMM_NULL: 90 raise ValueError("null communicator") 91 cdef MPI_Comm newcomm = MPI_COMM_NULL 92 CHKERR(PetscCommDuplicate(self.comm, &newcomm, NULL)) 93 cdef Comm comm = type(self)() 94 comm.comm = newcomm 95 comm.isdup = 1 96 comm.base = self.base 97 return comm 98 99 def getSize(self) -> int: 100 """Return the number of processes in the communicator. 101 102 Not collective. 103 104 """ 105 if self.comm == MPI_COMM_NULL: 106 raise ValueError("null communicator") 107 cdef int size=0 108 CHKERRMPI(MPI_Comm_size(self.comm, &size)) 109 return size 110 111 def getRank(self) -> int: 112 """Return the rank of the calling processes in the communicator. 113 114 Not collective. 115 116 """ 117 if self.comm == MPI_COMM_NULL: 118 raise ValueError("null communicator") 119 cdef int rank=0 120 CHKERRMPI(MPI_Comm_rank(self.comm, &rank)) 121 return rank 122 123 def barrier(self) -> None: 124 """Barrier synchronization. 125 126 Collective. 127 128 """ 129 if self.comm == MPI_COMM_NULL: 130 raise ValueError("null communicator") 131 CHKERRMPI(MPI_Barrier(self.comm)) 132 133 # --- properties --- 134 135 property size: 136 """Communicator size.""" 137 def __get__(self) -> int: 138 return self.getSize() 139 140 property rank: 141 """Communicator rank.""" 142 def __get__(self) -> int: 143 return self.getRank() 144 145 # --- Fortran support --- 146 147 property fortran: 148 """Fortran handle.""" 149 def __get__(self) -> int: 150 cdef MPI_Comm comm = self.comm 151 return MPI_Comm_c2f(comm) 152 153 # --- mpi4py support --- 154 155 def tompi4py(self) -> Intracomm: 156 """Convert communicator to `mpi4py`. 157 158 Not collective. 159 160 See Also 161 -------- 162 mpi4py.MPI.Comm, mpi4py.MPI.Intracomm 163 164 """ 165 cdef MPI_Comm comm = self.comm 166 return mpi4py_Comm_New(comm) 167 168 # --- mpi4py compatibility API --- 169 170 Free = destroy 171 Clone = duplicate 172 Dup = duplicate 173 Get_size = getSize 174 Get_rank = getRank 175 Barrier = barrier 176 177# -------------------------------------------------------------------- 178 179cdef Comm __COMM_NULL__ = Comm() 180cdef Comm __COMM_SELF__ = Comm() 181cdef Comm __COMM_WORLD__ = Comm() 182 183COMM_NULL = __COMM_NULL__ 184COMM_SELF = __COMM_SELF__ 185COMM_WORLD = __COMM_WORLD__ 186 187# -------------------------------------------------------------------- 188 189cdef MPI_Comm PETSC_COMM_DEFAULT = MPI_COMM_NULL 190 191cdef MPI_Comm GetComm( 192 object comm, MPI_Comm defv, 193) except? MPI_COMM_NULL: 194 return def_Comm(comm, defv) 195 196cdef MPI_Comm GetCommDefault(): 197 return PETSC_COMM_DEFAULT 198 199# -------------------------------------------------------------------- 200