1# ------------------------------------------------------------------------------ 2 3cdef class Sys: 4 5 """System utilities.""" 6 7 @classmethod 8 def getVersion( 9 cls, 10 devel: bool = False, 11 date: bool = False, 12 author: bool = False) -> tuple[int, int, int]: 13 """Return PETSc version information. 14 15 Not collective. 16 17 Parameters 18 ---------- 19 devel 20 Additionally, return whether using an in-development version. 21 date 22 Additionally, return date information. 23 author 24 Additionally, return author information. 25 26 Returns 27 ------- 28 major : int 29 Major version number. 30 minor : int 31 Minor version number. 32 micro : int 33 Micro (or patch) version number. 34 35 See Also 36 -------- 37 petsc.PetscGetVersion, petsc.PetscGetVersionNumber 38 39 """ 40 cdef char cversion[256] 41 cdef PetscInt major=0, minor=0, micro=0, release=0 42 CHKERR(PetscGetVersion(cversion, sizeof(cversion))) 43 CHKERR(PetscGetVersionNumber(&major, &minor, µ, &release)) 44 out = version = (toInt(major), toInt(minor), toInt(micro)) 45 if devel or date or author: 46 out = [version] 47 if devel: 48 out.append(not <bint>release) 49 if date: 50 vstr = bytes2str(cversion) 51 if release != 0: 52 date = vstr.split(",", 1)[-1].strip() 53 else: 54 date = vstr.split("Git Date:")[-1].strip() 55 out.append(date) 56 if author: 57 author = bytes2str(PETSC_AUTHOR_INFO).split('\n') 58 author = tuple([s.strip() for s in author if s]) 59 out.append(author) 60 return tuple(out) 61 62 @classmethod 63 def getVersionInfo(cls) -> dict[str, bool | int | str]: 64 """Return PETSc version information. 65 66 Not collective. 67 68 Returns 69 ------- 70 info : dict 71 Dictionary with version information. 72 73 See Also 74 -------- 75 petsc.PetscGetVersion, petsc.PetscGetVersionNumber 76 77 """ 78 version, dev, date, author = cls.getVersion(True, True, True) 79 return dict(major = version[0], 80 minor = version[1], 81 subminor = version[2], 82 release = not dev, 83 date = date, 84 authorinfo = author) 85 86 # --- xxx --- 87 88 @classmethod 89 def isInitialized(cls) -> bool: 90 """Return whether PETSc has been initialized. 91 92 Not collective. 93 94 See Also 95 -------- 96 isFinalized 97 98 """ 99 return toBool(PetscInitializeCalled) 100 101 @classmethod 102 def isFinalized(cls) -> bool: 103 """Return whether PETSc has been finalized. 104 105 Not collective. 106 107 See Also 108 -------- 109 isInitialized 110 111 """ 112 return toBool(PetscFinalizeCalled) 113 114 # --- xxx --- 115 116 @classmethod 117 def getDefaultComm(cls) -> Comm: 118 """Get the default MPI communicator used to create PETSc objects. 119 120 Not collective. 121 122 See Also 123 -------- 124 setDefaultComm 125 126 """ 127 cdef Comm comm = Comm() 128 comm.comm = PETSC_COMM_DEFAULT 129 return comm 130 131 @classmethod 132 def setDefaultComm(cls, comm: Comm | None) -> None: 133 """Set the default MPI communicator used to create PETSc objects. 134 135 Logically collective. 136 137 Parameters 138 ---------- 139 comm 140 MPI communicator. If set to `None`, uses `COMM_WORLD`. 141 142 See Also 143 -------- 144 getDefaultComm 145 146 """ 147 cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_WORLD) 148 if ccomm == MPI_COMM_NULL: 149 raise ValueError("null communicator") 150 global PETSC_COMM_DEFAULT 151 PETSC_COMM_DEFAULT = ccomm 152 153 # --- xxx --- 154 155 @classmethod 156 def Print( 157 cls, 158 *args: Any, 159 sep: str = ' ', 160 end: str = '\n', 161 comm: Comm | None = None, 162 **kwargs: Any) -> None: # noqa: E129 163 """Print output from the first processor of a communicator. 164 165 Collective. 166 167 Parameters 168 ---------- 169 *args 170 Positional arguments. 171 sep 172 String inserted between values, by default a space. 173 end 174 String appended after the last value, by default a newline. 175 comm 176 MPI communicator, defaults to `getDefaultComm`. 177 **kwargs 178 Keyword arguments. 179 180 See Also 181 -------- 182 petsc.PetscPrintf 183 184 """ 185 cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT) 186 if comm_rank(ccomm) == 0: 187 if not args: args = ('',) 188 format = ['%s', sep] * len(args) 189 format[-1] = end 190 message = ''.join(format) % args 191 else: 192 message = '' 193 cdef const char *m = NULL 194 message = str2bytes(message, &m) 195 CHKERR(PetscPrintf(ccomm, '%s', m)) 196 197 @classmethod 198 def syncPrint( 199 cls, 200 *args: Any, 201 sep: str = ' ', 202 end: str = '\n', 203 flush: bool = False, 204 comm: Comm | None = None, 205 **kwargs: Any) -> None: # noqa: E129 206 """Print synchronized output from several processors of a communicator. 207 208 Not collective. 209 210 Parameters 211 ---------- 212 *args 213 Positional arguments. 214 sep 215 String inserted between values, by default a space. 216 end 217 String appended after the last value, by default a newline. 218 flush 219 Whether to flush output with `syncFlush`. 220 comm 221 MPI communicator, defaults to `getDefaultComm`. 222 **kwargs 223 Keyword arguments. 224 225 See Also 226 -------- 227 petsc.PetscSynchronizedPrintf, petsc.PetscSynchronizedFlush 228 229 """ 230 cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT) 231 if not args: args = ('',) 232 format = ['%s', sep] * len(args) 233 format[-1] = end 234 message = ''.join(format) % args 235 cdef const char *m = NULL 236 message = str2bytes(message, &m) 237 CHKERR(PetscSynchronizedPrintf(ccomm, '%s', m)) 238 if flush: CHKERR(PetscSynchronizedFlush(ccomm, PETSC_STDOUT)) 239 240 @classmethod 241 def syncFlush(cls, comm: Comm | None = None) -> None: 242 """Flush output from previous `syncPrint` calls. 243 244 Collective. 245 246 Parameters 247 ---------- 248 comm 249 MPI communicator, defaults to `getDefaultComm`. 250 251 See Also 252 -------- 253 petsc.PetscSynchronizedPrintf, petsc.PetscSynchronizedFlush 254 255 """ 256 cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT) 257 CHKERR(PetscSynchronizedFlush(ccomm, PETSC_STDOUT)) 258 259 # --- xxx --- 260 261 @classmethod 262 def splitOwnership( 263 cls, 264 size: int | tuple[int, int], 265 bsize: int | None = None, 266 comm: Comm | None = None) -> tuple[int, int]: 267 """Given a global (or local) size determines a local (or global) size. 268 269 Collective. 270 271 Parameters 272 ---------- 273 size 274 Global size ``N`` or 2-tuple ``(n, N)`` with local and global 275 sizes. Either of ``n`` or ``N`` (but not both) can be `None`. 276 bsize 277 Block size, defaults to ``1``. 278 comm 279 MPI communicator, defaults to `getDefaultComm`. 280 281 Returns 282 ------- 283 n : int 284 The local size. 285 N : int 286 The global size. 287 288 Notes 289 ----- 290 The ``size`` argument corresponds to the full size of the 291 vector. That is, an array with 10 blocks and a block size of 3 will 292 have a ``size`` of 30, not 10. 293 294 See Also 295 -------- 296 petsc.PetscSplitOwnership 297 298 """ 299 cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT) 300 cdef PetscInt bs=0, n=0, N=0 301 Sys_Sizes(size, bsize, &bs, &n, &N) 302 if bs == PETSC_DECIDE: bs = 1 303 if n > 0: n = n // bs 304 if N > 0: N = N // bs 305 CHKERR(PetscSplitOwnership(ccomm, &n, &N)) 306 n = n * bs 307 N = N * bs 308 return (toInt(n), toInt(N)) 309 310 @classmethod 311 def sleep(cls, seconds: float = 1.0) -> None: 312 """Sleep some number of seconds. 313 314 Not collective. 315 316 Parameters 317 ---------- 318 seconds 319 Time to sleep in seconds. 320 321 See Also 322 -------- 323 petsc.PetscSleep 324 325 """ 326 cdef PetscReal s = asReal(seconds) 327 CHKERR(PetscSleep(s)) 328 329 # --- xxx --- 330 331 @classmethod 332 def pushErrorHandler(cls, errhandler: str) -> None: 333 """Set the current error handler. 334 335 Logically collective. 336 337 Parameters 338 ---------- 339 errhandler 340 The name of the error handler. 341 342 See Also 343 -------- 344 petsc.PetscPushErrorHandler 345 346 """ 347 cdef PetscErrorHandlerFunction handler = NULL 348 if errhandler == "python": 349 handler = <PetscErrorHandlerFunction> PetscPythonErrorHandler 350 elif errhandler == "debugger": 351 handler = PetscAttachDebuggerErrorHandler 352 elif errhandler == "emacs": 353 handler = PetscEmacsClientErrorHandler 354 elif errhandler == "traceback": 355 handler = PetscTraceBackErrorHandler 356 elif errhandler == "ignore": 357 handler = PetscIgnoreErrorHandler 358 elif errhandler == "mpiabort": 359 handler = PetscMPIAbortErrorHandler 360 elif errhandler == "abort": 361 handler = PetscAbortErrorHandler 362 else: 363 raise ValueError(f"unknown error handler: {errhandler!r}") 364 CHKERR(PetscPushErrorHandler(handler, NULL)) 365 366 @classmethod 367 def popErrorHandler(cls) -> None: 368 """Remove the current error handler. 369 370 Logically collective. 371 372 See Also 373 -------- 374 petsc.PetscPopErrorHandler 375 376 """ 377 CHKERR(PetscPopErrorHandler()) 378 379 @classmethod 380 def popSignalHandler(cls) -> None: 381 """Remove the current signal handler. 382 383 Logically collective. 384 385 See Also 386 -------- 387 petsc.PetscPopSignalHandler 388 389 """ 390 CHKERR(PetscPopSignalHandler()) 391 392 @classmethod 393 def infoAllow( 394 cls, 395 flag: bool, 396 filename: str | None = None, 397 mode: str = "w") -> None: 398 """Enables or disables PETSc info messages. 399 400 Not collective. 401 402 Parameters 403 ---------- 404 flag 405 Whether to enable info messages. 406 filename 407 Name of a file where to dump output. 408 mode 409 Write mode for file, by default ``"w"``. 410 411 See Also 412 -------- 413 petsc.PetscInfoAllow, petsc.PetscInfoSetFile 414 415 """ 416 cdef PetscBool tval = PETSC_FALSE 417 cdef const char *cfilename = NULL 418 cdef const char *cmode = NULL 419 if flag: tval = PETSC_TRUE 420 CHKERR(PetscInfoAllow(tval)) 421 if filename is not None: 422 filename = str2bytes(filename, &cfilename) 423 mode = str2bytes(mode, &cmode) 424 CHKERR(PetscInfoSetFile(cfilename, cmode)) 425 426 @classmethod 427 def registerCitation(cls, citation: str) -> None: 428 """Register BibTeX citation. 429 430 Not collective. 431 432 Parameters 433 ---------- 434 citation 435 The BibTex citation entry to register. 436 437 See Also 438 -------- 439 petsc.PetscCitationsRegister 440 441 """ 442 if not citation: raise ValueError("empty citation") 443 cdef const char *cit = NULL 444 citation = str2bytes(citation, &cit) 445 cdef PetscBool flag = get_citation(citation) 446 CHKERR(PetscCitationsRegister(cit, &flag)) 447 set_citation(citation, toBool(flag)) 448 449 @classmethod 450 def hasExternalPackage(cls, package: str) -> bool: 451 """Return whether PETSc has support for external package. 452 453 Not collective. 454 455 Parameters 456 ---------- 457 package 458 The external package name. 459 460 See Also 461 -------- 462 petsc.PetscHasExternalPackage 463 464 """ 465 cdef const char *cpackage = NULL 466 package = str2bytes(package, &cpackage) 467 cdef PetscBool has = PETSC_FALSE 468 CHKERR(PetscHasExternalPackage(cpackage, &has)) 469 return toBool(has) 470 471 472cdef dict citations_registry = {} 473 474cdef PetscBool get_citation(object citation): 475 cdef bint is_set = citations_registry.get(citation) 476 return PETSC_TRUE if is_set else PETSC_FALSE 477 478cdef set_citation(object citation, bint is_set): 479 citations_registry[citation] = is_set 480 481# ------------------------------------------------------------------------------ 482