xref: /petsc/src/binding/petsc4py/src/petsc4py/PETSc/Mat.pyx (revision f2300f31d01ffc99ca7a05a43941a14c1c1d9061)
1# --------------------------------------------------------------------
2
3class MatType(object):
4    """Matrix type.
5
6    See Also
7    --------
8    petsc.MatType
9
10    """
11    SAME            = S_(MATSAME)
12    MAIJ            = S_(MATMAIJ)
13    SEQMAIJ         = S_(MATSEQMAIJ)
14    MPIMAIJ         = S_(MATMPIMAIJ)
15    KAIJ            = S_(MATKAIJ)
16    SEQKAIJ         = S_(MATSEQKAIJ)
17    MPIKAIJ         = S_(MATMPIKAIJ)
18    IS              = S_(MATIS)
19    AIJ             = S_(MATAIJ)
20    SEQAIJ          = S_(MATSEQAIJ)
21    MPIAIJ          = S_(MATMPIAIJ)
22    AIJCRL          = S_(MATAIJCRL)
23    SEQAIJCRL       = S_(MATSEQAIJCRL)
24    MPIAIJCRL       = S_(MATMPIAIJCRL)
25    AIJCUSPARSE     = S_(MATAIJCUSPARSE)
26    SEQAIJCUSPARSE  = S_(MATSEQAIJCUSPARSE)
27    MPIAIJCUSPARSE  = S_(MATMPIAIJCUSPARSE)
28    AIJVIENNACL     = S_(MATAIJVIENNACL)
29    SEQAIJVIENNACL  = S_(MATSEQAIJVIENNACL)
30    MPIAIJVIENNACL  = S_(MATMPIAIJVIENNACL)
31    AIJPERM         = S_(MATAIJPERM)
32    SEQAIJPERM      = S_(MATSEQAIJPERM)
33    MPIAIJPERM      = S_(MATMPIAIJPERM)
34    AIJSELL         = S_(MATAIJSELL)
35    SEQAIJSELL      = S_(MATSEQAIJSELL)
36    MPIAIJSELL      = S_(MATMPIAIJSELL)
37    AIJMKL          = S_(MATAIJMKL)
38    SEQAIJMKL       = S_(MATSEQAIJMKL)
39    MPIAIJMKL       = S_(MATMPIAIJMKL)
40    BAIJMKL         = S_(MATBAIJMKL)
41    SEQBAIJMKL      = S_(MATSEQBAIJMKL)
42    MPIBAIJMKL      = S_(MATMPIBAIJMKL)
43    SHELL           = S_(MATSHELL)
44    DENSE           = S_(MATDENSE)
45    DENSECUDA       = S_(MATDENSECUDA)
46    DENSEHIP        = S_(MATDENSEHIP)
47    SEQDENSE        = S_(MATSEQDENSE)
48    SEQDENSECUDA    = S_(MATSEQDENSECUDA)
49    SEQDENSEHIP     = S_(MATSEQDENSEHIP)
50    MPIDENSE        = S_(MATMPIDENSE)
51    MPIDENSECUDA    = S_(MATMPIDENSECUDA)
52    MPIDENSEHIP     = S_(MATMPIDENSEHIP)
53    ELEMENTAL       = S_(MATELEMENTAL)
54    BAIJ            = S_(MATBAIJ)
55    SEQBAIJ         = S_(MATSEQBAIJ)
56    MPIBAIJ         = S_(MATMPIBAIJ)
57    MPIADJ          = S_(MATMPIADJ)
58    SBAIJ           = S_(MATSBAIJ)
59    SEQSBAIJ        = S_(MATSEQSBAIJ)
60    MPISBAIJ        = S_(MATMPISBAIJ)
61    MFFD            = S_(MATMFFD)
62    NORMAL          = S_(MATNORMAL)
63    NORMALHERMITIAN = S_(MATNORMALHERMITIAN)
64    LRC             = S_(MATLRC)
65    SCATTER         = S_(MATSCATTER)
66    BLOCKMAT        = S_(MATBLOCKMAT)
67    COMPOSITE       = S_(MATCOMPOSITE)
68    FFT             = S_(MATFFT)
69    FFTW            = S_(MATFFTW)
70    SEQCUFFT        = S_(MATSEQCUFFT)
71    TRANSPOSE       = S_(MATTRANSPOSEVIRTUAL)
72    HERMITIANTRANSPOSE = S_(MATHERMITIANTRANSPOSEVIRTUAL)
73    SCHURCOMPLEMENT = S_(MATSCHURCOMPLEMENT)
74    PYTHON          = S_(MATPYTHON)
75    HYPRE           = S_(MATHYPRE)
76    HYPRESTRUCT     = S_(MATHYPRESTRUCT)
77    HYPRESSTRUCT    = S_(MATHYPRESSTRUCT)
78    SUBMATRIX       = S_(MATSUBMATRIX)
79    LOCALREF        = S_(MATLOCALREF)
80    NEST            = S_(MATNEST)
81    PREALLOCATOR    = S_(MATPREALLOCATOR)
82    SELL            = S_(MATSELL)
83    SEQSELL         = S_(MATSEQSELL)
84    MPISELL         = S_(MATMPISELL)
85    DUMMY           = S_(MATDUMMY)
86    LMVM            = S_(MATLMVM)
87    LMVMDFP         = S_(MATLMVMDFP)
88    LMVMDDFP        = S_(MATLMVMDDFP)
89    LMVMBFGS        = S_(MATLMVMBFGS)
90    LMVMDBFGS       = S_(MATLMVMDBFGS)
91    LMVMDQN         = S_(MATLMVMDQN)
92    LMVMSR1         = S_(MATLMVMSR1)
93    LMVMBROYDEN     = S_(MATLMVMBROYDEN)
94    LMVMBADBROYDEN  = S_(MATLMVMBADBROYDEN)
95    LMVMSYMBROYDEN  = S_(MATLMVMSYMBROYDEN)
96    LMVMSYMBADBROYDEN = S_(MATLMVMSYMBADBROYDEN)
97    LMVMDIAGBBROYDEN = S_(MATLMVMDIAGBROYDEN)
98    CONSTANTDIAGONAL = S_(MATCONSTANTDIAGONAL)
99    DIAGONAL         = S_(MATDIAGONAL)
100    H2OPUS           = S_(MATH2OPUS)
101
102
103class MatOption(object):
104    """Matrix option.
105
106    See Also
107    --------
108    petsc.MatOption
109
110    """
111    OPTION_MIN                  = MAT_OPTION_MIN
112    UNUSED_NONZERO_LOCATION_ERR = MAT_UNUSED_NONZERO_LOCATION_ERR
113    ROW_ORIENTED                = MAT_ROW_ORIENTED
114    SYMMETRIC                   = MAT_SYMMETRIC
115    STRUCTURALLY_SYMMETRIC      = MAT_STRUCTURALLY_SYMMETRIC
116    FORCE_DIAGONAL_ENTRIES      = MAT_FORCE_DIAGONAL_ENTRIES
117    IGNORE_OFF_PROC_ENTRIES     = MAT_IGNORE_OFF_PROC_ENTRIES
118    USE_HASH_TABLE              = MAT_USE_HASH_TABLE
119    KEEP_NONZERO_PATTERN        = MAT_KEEP_NONZERO_PATTERN
120    IGNORE_ZERO_ENTRIES         = MAT_IGNORE_ZERO_ENTRIES
121    USE_INODES                  = MAT_USE_INODES
122    HERMITIAN                   = MAT_HERMITIAN
123    SYMMETRY_ETERNAL            = MAT_SYMMETRY_ETERNAL
124    NEW_NONZERO_LOCATION_ERR    = MAT_NEW_NONZERO_LOCATION_ERR
125    IGNORE_LOWER_TRIANGULAR     = MAT_IGNORE_LOWER_TRIANGULAR
126    ERROR_LOWER_TRIANGULAR      = MAT_ERROR_LOWER_TRIANGULAR
127    GETROW_UPPERTRIANGULAR      = MAT_GETROW_UPPERTRIANGULAR
128    SPD                         = MAT_SPD
129    NO_OFF_PROC_ZERO_ROWS       = MAT_NO_OFF_PROC_ZERO_ROWS
130    NO_OFF_PROC_ENTRIES         = MAT_NO_OFF_PROC_ENTRIES
131    NEW_NONZERO_LOCATIONS       = MAT_NEW_NONZERO_LOCATIONS
132    NEW_NONZERO_ALLOCATION_ERR  = MAT_NEW_NONZERO_ALLOCATION_ERR
133    SUBSET_OFF_PROC_ENTRIES     = MAT_SUBSET_OFF_PROC_ENTRIES
134    SUBMAT_SINGLEIS             = MAT_SUBMAT_SINGLEIS
135    STRUCTURE_ONLY              = MAT_STRUCTURE_ONLY
136    SORTED_FULL                 = MAT_SORTED_FULL
137    OPTION_MAX                  = MAT_OPTION_MAX
138
139
140class MatAssemblyType(object):
141    """Matrix assembly type.
142
143    See Also
144    --------
145    petsc.MatAssemblyType
146
147    """
148    # native
149    FINAL_ASSEMBLY = MAT_FINAL_ASSEMBLY
150    FLUSH_ASSEMBLY = MAT_FLUSH_ASSEMBLY
151    # aliases
152    FINAL = FINAL_ASSEMBLY
153    FLUSH = FLUSH_ASSEMBLY
154
155
156class MatInfoType(object):
157    """Matrix info type."""
158    LOCAL = MAT_LOCAL
159    GLOBAL_MAX = MAT_GLOBAL_MAX
160    GLOBAL_SUM = MAT_GLOBAL_SUM
161
162
163class MatStructure(object):
164    """Matrix modification structure.
165
166    See Also
167    --------
168    petsc.MatStructure
169
170    """
171    # native
172    SAME_NONZERO_PATTERN      = MAT_SAME_NONZERO_PATTERN
173    DIFFERENT_NONZERO_PATTERN = MAT_DIFFERENT_NONZERO_PATTERN
174    SUBSET_NONZERO_PATTERN    = MAT_SUBSET_NONZERO_PATTERN
175    UNKNOWN_NONZERO_PATTERN   = MAT_UNKNOWN_NONZERO_PATTERN
176    # aliases
177    SAME      = SAME_NZ      = SAME_NONZERO_PATTERN
178    SUBSET    = SUBSET_NZ    = SUBSET_NONZERO_PATTERN
179    DIFFERENT = DIFFERENT_NZ = DIFFERENT_NONZERO_PATTERN
180    UNKNOWN   = UNKNOWN_NZ   = UNKNOWN_NONZERO_PATTERN
181
182
183class MatDuplicateOption(object):
184    """Matrix duplicate option.
185
186    See Also
187    --------
188    petsc.MatDuplicateOption
189
190    """
191    DO_NOT_COPY_VALUES    = MAT_DO_NOT_COPY_VALUES
192    COPY_VALUES           = MAT_COPY_VALUES
193    SHARE_NONZERO_PATTERN = MAT_SHARE_NONZERO_PATTERN
194
195
196class MatOrderingType(object):
197    """Factored matrix ordering type.
198
199    See Also
200    --------
201    petsc.MatOrderingType
202
203    """
204    NATURAL     = S_(MATORDERINGNATURAL)
205    ND          = S_(MATORDERINGND)
206    OWD         = S_(MATORDERING1WD)
207    RCM         = S_(MATORDERINGRCM)
208    QMD         = S_(MATORDERINGQMD)
209    ROWLENGTH   = S_(MATORDERINGROWLENGTH)
210    WBM         = S_(MATORDERINGWBM)
211    SPECTRAL    = S_(MATORDERINGSPECTRAL)
212    AMD         = S_(MATORDERINGAMD)
213    METISND     = S_(MATORDERINGMETISND)
214
215
216class MatSolverType(object):
217    """Factored matrix solver type.
218
219    See Also
220    --------
221    petsc.MatSolverType
222
223    """
224    SUPERLU         = S_(MATSOLVERSUPERLU)
225    SUPERLU_DIST    = S_(MATSOLVERSUPERLU_DIST)
226    STRUMPACK       = S_(MATSOLVERSTRUMPACK)
227    UMFPACK         = S_(MATSOLVERUMFPACK)
228    CHOLMOD         = S_(MATSOLVERCHOLMOD)
229    KLU             = S_(MATSOLVERKLU)
230    ELEMENTAL       = S_(MATSOLVERELEMENTAL)
231    SCALAPACK       = S_(MATSOLVERSCALAPACK)
232    ESSL            = S_(MATSOLVERESSL)
233    LUSOL           = S_(MATSOLVERLUSOL)
234    MUMPS           = S_(MATSOLVERMUMPS)
235    MKL_PARDISO     = S_(MATSOLVERMKL_PARDISO)
236    MKL_CPARDISO    = S_(MATSOLVERMKL_CPARDISO)
237    PASTIX          = S_(MATSOLVERPASTIX)
238    MATLAB          = S_(MATSOLVERMATLAB)
239    PETSC           = S_(MATSOLVERPETSC)
240    BAS             = S_(MATSOLVERBAS)
241    CUSPARSE        = S_(MATSOLVERCUSPARSE)
242    CUDA            = S_(MATSOLVERCUDA)
243    SPQR            = S_(MATSOLVERSPQR)
244
245
246class MatFactorShiftType(object):
247    """Factored matrix shift type.
248
249    See Also
250    --------
251    petsc.MatFactorShiftType
252
253    """
254    # native
255    NONE              = MAT_SHIFT_NONE
256    NONZERO           = MAT_SHIFT_NONZERO
257    POSITIVE_DEFINITE = MAT_SHIFT_POSITIVE_DEFINITE
258    INBLOCKS          = MAT_SHIFT_INBLOCKS
259    # aliases
260    NZ = MAT_SHIFT_NONZERO
261    PD = MAT_SHIFT_POSITIVE_DEFINITE
262
263
264class MatSORType(object):
265    """Matrix SOR type.
266
267    See Also
268    --------
269    petsc.MatSORType
270
271    """
272    FORWARD_SWEEP         = SOR_FORWARD_SWEEP
273    BACKWARD_SWEEP        = SOR_BACKWARD_SWEEP
274    SYMMETRY_SWEEP        = SOR_SYMMETRIC_SWEEP
275    LOCAL_FORWARD_SWEEP   = SOR_LOCAL_FORWARD_SWEEP
276    LOCAL_BACKWARD_SWEEP  = SOR_LOCAL_BACKWARD_SWEEP
277    LOCAL_SYMMETRIC_SWEEP = SOR_LOCAL_SYMMETRIC_SWEEP
278    ZERO_INITIAL_GUESS    = SOR_ZERO_INITIAL_GUESS
279    EISENSTAT             = SOR_EISENSTAT
280    APPLY_UPPER           = SOR_APPLY_UPPER
281    APPLY_LOWER           = SOR_APPLY_LOWER
282
283
284@cython.internal
285cdef class MatStencil:
286    """Associate structured grid coordinates with matrix indices.
287
288    See Also
289    --------
290    petsc.MatStencil
291
292    """
293
294    cdef PetscMatStencil stencil
295
296    property i:
297        "First logical grid coordinate."
298        def __get__(self) -> int:
299            return toInt(self.stencil.i)
300
301        def __set__(self, value: int) -> None:
302            self.stencil.i = asInt(value)
303
304    property j:
305        "Second logical grid coordinate."
306        def __get__(self) -> int:
307            return toInt(self.stencil.j)
308
309        def __set__(self, value: int) -> None:
310            self.stencil.j = asInt(value)
311
312    property k:
313        "Third logical grid coordinate."
314        def __get__(self) -> int:
315            return toInt(self.stencil.k)
316
317        def __set__(self, value: int) -> None:
318            self.stencil.k = asInt(value)
319
320    property c:
321        "Field component."
322        def __get__(self) -> int:
323            return toInt(self.stencil.c)
324
325        def __set__(self, value: int) -> None:
326            self.stencil.c = asInt(value)
327
328    property index:
329        "Logical grid coordinates ``(i, j, k)``."
330        def __get__(self) -> tuple[int, int, int]:
331            cdef PetscMatStencil *s = &self.stencil
332            return toInt(s.i), toInt(s.j), toInt(s.k)
333
334        def __set__(self, value: Sequence[int]) -> None:
335            cdef PetscMatStencil *s = &self.stencil
336            s.i = s.j = s.k = 0
337            asDims(value, &s.i, &s.j, &s.k)
338
339    property field:
340        "Field component."
341        def __get__(self) -> int:
342            cdef PetscMatStencil *s = &self.stencil
343            return toInt(s.c)
344
345        def __set__(self, value: int) -> None:
346            cdef PetscMatStencil *s = &self.stencil
347            s.c = asInt(value)
348
349# --------------------------------------------------------------------
350
351cdef class Mat(Object):
352    """Matrix object.
353
354    Mat is described in the `PETSc manual <petsc:manual/mat>`.
355
356    See Also
357    --------
358    petsc.Mat
359
360    """
361
362    Type            = MatType
363    Option          = MatOption
364    AssemblyType    = MatAssemblyType
365    InfoType        = MatInfoType
366    Structure       = MatStructure
367    DuplicateOption = MatDuplicateOption
368    OrderingType    = MatOrderingType
369    SolverType      = MatSolverType
370    FactorShiftType = MatFactorShiftType
371    SORType         = MatSORType
372    #
373
374    def __cinit__(self):
375        self.obj = <PetscObject*> &self.mat
376        self.mat = NULL
377
378    # unary operations
379
380    def __pos__(self):
381        return mat_pos(self)
382
383    def __neg__(self):
384        return mat_neg(self)
385
386    # inplace binary operations
387
388    def __iadd__(self, other):
389        return mat_iadd(self, other)
390
391    def __isub__(self, other):
392        return mat_isub(self, other)
393
394    def __imul__(self, other):
395        return mat_imul(self, other)
396
397    def __idiv__(self, other):
398        return mat_idiv(self, other)
399
400    def __itruediv__(self, other):
401        return mat_idiv(self, other)
402
403    # binary operations
404
405    def __add__(self, other):
406        return mat_add(self, other)
407
408    def __radd__(self, other):
409        return mat_radd(self, other)
410
411    def __sub__(self, other):
412        return mat_sub(self, other)
413
414    def __rsub__(self, other):
415        return mat_rsub(self, other)
416
417    def __mul__(self, other):
418        return mat_mul(self, other)
419
420    def __rmul__(self, other):
421        return mat_rmul(self, other)
422
423    def __div__(self, other):
424        return mat_div(self, other)
425
426    def __rdiv__(self, other):
427        return mat_rdiv(self, other)
428
429    def __truediv__(self, other):
430        return mat_div(self, other)
431
432    def __rtruediv__(self, other):
433        return mat_rdiv(self, other)
434
435    def __matmul__(self, other):
436        return mat_matmul(self, other)
437
438    #
439
440    def __getitem__(self, ij):
441        return mat_getitem(self, ij)
442
443    def __setitem__(self, ij, v):
444        mat_setitem(self, ij, v)
445
446    def __call__(self, x, y=None):
447        if y is None:
448            y = self.createVecLeft()
449        self.mult(x, y)
450        return y
451    #
452
453    def view(self, Viewer viewer=None) -> None:
454        """View the matrix.
455
456        Collective.
457
458        Parameters
459        ----------
460        viewer
461            A `Viewer` instance or `None` for the default viewer.
462
463        Notes
464        -----
465        Viewers with type `Viewer.Type.ASCII` are only recommended for small
466        matrices on small numbers of processes. Larger matrices should use a
467        binary format like `Viewer.Type.BINARY`.
468
469        See Also
470        --------
471        load, Viewer, petsc.MatView
472
473        """
474        cdef PetscViewer vwr = NULL
475        if viewer is not None: vwr = viewer.vwr
476        CHKERR(MatView(self.mat, vwr))
477
478    def destroy(self) -> Self:
479        """Destroy the matrix.
480
481        Collective.
482
483        See Also
484        --------
485        create, petsc.MatDestroy
486
487        """
488        CHKERR(MatDestroy(&self.mat))
489        return self
490
491    def create(self, comm: Comm | None = None) -> Self:
492        """Create the matrix.
493
494        Collective.
495
496        Once created, the user should call `setType` or
497        `setFromOptions` before using the matrix. Alternatively, specific
498        creation routines such as `createAIJ` or
499        `createBAIJ` can be used.
500
501        Parameters
502        ----------
503        comm
504            MPI communicator, defaults to `Sys.getDefaultComm`.
505
506        See Also
507        --------
508        destroy, petsc.MatCreate
509
510        """
511        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
512        cdef PetscMat newmat = NULL
513        CHKERR(MatCreate(ccomm, &newmat))
514        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
515        return self
516
517    def setType(self, mat_type: Type | str) -> None:
518        """Set the matrix type.
519
520        Collective.
521
522        Parameters
523        ----------
524        mat_type
525            The matrix type.
526
527        See Also
528        --------
529        create, getType, petsc.MatSetType
530
531        """
532        cdef PetscMatType cval = NULL
533        mat_type = str2bytes(mat_type, &cval)
534        CHKERR(MatSetType(self.mat, cval))
535
536    def setSizes(
537        self,
538        size: MatSizeSpec,
539        bsize: MatBlockSizeSpec | None = None) -> None:
540        """Set the local, global and block sizes.
541
542        Collective.
543
544        Parameters
545        ----------
546        size
547            Matrix size.
548        bsize
549            Matrix block size. If `None`, a block size of ``1`` is set.
550
551        Examples
552        --------
553        Create a `Mat` with ``n`` rows and columns and the same local and
554        global sizes.
555
556        >>> mat = PETSc.Mat().create()
557        >>> mat.setFromOptions()
558        >>> mat.setSizes(n)
559
560        Create a `Mat` with ``nr`` rows, ``nc`` columns and the same local and
561        global sizes.
562
563        >>> mat = PETSc.Mat().create()
564        >>> mat.setFromOptions()
565        >>> mat.setSizes([nr, nc])
566
567        Create a `Mat` with ``nrl`` local rows, ``nrg`` global rows, ``ncl``
568        local columns and ``ncg`` global columns.
569
570        >>> mat = PETSc.Mat().create()
571        >>> mat.setFromOptions()
572        >>> mat.setSizes([[nrl, nrg], [ncl, ncg]])
573
574        See Also
575        --------
576        setBlockSize, setBlockSizes, petsc.MatSetSizes, petsc.MatSetBlockSize
577        petsc.MatSetBlockSizes
578
579        """
580        cdef PetscInt rbs = 0, cbs = 0, m = 0, n = 0, M = 0, N = 0
581        Mat_Sizes(size, bsize, &rbs, &cbs, &m, &n, &M, &N)
582        CHKERR(MatSetSizes(self.mat, m, n, M, N))
583        if rbs != PETSC_DECIDE:
584            if cbs != PETSC_DECIDE:
585                CHKERR(MatSetBlockSizes(self.mat, rbs, cbs))
586            else:
587                CHKERR(MatSetBlockSize(self.mat, rbs))
588
589    def setBlockSize(self, bsize: int) -> None:
590        """Set the matrix block size (same for rows and columns).
591
592        Logically collective.
593
594        Parameters
595        ----------
596        bsize
597            Block size.
598
599        See Also
600        --------
601        setBlockSizes, setSizes, petsc.MatSetBlockSize
602
603        """
604        cdef PetscInt bs = asInt(bsize)
605        CHKERR(MatSetBlockSize(self.mat, bs))
606
607    def setBlockSizes(self, row_bsize: int, col_bsize: int) -> None:
608        """Set the row and column block sizes.
609
610        Logically collective.
611
612        Parameters
613        ----------
614        row_bsize
615            Row block size.
616        col_bsize
617            Column block size.
618
619        See Also
620        --------
621        setBlockSize, setSizes, petsc.MatSetBlockSizes
622
623        """
624        cdef PetscInt rbs = asInt(row_bsize)
625        cdef PetscInt cbs = asInt(col_bsize)
626        CHKERR(MatSetBlockSizes(self.mat, rbs, cbs))
627
628    def setVariableBlockSizes(self, blocks: Sequence[int]) -> None:
629        """Set diagonal point-blocks of the matrix.
630
631        Not collective.
632
633        See Also
634        --------
635        setBlockSize, petsc.MatSetVariableBlockSizes
636
637        """
638        cdef PetscInt nb=0, *b=NULL
639        iarray_i(blocks, &nb, &b)
640        CHKERR(MatSetVariableBlockSizes(self.mat, nb, b))
641
642    def setVecType(self, vec_type: Vec.Type | str) -> None:
643        """Set the vector type.
644
645        Collective.
646
647        Parameters
648        ----------
649        vec_type
650            Vector type used when creating vectors with `createVecs`.
651
652        See Also
653        --------
654        getVecType, petsc.MatSetVecType
655
656        """
657        cdef PetscVecType cval = NULL
658        vec_type = str2bytes(vec_type, &cval)
659        CHKERR(MatSetVecType(self.mat, cval))
660
661    def getVecType(self) -> str:
662        """Return the vector type used by the matrix.
663
664        Not collective.
665
666        See Also
667        --------
668        setVecType, petsc.MatGetVecType
669
670        """
671        cdef PetscVecType cval = NULL
672        CHKERR(MatGetVecType(self.mat, &cval))
673        return bytes2str(cval)
674
675    def setNestVecType(self, vec_type: Vec.Type | str) -> None:
676        """Set the vector type for a `Type.NEST` matrix.
677
678        Collective.
679
680        Parameters
681        ----------
682        vec_type
683            Vector type used when creating vectors with `createVecs`.
684
685        See Also
686        --------
687        getVecType, petsc.MatNestSetVecType
688
689        """
690        cdef PetscVecType cval = NULL
691        vec_type = str2bytes(vec_type, &cval)
692        CHKERR(MatNestSetVecType(self.mat, cval))
693
694    #
695
696    def createAIJ(
697        self,
698        size: MatSizeSpec,
699        bsize: MatBlockSizeSpec | None = None,
700        nnz: NNZSpec | None = None,
701        csr: CSRIndicesSpec | None = None,
702        comm: Comm | None = None) -> Self:
703        """Create a sparse `Type.AIJ` matrix, optionally preallocating.
704
705        Collective.
706
707        To preallocate the matrix the user can either pass ``nnz`` or ``csr``
708        describing the sparsity. If neither is set then preallocation will not
709        occur. Consult the `PETSc manual <petsc:sec_matsparse>` for
710        more information.
711
712        Parameters
713        ----------
714        size
715            Matrix size.
716        bsize
717            Matrix block size. If `None`, a block size of ``1`` is set.
718        nnz
719            Optional non-zeros preallocation pattern.
720        csr
721            Optional compressed sparse row layout information.
722            If provided, it takes precedence on ``nnz``.
723        comm
724            MPI communicator, defaults to `Sys.getDefaultComm`.
725
726        See Also
727        --------
728        setSizes, createBAIJ, petsc.MATAIJ, petsc.MATSEQAIJ, petsc.MATMPIAIJ
729        petsc.MatCreateAIJ, petsc.MatSeqAIJSetPreallocation
730        petsc.MatSeqAIJSetPreallocationCSR
731
732        """
733        # create matrix
734        cdef PetscMat newmat = NULL
735        Mat_Create(MATAIJ, comm, size, bsize, &newmat)
736        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
737        # preallocate matrix
738        Mat_AllocAIJ(self.mat, nnz, csr)
739        return self
740
741    def createBAIJ(
742        self,
743        size: MatSizeSpec,
744        bsize: MatBlockSizeSpec,
745        nnz: NNZSpec | None = None,
746        csr: CSRIndicesSpec | None = None,
747        comm: Comm | None = None) -> Self:
748        """Create a sparse blocked `Type.BAIJ` matrix, optionally preallocating.
749
750        Collective.
751
752        To preallocate the matrix the user can either pass ``nnz`` or ``csr``
753        describing the sparsity. If neither is set then preallocation will not
754        occur. Consult the `PETSc manual <petsc:sec_matsparse>` for
755        more information.
756
757        Parameters
758        ----------
759        size
760            Matrix size.
761        bsize
762            Matrix block size.
763        nnz
764            Optional non-zeros preallocation pattern for block rows.
765        csr
766            Optional block-compressed sparse row layout information.
767            If provided, it takes precedence on ``nnz``.
768        comm
769            MPI communicator, defaults to `Sys.getDefaultComm`.
770
771        See Also
772        --------
773        setSizes, createAIJ, petsc.MATBAIJ, petsc.MATSEQBAIJ
774        petsc.MATMPIBAIJ, petsc.MatCreateBAIJ
775
776        """
777        # create matrix
778        cdef PetscMat newmat = NULL
779        Mat_Create(MATBAIJ, comm, size, bsize, &newmat)
780        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
781        # preallocate matrix
782        Mat_AllocAIJ(self.mat, nnz, csr)
783        return self
784
785    def createSBAIJ(
786        self,
787        size: MatSizeSpec,
788        bsize: MatBlockSizeSpec,
789        nnz: NNZSpec | None = None,
790        csr: CSRIndicesSpec | None = None,
791        comm: Comm | None = None) -> Self:
792        """Create a sparse `Type.SBAIJ` matrix in symmetric block format.
793
794        Collective.
795
796        To preallocate the matrix the user can either pass ``nnz`` or ``csr``
797        describing the sparsity. If neither is set then preallocation will not
798        occur. Consult the `PETSc manual <petsc:sec_matsparse>` for
799        more information.
800
801        Parameters
802        ----------
803        size
804            Matrix size.
805        bsize
806            Matrix block size.
807        nnz
808            Optional upper-triangular (including diagonal)
809            non-zeros preallocation pattern for block rows.
810        csr
811            Optional block-compressed sparse row layout information.
812            If provided, it takes precedence on ``nnz``.
813        comm
814            MPI communicator, defaults to `Sys.getDefaultComm`.
815
816        See Also
817        --------
818        createAIJ, createBAIJ, petsc.MatCreateSBAIJ
819
820        """
821        # create matrix
822        cdef PetscMat newmat = NULL
823        Mat_Create(MATSBAIJ, comm, size, bsize, &newmat)
824        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
825        # preallocate matrix
826        Mat_AllocAIJ(self.mat, nnz, csr)
827        return self
828
829    def createAIJCRL(
830        self,
831        size: MatSizeSpec,
832        bsize: MatBlockSizeSpec | None = None,
833        nnz: NNZSpec | None = None,
834        csr: CSRIndicesSpec | None = None,
835        comm: Comm | None = None) -> Self:
836        """Create a sparse `Type.AIJCRL` matrix.
837
838        Collective.
839
840        This is similar to `Type.AIJ` matrices but stores some additional
841        information that improves vectorization for the matrix-vector product.
842
843        To preallocate the matrix the user can either pass ``nnz`` or ``csr``
844        describing the sparsity. If neither is set then preallocation will not
845        occur. Consult the `PETSc manual <petsc:sec_matsparse>` for
846        more information.
847
848        Parameters
849        ----------
850        size
851            Matrix size.
852        bsize
853            Matrix block size. If `None`, a block size of ``1`` is set.
854        nnz
855            Optional non-zeros preallocation pattern.
856        csr
857            Optional compressed sparse row layout information.
858            If provided, it takes precedence on ``nnz``.
859        comm
860            MPI communicator, defaults to `Sys.getDefaultComm`.
861
862        See Also
863        --------
864        createAIJ, createBAIJ, petsc.MatCreateSeqAIJCRL
865        petsc.MatCreateMPIAIJCRL
866
867        """
868        # create matrix
869        cdef PetscMat newmat = NULL
870        Mat_Create(MATAIJCRL, comm, size, bsize, &newmat)
871        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
872        # preallocate matrix
873        Mat_AllocAIJ(self.mat, nnz, csr)
874        return self
875
876    def setPreallocationNNZ(self, nnz: NNZSpec) -> Self:
877        """Preallocate memory for the matrix with a non-zero pattern.
878
879        Collective.
880
881        Correct preallocation can result in a dramatic reduction in matrix
882        assembly time.
883
884        Parameters
885        ----------
886        nnz
887            The number of non-zeros per row for the local portion of the matrix,
888            or a 2-tuple for the on-process and off-process part of the matrix.
889
890        See Also
891        --------
892        setPreallocationCSR, createAIJ, petsc.MatSeqAIJSetPreallocation
893        petsc.MatMPIAIJSetPreallocation
894
895        """
896        cdef PetscBool done = PETSC_FALSE
897        CHKERR(MatIsPreallocated(self.mat, &done))
898        # if done: raise Error(PETSC_ERR_ORDER)
899        Mat_AllocAIJ_NNZ(self.mat, nnz)
900        return self
901
902    def setPreallocationCOO(self, coo_i: Sequence[int], coo_j: Sequence[int]) -> Self:
903        """Set preallocation using coordinate format with global indices.
904
905        Collective.
906
907        Parameters
908        ----------
909        coo_i
910            Row indices in COO format.
911        coo_j
912            Column indices in COO format.
913
914        See Also
915        --------
916        setValuesCOO, setPreallocationNNZ, setPreallocationCSR
917        petsc.MatSetPreallocationCOO
918
919        """
920        cdef PetscInt ncoo_i = 0, ncoo_j = 0
921        cdef PetscInt *ccoo_i = NULL, *ccoo_j = NULL
922        cdef PetscCount ncoo = 0
923
924        coo_i = iarray_i(coo_i, &ncoo_i, &ccoo_i)
925        coo_j = iarray_i(coo_j, &ncoo_j, &ccoo_j)
926
927        if ncoo_i != ncoo_j:
928            raise ValueError("coo_i and coo_j must have the same length")
929
930        ncoo = <PetscCount> ncoo_i
931        CHKERR(MatSetPreallocationCOO(self.mat, ncoo, ccoo_i, ccoo_j))
932        return self
933
934    def setPreallocationCOOLocal(self, coo_i: Sequence[int], coo_j: Sequence[int]) -> Self:
935        """Set preallocation using coordinate format with local indices.
936
937        Collective.
938
939        Parameters
940        ----------
941        coo_i
942            Row indices in COO format.
943        coo_j
944            Column indices in COO format.
945
946        See Also
947        --------
948        setPreallocationCOO, setValuesCOO, setLGMap
949        petsc.MatSetPreallocationCOOLocal, petsc.MatSetPreallocationCOOLocal
950
951        """
952        cdef PetscInt ncoo_i = 0, ncoo_j = 0
953        cdef PetscInt *ccoo_i = NULL, *ccoo_j = NULL
954        cdef PetscCount ncoo = 0
955
956        coo_i = iarray_i(coo_i, &ncoo_i, &ccoo_i)
957        coo_j = iarray_i(coo_j, &ncoo_j, &ccoo_j)
958
959        if ncoo_i != ncoo_j:
960            raise ValueError("coo_i and coo_j must have the same length")
961
962        ncoo = <PetscCount> ncoo_i
963        CHKERR(MatSetPreallocationCOOLocal(self.mat, ncoo, ccoo_i, ccoo_j))
964        return self
965
966    def setPreallocationCSR(self, csr: CSRIndicesSpec) -> Self:
967        """Preallocate memory for the matrix with a CSR layout.
968
969        Collective.
970
971        Correct preallocation can result in a dramatic reduction in matrix
972        assembly time.
973
974        Parameters
975        ----------
976        csr
977            Local matrix data in compressed sparse row layout format.
978
979        Notes
980        -----
981        Must use the block-compressed form with `Type.BAIJ` and `Type.SBAIJ`.
982
983        See Also
984        --------
985        setPreallocationNNZ, createAIJ, createBAIJ, createSBAIJ
986        petsc.MatSeqAIJSetPreallocationCSR
987        petsc.MatMPIAIJSetPreallocationCSR
988        petsc.MatSeqBAIJSetPreallocationCSR
989        petsc.MatMPIBAIJSetPreallocationCSR
990        petsc.MatSeqSBAIJSetPreallocationCSR
991        petsc.MatMPISBAIJSetPreallocationCSR
992
993        """
994        cdef PetscBool done = PETSC_FALSE
995        CHKERR(MatIsPreallocated(self.mat, &done))
996        # if done: raise Error(PETSC_ERR_ORDER)
997        Mat_AllocAIJ_CSR(self.mat, csr)
998        return self
999
1000    def preallocatorPreallocate(self, Mat A, fill: bool = True) -> None:
1001        """Preallocate memory for a matrix using a preallocator matrix.
1002
1003        Collective.
1004
1005        The current matrix (``self``) must be of type `Type.PREALLOCATOR`.
1006
1007        Parameters
1008        ----------
1009        A
1010            The matrix to be preallocated.
1011        fill
1012            Flag indicating whether or not to insert zeros into
1013            the newly allocated matrix, defaults to `True`.
1014
1015        See Also
1016        --------
1017        petsc.MatPreallocatorPreallocate
1018
1019        """
1020        cdef PetscBool cfill = asBool(fill)
1021        CHKERR(MatPreallocatorPreallocate(self.mat, cfill, A.mat))
1022
1023    def createAIJWithArrays(
1024        self,
1025        size: MatSizeSpec,
1026        csr: CSRSpec | tuple[CSRSpec, CSRSpec],
1027        bsize: MatBlockSizeSpec | None = None,
1028        comm: Comm | None = None) -> Self:
1029        """Create a sparse `Type.AIJ` matrix with data in CSR format.
1030
1031        Collective.
1032
1033        Parameters
1034        ----------
1035        size
1036            Matrix size.
1037        csr
1038            Local matrix data in compressed sparse row format.
1039        bsize
1040            Matrix block size. If `None`, a block size of ``1`` is set.
1041        comm
1042            MPI communicator, defaults to `Sys.getDefaultComm`.
1043
1044        Notes
1045        -----
1046        For `Type.SEQAIJ` matrices, the ``csr`` data is not copied.
1047        For `Type.MPIAIJ` matrices, the ``csr`` data is not copied only
1048        in the case it represents on-process and off-process information.
1049
1050        See Also
1051        --------
1052        createAIJ, petsc.MatCreateSeqAIJWithArrays
1053        petsc.MatCreateMPIAIJWithArrays, petsc.MatCreateMPIAIJWithSplitArrays
1054
1055        """
1056        # communicator
1057        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
1058        # sizes and block sizes
1059        cdef PetscInt rbs = 0, cbs = 0, m = 0, n = 0, M = 0, N = 0
1060        Mat_Sizes(size, bsize, &rbs, &cbs, &m, &n, &M, &N)
1061        if rbs == PETSC_DECIDE: rbs = 1
1062        if cbs == PETSC_DECIDE: cbs = rbs
1063        Sys_Layout(ccomm, rbs, &m, &M)
1064        Sys_Layout(ccomm, cbs, &n, &N)
1065        # unpack CSR argument
1066        cdef object pi, pj, pv, poi, poj, pov
1067        try:
1068            (pi, pj, pv), (poi, poj, pov) = csr
1069        except (TypeError, ValueError):
1070            pi, pj, pv = csr
1071            poi = poj = pov = None
1072        # rows, cols, and values
1073        cdef PetscInt ni=0, noi=0, *i=NULL, *oi=NULL
1074        cdef PetscInt nj=0, noj=0, *j=NULL, *oj=NULL
1075        pi = iarray_i(pi, &ni, &i) # Row pointers (diagonal)
1076        pj = iarray_i(pj, &nj, &j) # Column indices (diagonal)
1077        if ni != m+1:  raise ValueError(
1078            "A matrix with %d rows requires a row pointer of length %d (given: %d)" %
1079            (toInt(m), toInt(m+1), toInt(ni)))
1080        if poi is not None and poj is not None:
1081            poi = iarray_i(poi, &noi, &oi) # Row pointers (off-diagonal)
1082            poj = iarray_i(poj, &noj, &oj) # Column indices (off-diagonal)
1083        cdef PetscInt nv=0, nov=0
1084        cdef PetscScalar *v=NULL, *ov=NULL
1085        pv = iarray_s(pv, &nv, &v) # Non-zero values (diagonal)
1086        if nj != nv:  raise ValueError(
1087            "Given %d column indices but %d non-zero values" %
1088            (toInt(nj), toInt(nv)))
1089        if pov is not None:
1090            pov = iarray_s(pov, &nov, &ov) # Non-zero values (off-diagonal)
1091        # create matrix
1092        cdef PetscMat newmat = NULL
1093        if comm_size(ccomm) == 1:
1094            CHKERR(MatCreateSeqAIJWithArrays(
1095                ccomm, m, n, i, j, v, &newmat))
1096            csr = (pi, pj, pv)
1097        else:
1098            # if off-diagonal components are provided then SplitArrays can be
1099            # used (and not cause a copy).
1100            if oi != NULL and oj != NULL and ov != NULL:
1101                CHKERR(MatCreateMPIAIJWithSplitArrays(
1102                    ccomm, m, n, M, N, i, j, v, oi, oj, ov, &newmat))
1103                csr = ((pi, pj, pv), (poi, poj, pov))
1104            else:
1105                CHKERR(MatCreateMPIAIJWithArrays(
1106                    ccomm, m, n, M, N, i, j, v, &newmat))
1107                csr = None
1108        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1109        self.set_attr('__csr__', csr)
1110        return self
1111
1112    #
1113
1114    def createDense(
1115        self,
1116        size: MatSizeSpec,
1117        bsize: MatBlockSizeSpec | None = None,
1118        array: Sequence[Scalar] | None = None,
1119        comm: Comm | None = None) -> Self:
1120        """Create a `Type.DENSE` matrix.
1121
1122        Collective.
1123
1124        Parameters
1125        ----------
1126        size
1127            Matrix size.
1128        bsize
1129            Matrix block size. If `None`, a block size of ``1`` is set.
1130        array
1131            Optional matrix data. If `None`, memory is internally allocated.
1132        comm
1133            MPI communicator, defaults to `Sys.getDefaultComm`.
1134
1135        See Also
1136        --------
1137        createDenseCUDA, petsc.MATDENSE, petsc.MatCreateDense
1138
1139        """
1140        # create matrix
1141        cdef PetscMat newmat = NULL
1142        Mat_Create(MATDENSE, comm, size, bsize, &newmat)
1143        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1144        # preallocate matrix
1145        if array is not None:
1146            array = Mat_AllocDense(self.mat, array)
1147            self.set_attr('__array__', array)
1148        return self
1149
1150    def createDenseCUDA(
1151        self,
1152        size: MatSizeSpec,
1153        bsize: MatBlockSizeSpec | None = None,
1154        array: Sequence[Scalar] | None = None,
1155        cudahandle: int | None = None,
1156        comm: Comm | None = None) -> Self:
1157        """Create a `Type.DENSECUDA` matrix with optional host and device data.
1158
1159        Collective.
1160
1161        Parameters
1162        ----------
1163        size
1164            Matrix size.
1165        bsize
1166            Matrix block size. If `None`, a block size of ``1`` is set.
1167        array
1168            Host data. Will be lazily allocated if `None`.
1169        cudahandle
1170            Address of the array on the GPU. Will be lazily allocated if
1171            `None`. If ``cudahandle`` is provided, ``array`` will be
1172            ignored.
1173        comm
1174            MPI communicator, defaults to `Sys.getDefaultComm`.
1175
1176        See Also
1177        --------
1178        createDense, petsc.MatCreateDenseCUDA
1179
1180        """
1181        # create matrix
1182        cdef PetscMat newmat = NULL
1183        # communicator
1184        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
1185        # sizes and block sizes
1186        cdef PetscInt rbs = 0, cbs = 0, m = 0, n = 0, M = 0, N = 0
1187
1188        # FIXME handle the case of array not None?
1189        if cudahandle is not None:
1190            Mat_Sizes(size, None, &rbs, &cbs, &m, &n, &M, &N)
1191            if rbs == PETSC_DECIDE: rbs = 1
1192            if cbs == PETSC_DECIDE: cbs = rbs
1193            Sys_Layout(ccomm, rbs, &m, &M)
1194            Sys_Layout(ccomm, cbs, &n, &N)
1195            # create matrix and set sizes
1196            CHKERR(MatCreateDenseCUDA(ccomm, m, n, M, N, <PetscScalar*>(<Py_uintptr_t>cudahandle), &newmat))
1197            # Does block size make sense for MATDENSE?
1198            CHKERR(MatSetBlockSizes(newmat, rbs, cbs))
1199        else:
1200            Mat_Create(MATDENSECUDA, comm, size, bsize, &newmat)
1201            if array is not None:
1202                array = Mat_AllocDense(self.mat, array)
1203                self.set_attr('__array__', array)
1204        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1205        return self
1206
1207    def setPreallocationDense(self, array: Sequence[Scalar]) -> Self:
1208        """Set the array used for storing matrix elements for a dense matrix.
1209
1210        Collective.
1211
1212        Parameters
1213        ----------
1214        array
1215            Array that will be used to store matrix data.
1216
1217        See Also
1218        --------
1219        petsc.MatSeqDenseSetPreallocation, petsc.MatMPIDenseSetPreallocation
1220
1221        """
1222        cdef PetscBool done = PETSC_FALSE
1223        CHKERR(MatIsPreallocated(self.mat, &done))
1224        # if done: raise Error(PETSC_ERR_ORDER)
1225        array = Mat_AllocDense(self.mat, array)
1226        self.set_attr('__array__', array)
1227        return self
1228
1229    #
1230
1231    def createScatter(self, Scatter scatter, comm: Comm | None = None) -> Self:
1232        """Create a `Type.SCATTER` matrix from a vector scatter.
1233
1234        Collective.
1235
1236        Parameters
1237        ----------
1238        scatter
1239            Vector scatter.
1240        comm
1241            MPI communicator, defaults to `Sys.getDefaultComm`.
1242
1243        See Also
1244        --------
1245        petsc.MATSCATTER, petsc.MatCreateScatter
1246
1247        """
1248        if comm is None: comm = scatter.getComm()
1249        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
1250        cdef PetscMat newmat = NULL
1251        CHKERR(MatCreateScatter(ccomm, scatter.sct, &newmat))
1252        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1253        return self
1254
1255    def createNormal(self, Mat mat) -> Self:
1256        """Create a `Type.NORMAL` matrix representing AᵀA.
1257
1258        Collective.
1259
1260        Parameters
1261        ----------
1262        mat
1263            The (possibly rectangular) matrix A.
1264
1265        Notes
1266        -----
1267        The product AᵀA is never actually formed. Instead A and Aᵀ are used
1268        during `mult` and various other matrix operations.
1269
1270        See Also
1271        --------
1272        petsc.MATNORMAL, petsc.MatCreateNormal
1273
1274        """
1275        cdef PetscMat newmat = NULL
1276        CHKERR(MatCreateNormal(mat.mat, &newmat))
1277        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1278        return self
1279
1280    def createTranspose(self, Mat mat) -> Self:
1281        """Create a `Type.TRANSPOSE` matrix that behaves like Aᵀ.
1282
1283        Collective.
1284
1285        Parameters
1286        ----------
1287        mat
1288            Matrix A to represent the transpose of.
1289
1290        Notes
1291        -----
1292        The transpose is never actually formed. Instead `multTranspose` is
1293        called whenever the matrix-vector product is computed.
1294
1295        See Also
1296        --------
1297        createNormal, petsc.MatCreateTranspose
1298
1299        """
1300        cdef PetscMat newmat = NULL
1301        CHKERR(MatCreateTranspose(mat.mat, &newmat))
1302        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1303        return self
1304
1305    def getTransposeMat(self) -> Mat:
1306        """Return the internal matrix of a `Type.TRANSPOSE` matrix.
1307
1308        Not collective.
1309
1310        Parameters
1311        ----------
1312        mat
1313            Matrix A of type `Type.TRANSPOSE`.
1314
1315        See Also
1316        --------
1317        petsc.MatTransposeGetMat
1318
1319        """
1320        cdef Mat mat = type(self)()
1321        CHKERR(MatTransposeGetMat(self.mat, &mat.mat))
1322        CHKERR(PetscINCREF(mat.obj))
1323        return mat
1324
1325    def createNormalHermitian(self, Mat mat) -> Self:
1326        """Create a `Type.NORMALHERMITIAN` matrix representing (A*)ᵀA.
1327
1328        Collective.
1329
1330        Parameters
1331        ----------
1332        mat
1333            The (possibly rectangular) matrix A.
1334
1335        Notes
1336        -----
1337        The product (A*)ᵀA is never actually formed.
1338
1339        See Also
1340        --------
1341        createHermitianTranspose, petsc.MATNORMAL, petsc.MATNORMALHERMITIAN
1342        petsc.MatCreateNormalHermitian
1343
1344        """
1345        cdef PetscMat newmat = NULL
1346        CHKERR(MatCreateNormalHermitian(mat.mat, &newmat))
1347        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1348        return self
1349
1350    def createHermitianTranspose(self, Mat mat) -> Self:
1351        """Create a `Type.HERMITIANTRANSPOSE` matrix that behaves like (A*)ᵀ.
1352
1353        Collective.
1354
1355        Parameters
1356        ----------
1357        mat
1358            Matrix A to represent the Hermitian transpose of.
1359
1360        Notes
1361        -----
1362        The Hermitian transpose is never actually formed.
1363
1364        See Also
1365        --------
1366        createNormal, createNormalHermitian
1367        petsc.MATHERMITIANTRANSPOSEVIRTUAL, petsc.MatCreateHermitianTranspose
1368
1369        """
1370        cdef PetscMat newmat = NULL
1371        CHKERR(MatCreateHermitianTranspose(mat.mat, &newmat))
1372        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1373        return self
1374
1375    def createLRC(
1376        self,
1377        Mat A or None: Mat | None,
1378        Mat U,
1379        Vec c or None: Vec | None,
1380        Mat V or None: Mat | None) -> Self:
1381        """Create a low-rank correction `Type.LRC` matrix representing A + UCVᵀ.
1382
1383        Collective.
1384
1385        Parameters
1386        ----------
1387        A
1388            Sparse matrix, can be `None`.
1389        U
1390            Dense rectangular matrix.
1391        c
1392            Vector containing the diagonal of ``C``, can be `None`.
1393        V
1394            Dense rectangular matrix, can be set to ``U`` or 'None'.
1395
1396        Notes
1397        -----
1398        The matrix A + UCVᵀ is never actually formed.
1399
1400        C is a diagonal matrix (represented as a vector) of order k, where k
1401        is the number of columns of both ``U`` and ``V``.
1402
1403        If A is `None` then the new object behaves like a low-rank matrix UCVᵀ.
1404
1405        Use the same matrix for ``V`` and ``U`` (or ``V=None``) for a symmetric
1406        low-rank correction, A + UCUᵀ.
1407
1408        If ``c`` is `None` then the low-rank correction is just U*Vᵀ. If a
1409        sequential ``c`` vector is used for a parallel matrix, PETSc assumes
1410        that the values of the vector are consistently set across processors.
1411
1412        See Also
1413        --------
1414        petsc.MATLRC, petsc.MatCreateLRC
1415
1416        """
1417        cdef PetscMat Amat = NULL
1418        cdef PetscMat Umat = U.mat
1419        cdef PetscVec cvec = NULL
1420        cdef PetscMat Vmat = NULL
1421        cdef PetscMat newmat = NULL
1422        if A is not None: Amat = A.mat
1423        if c is not None: cvec = c.vec
1424        if V is not None: Vmat = V.mat
1425        CHKERR(MatCreateLRC(Amat, Umat, cvec, Vmat, &newmat))
1426        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1427        return self
1428
1429    def createSubMatrixVirtual(self, Mat A, IS isrow, IS iscol=None) -> Self:
1430        """Create a `Type.SUBMATRIX` matrix that acts as a submatrix.
1431
1432        Collective.
1433
1434        Parameters
1435        ----------
1436        A
1437            Matrix to extract submatrix from.
1438        isrow
1439            Rows present in the submatrix.
1440        iscol
1441            Columns present in the submatrix, defaults to ``isrow``.
1442
1443        See Also
1444        --------
1445        petsc.MatCreateSubMatrixVirtual
1446
1447        """
1448        if iscol is None: iscol = isrow
1449        cdef PetscMat newmat = NULL
1450        CHKERR(MatCreateSubMatrixVirtual(A.mat, isrow.iset, iscol.iset, &newmat))
1451        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1452        return self
1453
1454    def createNest(
1455        self,
1456        mats: Sequence[Sequence[Mat]],
1457        isrows: Sequence[IS] | None = None,
1458        iscols: Sequence[IS] | None = None,
1459        comm: Comm | None = None) -> Self:
1460        """Create a `Type.NEST` matrix containing multiple submatrices.
1461
1462        Collective.
1463
1464        Parameters
1465        ----------
1466        mats
1467            Iterable of matrix block rows with size ``len(isrows)``.
1468            Each matrix block row must be of size ``len(iscols)``.
1469            Empty submatrices can be set with `None`.
1470        isrows
1471            Index set for each nested row block, defaults to contiguous
1472            ordering.
1473        iscols
1474            Index set for each nested column block, defaults to contiguous
1475            ordering.
1476        comm
1477            MPI communicator, defaults to `Sys.getDefaultComm`.
1478
1479        See Also
1480        --------
1481        petsc.MatCreateNest, petsc.MATNEST
1482
1483        """
1484        cdef object mat
1485        mats = [list(mat) for mat in mats]
1486        if isrows:
1487            isrows = list(isrows)
1488            assert len(isrows) == len(mats)
1489        else:
1490            isrows = None
1491        if iscols:
1492            iscols = list(iscols)
1493            assert len(iscols) == len(mats[0])
1494        else:
1495            iscols = None
1496        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
1497        cdef Py_ssize_t i, mr = len(mats)
1498        cdef Py_ssize_t j, mc = len(mats[0])
1499        cdef PetscInt nr = <PetscInt>mr
1500        cdef PetscInt nc = <PetscInt>mc
1501        cdef PetscMat *cmats   = NULL
1502        cdef PetscIS  *cisrows = NULL
1503        cdef PetscIS  *ciscols = NULL
1504        cdef object unused1, unused2, unused3
1505        unused1 = oarray_p(empty_p(nr*nc), NULL, <void**>&cmats)
1506        for i from 0 <= i < mr:
1507            for j from 0 <= j < mc:
1508                mat = mats[i][j]
1509                cmats[i*mc+j] = (<Mat?>mat).mat if mat is not None else NULL
1510        if isrows is not None:
1511            unused2 = oarray_p(empty_p(nr), NULL, <void**>&cisrows)
1512            for i from 0 <= i < mr: cisrows[i] = (<IS?>isrows[i]).iset
1513        if iscols is not None:
1514            unused3 = oarray_p(empty_p(nc), NULL, <void**>&ciscols)
1515            for j from 0 <= j < mc: ciscols[j] = (<IS?>iscols[j]).iset
1516        cdef PetscMat newmat = NULL
1517        CHKERR(MatCreateNest(ccomm, nr, cisrows, nc, ciscols, cmats, &newmat))
1518        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1519        return self
1520
1521    def createH2OpusFromMat(
1522        self,
1523        Mat A,
1524        coordinates: Sequence[Scalar] | None = None,
1525        dist: bool | None = None,
1526        eta: float | None = None,
1527        leafsize: int | None = None,
1528        maxrank: int | None = None,
1529        bs: int | None = None,
1530        rtol: float | None = None) -> Self:
1531        """Create a hierarchical `Type.H2OPUS` matrix sampling from a provided operator.
1532
1533        Collective.
1534
1535        Parameters
1536        ----------
1537        A
1538            Matrix to be sampled.
1539        coordinates
1540            Coordinates of the points.
1541        dist
1542            Whether or not coordinates are distributed, defaults to `False`.
1543        eta
1544            Admissibility condition tolerance, defaults to `DECIDE`.
1545        leafsize
1546            Leaf size in cluster tree, defaults to `DECIDE`.
1547        maxrank
1548            Maximum rank permitted, defaults to `DECIDE`.
1549        bs
1550            Maximum number of samples to take concurrently, defaults to
1551            `DECIDE`.
1552        rtol
1553            Relative tolerance for construction, defaults to `DECIDE`.
1554
1555        Notes
1556        -----
1557        See `petsc.MatCreateH2OpusFromMat` for the appropriate database
1558        options.
1559
1560        See Also
1561        --------
1562        petsc_options, petsc.MatCreateH2OpusFromMat
1563
1564        """
1565        cdef PetscInt cdim = 1
1566        cdef PetscReal *coords = NULL
1567        cdef PetscBool cdist = PETSC_FALSE
1568        cdef PetscReal peta = PETSC_DECIDE
1569        cdef PetscInt lsize = PETSC_DECIDE
1570        cdef PetscInt maxr = PETSC_DECIDE
1571        cdef PetscInt pbs = PETSC_DECIDE
1572        cdef PetscReal tol = PETSC_DECIDE
1573        cdef ndarray xyz
1574        cdef PetscInt nvtx
1575        cdef PetscInt rl = 0, cl = 0
1576        if dist is not None: cdist = asBool(dist)
1577        if eta is not None: peta = asReal(eta)
1578        if leafsize is not None: lsize = asInt(leafsize)
1579        if maxrank is not None: maxr = asInt(maxrank)
1580        if bs is not None: pbs = asInt(bs)
1581        if rtol is not None: tol = asReal(rtol)
1582
1583        if coordinates is not None:
1584            xyz = iarray(coordinates, NPY_PETSC_REAL)
1585            if PyArray_ISFORTRAN(xyz): xyz = PyArray_Copy(xyz)
1586            if PyArray_NDIM(xyz) != 2: raise ValueError(
1587                ("coordinates must have two dimensions: "
1588                 "coordinates.ndim=%d") % (PyArray_NDIM(xyz)))
1589            nvtx = <PetscInt> PyArray_DIM(xyz, 0)
1590            CHKERR(MatGetLocalSize(A.mat, &rl, &cl))
1591            if cl != rl: raise ValueError("Not for rectangular matrices")
1592            if nvtx < rl: raise ValueError(
1593                ("coordinates size must be at least %d" % rl))
1594            cdim = <PetscInt> PyArray_DIM(xyz, 1)
1595            coords = <PetscReal*> PyArray_DATA(xyz)
1596
1597        cdef PetscMat newmat = NULL
1598        CHKERR(MatCreateH2OpusFromMat(A.mat, cdim, coords, cdist, peta, lsize, maxr, pbs, tol, &newmat))
1599        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1600        return self
1601
1602    def createIS(
1603        self,
1604        size: MatSizeSpec,
1605        bsize: MatBlockSizeSpec | None = None,
1606        LGMap lgmapr = None,
1607        LGMap lgmapc = None,
1608        comm: Comm | None = None) -> Self:
1609        """Create a `Type.IS` matrix representing globally unassembled operators.
1610
1611        Collective.
1612
1613        Parameters
1614        ----------
1615        size
1616            Matrix size.
1617        bsize
1618            Matrix block size. If `None`, a block size of ``1`` is set.
1619        lgmapr
1620            Optional local-to-global mapping for the rows.
1621            If `None`, the local row space matches the global row space.
1622        lgmapc
1623            Optional local-to-global mapping for the columns.
1624            If `None`, the local column space matches the global column space.
1625        comm
1626            MPI communicator, defaults to `Sys.getDefaultComm`.
1627
1628        See Also
1629        --------
1630        petsc.MATIS
1631
1632        """
1633        # communicator and sizes
1634        if comm is None and lgmapr is not None: comm = lgmapr.getComm()
1635        if comm is None and lgmapc is not None: comm = lgmapc.getComm()
1636        cdef PetscLGMap lgmr = NULL
1637        cdef PetscLGMap lgmc = NULL
1638        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
1639        cdef PetscInt rbs = 0, cbs = 0, m = 0, n = 0, M = 0, N = 0
1640        Mat_Sizes(size, bsize, &rbs, &cbs, &m, &n, &M, &N)
1641        Sys_Layout(ccomm, rbs, &m, &M)
1642        Sys_Layout(ccomm, cbs, &n, &N)
1643        # create matrix
1644        cdef PetscMat newmat = NULL
1645        cdef PetscInt bs = 1
1646        if rbs == cbs: bs = rbs
1647        if lgmapr is not None:
1648            lgmr = lgmapr.lgm
1649        if lgmapc is not None:
1650            lgmc = lgmapc.lgm
1651        CHKERR(MatCreateIS(ccomm, bs, m, n, M, N, lgmr, lgmc, &newmat))
1652        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1653        return self
1654
1655    def createConstantDiagonal(
1656        self,
1657        size: MatSizeSpec,
1658        diag: float,
1659        comm: Comm | None = None) -> Self:
1660        """Create a diagonal matrix of type `Type.CONSTANTDIAGONAL`.
1661
1662        Collective.
1663
1664        Parameters
1665        ----------
1666        size
1667            Matrix size.
1668        diag
1669            The diagonal value.
1670        comm
1671            MPI communicator, defaults to `Sys.getDefaultComm`.
1672
1673        See Also
1674        --------
1675        createDiagonal
1676
1677        """
1678        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
1679        cdef PetscInt rbs = 0, cbs = 0, m = 0, n = 0, M = 0, N = 0
1680        Mat_Sizes(size, None, &rbs, &cbs, &m, &n, &M, &N)
1681        Sys_Layout(ccomm, rbs, &m, &M)
1682        Sys_Layout(ccomm, cbs, &n, &N)
1683        cdef PetscMat newmat = NULL
1684        CHKERR(MatCreateConstantDiagonal(ccomm, m, n, M, N, diag, &newmat))
1685        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1686        return self
1687
1688    def createDiagonal(
1689        self,
1690        Vec diag) -> Self:
1691        """Create a diagonal matrix of type `Type.DIAGONAL`.
1692
1693        Collective.
1694
1695        Parameters
1696        ----------
1697        diag
1698            The vector holding diagonal values.
1699
1700        See Also
1701        --------
1702        createConstantDiagonal
1703
1704        """
1705        cdef PetscVec dvec = diag.vec
1706        cdef PetscMat newmat = NULL
1707        CHKERR(MatCreateDiagonal(dvec, &newmat))
1708        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1709        return self
1710
1711    def createPython(self, size: MatSizeSpec, context: Any = None, comm: Comm | None = None) -> Self:
1712        """Create a `Type.PYTHON` matrix.
1713
1714        Collective.
1715
1716        Parameters
1717        ----------
1718        size
1719            Matrix size.
1720        context
1721            An instance of the Python class implementing the required methods.
1722        comm
1723            MPI communicator, defaults to `Sys.getDefaultComm`.
1724
1725        See Also
1726        --------
1727        petsc_python_mat, setType, setPythonContext, Type.PYTHON
1728
1729        """
1730        # communicator and sizes
1731        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
1732        cdef PetscInt rbs = 0, cbs = 0, m = 0, n = 0, M = 0, N = 0
1733        Mat_Sizes(size, None, &rbs, &cbs, &m, &n, &M, &N)
1734        Sys_Layout(ccomm, rbs, &m, &M)
1735        Sys_Layout(ccomm, cbs, &n, &N)
1736        # create matrix
1737        # FIXME: propagate block sizes?
1738        cdef PetscMat newmat = NULL
1739        CHKERR(MatCreate(ccomm, &newmat))
1740        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
1741        CHKERR(MatSetSizes(self.mat, m, n, M, N))
1742        CHKERR(MatSetType(self.mat, MATPYTHON))
1743        CHKERR(MatPythonSetContext(self.mat, <void*>context))
1744        if context:
1745            CHKERR(MatSetUp(self.mat))
1746        return self
1747
1748    def setPythonContext(self, context: Any) -> None:
1749        """Set the instance of the class implementing the required Python methods.
1750
1751        Logically collective.
1752
1753        Notes
1754        -----
1755        In order to use the matrix, `Mat.setUp` must be called after having set
1756        the context. Pass `None` to reset the matrix to its initial state.
1757
1758        See Also
1759        --------
1760        petsc_python_mat, getPythonContext, setPythonType
1761
1762        """
1763        CHKERR(MatPythonSetContext(self.mat, <void*>context))
1764
1765    def getPythonContext(self) -> Any:
1766        """Return the instance of the class implementing the required Python methods.
1767
1768        Not collective.
1769
1770        See Also
1771        --------
1772        petsc_python_mat, setPythonContext
1773
1774        """
1775        cdef void *context = NULL
1776        CHKERR(MatPythonGetContext(self.mat, &context))
1777        if context == NULL: return None
1778        else: return <object> context
1779
1780    def setPythonType(self, py_type: str) -> None:
1781        """Set the fully qualified Python name of the class to be used.
1782
1783        Collective.
1784
1785        Notes
1786        -----
1787        In order to use the matrix, `Mat.setUp` must be called after having set
1788        the type.
1789
1790        See Also
1791        --------
1792        petsc_python_mat, setPythonContext, getPythonType
1793        petsc.MatPythonSetType
1794
1795        """
1796        cdef const char *cval = NULL
1797        py_type = str2bytes(py_type, &cval)
1798        CHKERR(MatPythonSetType(self.mat, cval))
1799
1800    def getPythonType(self) -> str:
1801        """Return the fully qualified Python name of the class used by the matrix.
1802
1803        Not collective.
1804
1805        See Also
1806        --------
1807        petsc_python_mat, setPythonContext, setPythonType
1808        petsc.MatPythonGetType
1809
1810        """
1811        cdef const char *cval = NULL
1812        CHKERR(MatPythonGetType(self.mat, &cval))
1813        return bytes2str(cval)
1814
1815    #
1816
1817    def setOptionsPrefix(self, prefix: str | None = None) -> None:
1818        """Set the prefix used for searching for options in the database.
1819
1820        Logically collective.
1821
1822        See Also
1823        --------
1824        petsc_options, getOptionsPrefix, petsc.MatSetOptionsPrefix
1825
1826        """
1827        cdef const char *cval = NULL
1828        prefix = str2bytes(prefix, &cval)
1829        CHKERR(MatSetOptionsPrefix(self.mat, cval))
1830
1831    def getOptionsPrefix(self) -> str:
1832        """Return the prefix used for searching for options in the database.
1833
1834        Not collective.
1835
1836        See Also
1837        --------
1838        petsc_options, setOptionsPrefix, petsc.MatGetOptionsPrefix
1839
1840        """
1841        cdef const char *cval = NULL
1842        CHKERR(MatGetOptionsPrefix(self.mat, &cval))
1843        return bytes2str(cval)
1844
1845    def appendOptionsPrefix(self, prefix: str | None = None) -> None:
1846        """Append to the prefix used for searching for options in the database.
1847
1848        Logically collective.
1849
1850        See Also
1851        --------
1852        petsc_options, setOptionsPrefix, petsc.MatAppendOptionsPrefix
1853
1854        """
1855        cdef const char *cval = NULL
1856        prefix = str2bytes(prefix, &cval)
1857        CHKERR(MatAppendOptionsPrefix(self.mat, cval))
1858
1859    def setFromOptions(self) -> None:
1860        """Configure the matrix from the options database.
1861
1862        Collective.
1863
1864        See Also
1865        --------
1866        petsc_options, petsc.MatSetFromOptions
1867
1868        """
1869        CHKERR(MatSetFromOptions(self.mat))
1870
1871    def setUp(self) -> Self:
1872        """Set up the internal data structures for using the matrix.
1873
1874        Collective.
1875
1876        See Also
1877        --------
1878        petsc.MatSetUp
1879
1880        """
1881        CHKERR(MatSetUp(self.mat))
1882        return self
1883
1884    def setOption(self, option: Option, flag: bool) -> None:
1885        """Set option.
1886
1887        Collective.
1888
1889        See Also
1890        --------
1891        getOption, petsc.MatSetOption
1892
1893        """
1894        CHKERR(MatSetOption(self.mat, option, flag))
1895
1896    def getOption(self, option: Option) -> bool:
1897        """Return the option value.
1898
1899        Not collective.
1900
1901        See Also
1902        --------
1903        setOption, petsc.MatGetOption
1904
1905        """
1906        cdef PetscBool flag = PETSC_FALSE
1907        CHKERR(MatGetOption(self.mat, option, &flag))
1908        return toBool(flag)
1909
1910    def getType(self) -> str:
1911        """Return the type of the matrix.
1912
1913        Not collective.
1914
1915        See Also
1916        --------
1917        setType, Type, petsc.MatGetType
1918
1919        """
1920        cdef PetscMatType cval = NULL
1921        CHKERR(MatGetType(self.mat, &cval))
1922        return bytes2str(cval)
1923
1924    def getSize(self) -> tuple[int, int]:
1925        """Return the global number of rows and columns.
1926
1927        Not collective.
1928
1929        See Also
1930        --------
1931        getLocalSize, getSizes, petsc.MatGetSize
1932
1933        """
1934        cdef PetscInt M = 0, N = 0
1935        CHKERR(MatGetSize(self.mat, &M, &N))
1936        return (toInt(M), toInt(N))
1937
1938    def getLocalSize(self) -> tuple[int, int]:
1939        """Return the local number of rows and columns.
1940
1941        Not collective.
1942
1943        See Also
1944        --------
1945        getSize, petsc.MatGetLocalSize
1946
1947        """
1948        cdef PetscInt m = 0, n = 0
1949        CHKERR(MatGetLocalSize(self.mat, &m, &n))
1950        return (toInt(m), toInt(n))
1951
1952    def getSizes(self) -> tuple[LayoutSizeSpec, LayoutSizeSpec]:
1953        """Return the tuple of matrix layouts.
1954
1955        Not collective.
1956
1957        See Also
1958        --------
1959        getLocalSize, getSize
1960
1961        """
1962        cdef PetscInt m = 0, n = 0
1963        cdef PetscInt M = 0, N = 0
1964        CHKERR(MatGetLocalSize(self.mat, &m, &n))
1965        CHKERR(MatGetSize(self.mat, &M, &N))
1966        return ((toInt(m), toInt(M)), (toInt(n), toInt(N)))
1967
1968    def getBlockSize(self) -> int:
1969        """Return the matrix block size.
1970
1971        Not collective.
1972
1973        See Also
1974        --------
1975        getBlockSize, petsc.MatGetBlockSize
1976
1977        """
1978        cdef PetscInt bs = 0
1979        CHKERR(MatGetBlockSize(self.mat, &bs))
1980        return toInt(bs)
1981
1982    def getBlockSizes(self) -> tuple[int, int]:
1983        """Return the row and column block sizes.
1984
1985        Not collective.
1986
1987        See Also
1988        --------
1989        getBlockSize, petsc.MatGetBlockSizes
1990
1991        """
1992        cdef PetscInt rbs = 0, cbs = 0
1993        CHKERR(MatGetBlockSizes(self.mat, &rbs, &cbs))
1994        return (toInt(rbs), toInt(cbs))
1995
1996    def getOwnershipRange(self) -> tuple[int, int]:
1997        """Return the locally owned range of rows.
1998
1999        Not collective.
2000
2001        See Also
2002        --------
2003        getOwnershipRanges, getOwnershipRangeColumn, petsc.MatGetOwnershipRange
2004
2005        """
2006        cdef PetscInt ival1 = 0, ival2 = 0
2007        CHKERR(MatGetOwnershipRange(self.mat, &ival1, &ival2))
2008        return (toInt(ival1), toInt(ival2))
2009
2010    def getOwnershipRanges(self) -> ArrayInt:
2011        """Return the range of rows owned by each process.
2012
2013        Not collective.
2014
2015        The returned array is the result of exclusive scan of the local sizes.
2016
2017        See Also
2018        --------
2019        getOwnershipRange, petsc.MatGetOwnershipRanges
2020
2021        """
2022        cdef const PetscInt *rowrng = NULL
2023        CHKERR(MatGetOwnershipRanges(self.mat, &rowrng))
2024        cdef MPI_Comm comm = MPI_COMM_NULL
2025        CHKERR(PetscObjectGetComm(<PetscObject>self.mat, &comm))
2026        cdef int size = -1
2027        CHKERR(<PetscErrorCode>MPI_Comm_size(comm, &size))
2028        return array_i(size+1, rowrng)
2029
2030    def getOwnershipRangeColumn(self) -> tuple[int, int]:
2031        """Return the locally owned range of columns.
2032
2033        Not collective.
2034
2035        See Also
2036        --------
2037        getOwnershipRangesColumn, getOwnershipRange
2038        petsc.MatGetOwnershipRangeColumn
2039
2040        """
2041        cdef PetscInt ival1 = 0, ival2 = 0
2042        CHKERR(MatGetOwnershipRangeColumn(self.mat, &ival1, &ival2))
2043        return (toInt(ival1), toInt(ival2))
2044
2045    def getOwnershipRangesColumn(self) -> ArrayInt:
2046        """Return the range of columns owned by each process.
2047
2048        Not collective.
2049
2050        See Also
2051        --------
2052        getOwnershipRangeColumn, petsc.MatGetOwnershipRangesColumn
2053
2054        """
2055        cdef const PetscInt *colrng = NULL
2056        CHKERR(MatGetOwnershipRangesColumn(self.mat, &colrng))
2057        cdef MPI_Comm comm = MPI_COMM_NULL
2058        CHKERR(PetscObjectGetComm(<PetscObject>self.mat, &comm))
2059        cdef int size = -1
2060        CHKERR(<PetscErrorCode>MPI_Comm_size(comm, &size))
2061        return array_i(size+1, colrng)
2062
2063    def getOwnershipIS(self) -> tuple[IS, IS]:
2064        """Return the ranges of rows and columns owned by each process as index sets.
2065
2066        Not collective.
2067
2068        See Also
2069        --------
2070        getOwnershipRanges, getOwnershipRangesColumn, petsc.MatGetOwnershipIS
2071
2072        """
2073        cdef IS rows = IS()
2074        cdef IS cols = IS()
2075        CHKERR(MatGetOwnershipIS(self.mat, &rows.iset, &cols.iset))
2076        return (rows, cols)
2077
2078    def getInfo(self, info: InfoType | None = None) -> dict[str, float]:
2079        """Return summary information.
2080
2081        Collective.
2082
2083        Parameters
2084        ----------
2085        info
2086            If `None`, it uses `InfoType.GLOBAL_SUM`.
2087
2088        See Also
2089        --------
2090        petsc.MatInfo, petsc.MatGetInfo
2091
2092        """
2093        cdef PetscMatInfoType itype = infotype(info)
2094        cdef PetscMatInfo cinfo
2095        CHKERR(MatGetInfo(self.mat, itype, &cinfo))
2096        return cinfo
2097
2098    def duplicate(self, copy: DuplicateOption | bool = False) -> Mat:
2099        """Return a clone of the matrix.
2100
2101        Collective.
2102
2103        Parameters
2104        ----------
2105        copy
2106            If `True`, it also copies the values.
2107
2108        See Also
2109        --------
2110        petsc.MatDuplicate
2111
2112        """
2113        cdef PetscMatDuplicateOption flag = matduplicateoption(copy)
2114        cdef Mat mat = type(self)()
2115        CHKERR(MatDuplicate(self.mat, flag, &mat.mat))
2116        return mat
2117
2118    def copy(self, Mat result=None, structure: Structure | None = None) -> Mat:
2119        """Return a copy of the matrix.
2120
2121        Collective.
2122
2123        Parameters
2124        ----------
2125        result
2126            Optional return matrix. If `None`, it is internally created.
2127        structure
2128            The copy structure. Only relevant if ``result`` is not `None`.
2129
2130        See Also
2131        --------
2132        petsc.MatCopy, petsc.MatDuplicate
2133
2134        """
2135        cdef PetscMatDuplicateOption copy = MAT_COPY_VALUES
2136        cdef PetscMatStructure mstr = matstructure(structure)
2137        if result is None:
2138            result = type(self)()
2139        if result.mat == NULL:
2140            CHKERR(MatDuplicate(self.mat, copy, &result.mat))
2141        else:
2142            CHKERR(MatCopy(self.mat, result.mat, mstr))
2143        return result
2144
2145    def load(self, Viewer viewer) -> Self:
2146        """Load a matrix.
2147
2148        Collective.
2149
2150        See Also
2151        --------
2152        petsc.MatLoad
2153
2154        """
2155        cdef MPI_Comm comm = MPI_COMM_NULL
2156        cdef PetscObject obj = <PetscObject>(viewer.vwr)
2157        if self.mat == NULL:
2158            CHKERR(PetscObjectGetComm(obj, &comm))
2159            CHKERR(MatCreate(comm, &self.mat))
2160        CHKERR(MatLoad(self.mat, viewer.vwr))
2161        return self
2162
2163    def convert(self, mat_type: Type | str | None = None, Mat out=None) -> Mat:
2164        """Convert the matrix type.
2165
2166        Collective.
2167
2168        Parameters
2169        ----------
2170        mat_type
2171            The type of the new matrix. If `None` uses `Type.SAME`.
2172        out
2173            Optional return matrix. If `None`, inplace conversion is performed.
2174            Otherwise, the matrix is reused.
2175
2176        See Also
2177        --------
2178        petsc.MatConvert
2179
2180        """
2181        cdef PetscMatType mtype = MATSAME
2182        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
2183        mat_type = str2bytes(mat_type, &mtype)
2184        if mtype == NULL: mtype = MATSAME
2185        if out is None: out = self
2186        if out.mat == self.mat:
2187            reuse = MAT_INPLACE_MATRIX
2188        elif out.mat == NULL:
2189            reuse = MAT_INITIAL_MATRIX
2190        else:
2191            reuse = MAT_REUSE_MATRIX
2192        CHKERR(MatConvert(self.mat, mtype, reuse, &out.mat))
2193        return out
2194
2195    def transpose(self, Mat out=None) -> Mat:
2196        """Return the transposed matrix.
2197
2198        Collective.
2199
2200        Parameters
2201        ----------
2202        out
2203            Optional return matrix. If `None`, inplace transposition is performed.
2204            Otherwise, the matrix is reused.
2205
2206        See Also
2207        --------
2208        petsc.MatTranspose
2209
2210        """
2211        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
2212        if out is None: out = self
2213        if out.mat == self.mat:
2214            reuse = MAT_INPLACE_MATRIX
2215        elif out.mat == NULL:
2216            reuse = MAT_INITIAL_MATRIX
2217        else:
2218            reuse = MAT_REUSE_MATRIX
2219        CHKERR(MatTranspose(self.mat, reuse, &out.mat))
2220        return out
2221
2222    def setTransposePrecursor(self, Mat out) -> None:
2223        """Set transpose precursor.
2224
2225        Logically collective.
2226
2227        See Also
2228        --------
2229        petsc.MatTransposeSetPrecursor
2230
2231        """
2232        CHKERR(MatTransposeSetPrecursor(self.mat, out.mat))
2233
2234    def hermitianTranspose(self, Mat out=None) -> Mat:
2235        """Return the transposed Hermitian matrix.
2236
2237        Collective.
2238
2239        Parameters
2240        ----------
2241        out
2242            Optional return matrix. If `None`, inplace transposition is performed.
2243            Otherwise, the matrix is reused.
2244
2245        See Also
2246        --------
2247        petsc.MatHermitianTranspose
2248
2249        """
2250        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
2251        if out is None: out = self
2252        if out.mat == self.mat:
2253            reuse = MAT_INPLACE_MATRIX
2254        elif out.mat == NULL:
2255            reuse = MAT_INITIAL_MATRIX
2256        else:
2257            reuse = MAT_REUSE_MATRIX
2258        CHKERR(MatHermitianTranspose(self.mat, reuse, &out.mat))
2259        return out
2260
2261    def realPart(self, Mat out=None) -> Mat:
2262        """Return the real part of the matrix.
2263
2264        Collective.
2265
2266        Parameters
2267        ----------
2268        out
2269            Optional return matrix. If `None`, the operation is performed in-place.
2270            Otherwise, the operation is performed on ``out``.
2271
2272        See Also
2273        --------
2274        imagPart, conjugate, petsc.MatRealPart
2275
2276        """
2277        if out is None:
2278            out = self
2279        elif out.mat == NULL:
2280            CHKERR(MatDuplicate(self.mat, MAT_COPY_VALUES, &out.mat))
2281        CHKERR(MatRealPart(out.mat))
2282        return out
2283
2284    def imagPart(self, Mat out=None) -> Mat:
2285        """Return the imaginary part of the matrix.
2286
2287        Collective.
2288
2289        Parameters
2290        ----------
2291        out
2292            Optional return matrix. If `None`, the operation is performed in-place.
2293            Otherwise, the operation is performed on ``out``.
2294
2295        See Also
2296        --------
2297        realPart, conjugate, petsc.MatImaginaryPart
2298
2299        """
2300        if out is None:
2301            out = self
2302        elif out.mat == NULL:
2303            CHKERR(MatDuplicate(self.mat, MAT_COPY_VALUES, &out.mat))
2304        CHKERR(MatImaginaryPart(out.mat))
2305        return out
2306
2307    def conjugate(self, Mat out=None) -> Mat:
2308        """Return the conjugate matrix.
2309
2310        Collective.
2311
2312        Parameters
2313        ----------
2314        out
2315            Optional return matrix. If `None`, the operation is performed in-place.
2316            Otherwise, the operation is performed on ``out``.
2317
2318        See Also
2319        --------
2320        realPart, imagPart, petsc.MatConjugate
2321
2322        """
2323        if out is None:
2324            out = self
2325        elif out.mat == NULL:
2326            CHKERR(MatDuplicate(self.mat, MAT_COPY_VALUES, &out.mat))
2327        CHKERR(MatConjugate(out.mat))
2328        return out
2329
2330    def permute(self, IS row, IS col) -> Mat:
2331        """Return the permuted matrix.
2332
2333        Collective.
2334
2335        Parameters
2336        ----------
2337        row
2338            Row permutation.
2339        col
2340            Column permutation.
2341
2342        See Also
2343        --------
2344        petsc.MatPermute
2345
2346        """
2347        cdef Mat mat = Mat()
2348        CHKERR(MatPermute(self.mat, row.iset, col.iset, &mat.mat))
2349        return mat
2350
2351    def equal(self, Mat mat) -> bool:
2352        """Return the result of matrix comparison.
2353
2354        Collective.
2355
2356        See Also
2357        --------
2358        petsc.MatEqual
2359
2360        """
2361        cdef PetscBool flag = PETSC_FALSE
2362        CHKERR(MatEqual(self.mat, mat.mat, &flag))
2363        return toBool(flag)
2364
2365    def isTranspose(self, Mat mat=None, tol: float = 0) -> bool:
2366        """Return the result of matrix comparison with transposition.
2367
2368        Collective.
2369
2370        Parameters
2371        ----------
2372        mat
2373            Matrix to compare against. Uses ``self`` if `None`.
2374        tol
2375            Tolerance for comparison.
2376
2377        See Also
2378        --------
2379        petsc.MatIsTranspose
2380
2381        """
2382        if mat is None: mat = self
2383        cdef PetscReal rval = asReal(tol)
2384        cdef PetscBool flag = PETSC_FALSE
2385        CHKERR(MatIsTranspose(self.mat, mat.mat, rval, &flag))
2386        return toBool(flag)
2387
2388    def isSymmetric(self, tol: float = 0) -> bool:
2389        """Return the boolean indicating if the matrix is symmetric.
2390
2391        Collective.
2392
2393        Parameters
2394        ----------
2395        tol
2396            Tolerance for comparison.
2397
2398        See Also
2399        --------
2400        petsc.MatIsSymmetric
2401
2402        """
2403        cdef PetscReal rval = asReal(tol)
2404        cdef PetscBool flag = PETSC_FALSE
2405        CHKERR(MatIsSymmetric(self.mat, rval, &flag))
2406        return toBool(flag)
2407
2408    def isSymmetricKnown(self) -> tuple[bool, bool]:
2409        """Return the 2-tuple indicating if the matrix is known to be symmetric.
2410
2411        Not collective.
2412
2413        See Also
2414        --------
2415        petsc.MatIsSymmetricKnown
2416
2417        """
2418        cdef PetscBool flag1 = PETSC_FALSE
2419        cdef PetscBool flag2 = PETSC_FALSE
2420        CHKERR(MatIsSymmetricKnown(self.mat, &flag1, &flag2))
2421        return (toBool(flag1), toBool(flag2))
2422
2423    def isHermitian(self, tol: float = 0) -> bool:
2424        """Return the boolean indicating if the matrix is Hermitian.
2425
2426        Collective.
2427
2428        Parameters
2429        ----------
2430        tol
2431            Tolerance for comparison.
2432
2433        See Also
2434        --------
2435        petsc.MatIsHermitian
2436
2437        """
2438        cdef PetscReal rval = asReal(tol)
2439        cdef PetscBool flag = PETSC_FALSE
2440        CHKERR(MatIsHermitian(self.mat, rval, &flag))
2441        return toBool(flag)
2442
2443    def isHermitianKnown(self) -> tuple[bool, bool]:
2444        """Return the 2-tuple indicating if the matrix is known to be Hermitian.
2445
2446        Not collective.
2447
2448        See Also
2449        --------
2450        petsc.MatIsHermitianKnown
2451
2452        """
2453        cdef PetscBool flag1 = PETSC_FALSE
2454        cdef PetscBool flag2 = PETSC_FALSE
2455        CHKERR(MatIsHermitianKnown(self.mat, &flag1, &flag2))
2456        return (toBool(flag1), toBool(flag2))
2457
2458    def isStructurallySymmetric(self) -> bool:
2459        """Return the boolean indicating if the matrix is structurally symmetric.
2460
2461        Not collective.
2462
2463        See Also
2464        --------
2465        petsc.MatIsStructurallySymmetric
2466
2467        """
2468        cdef PetscBool flag = PETSC_FALSE
2469        CHKERR(MatIsStructurallySymmetric(self.mat, &flag))
2470        return toBool(flag)
2471
2472    def isLinear(self, n: int = 1) -> bool:
2473        """Return whether the Mat is a linear operator.
2474
2475        Collective.
2476
2477        Parameters
2478        ----------
2479        n
2480            Number of random vectors to be tested.
2481
2482        See Also
2483        --------
2484        petsc.MatIsLinear
2485
2486        """
2487        cdef PetscBool flag = PETSC_FALSE
2488        CHKERR(MatIsLinear(self.mat, n, &flag))
2489        return toBool(flag)
2490
2491    def zeroEntries(self) -> None:
2492        """Zero the entries of the matrix.
2493
2494        Collective.
2495
2496        See Also
2497        --------
2498        petsc.MatZeroEntries
2499
2500        """
2501        CHKERR(MatZeroEntries(self.mat))
2502
2503    def getValue(self, row, col) -> Scalar:
2504        """Return the value in the (row, col) position.
2505
2506        Not collective.
2507
2508        See Also
2509        --------
2510        petsc.MatGetValues
2511
2512        """
2513        cdef PetscInt    ival1 = asInt(row)
2514        cdef PetscInt    ival2 = asInt(col)
2515        cdef PetscScalar sval  = 0
2516        CHKERR(MatGetValues(self.mat, 1, &ival1, 1, &ival2, &sval))
2517        return toScalar(sval)
2518
2519    def getValues(self, rows: Sequence[int], cols: Sequence[int], values: ArrayScalar | None = None) -> ArrayScalar:
2520        """Return the values in the ``zip(rows, cols)`` positions.
2521
2522        Not collective.
2523
2524        Parameters
2525        ----------
2526        rows
2527            Row indices.
2528        cols
2529            Column indices.
2530        values
2531            Optional array where to store the values.
2532
2533        See Also
2534        --------
2535        petsc.MatGetValues
2536
2537        """
2538        return matgetvalues(self.mat, rows, cols, values)
2539
2540    def getValuesCSR(self) -> tuple[ArrayInt, ArrayInt, ArrayScalar]:
2541        """Return the CSR representation of the local part of the matrix.
2542
2543        Not collective.
2544
2545        See Also
2546        --------
2547        petsc.MatGetRow
2548
2549        """
2550        # row ownership
2551        cdef PetscInt rstart=0, rend=0, nrows=0
2552        CHKERR(MatGetOwnershipRange(self.mat, &rstart, &rend))
2553        nrows = rend - rstart
2554        # first pass: row pointer array
2555        cdef PetscInt *AI = NULL
2556        cdef ndarray ai = oarray_i(empty_i(nrows+1), NULL, &AI)
2557        cdef PetscInt irow=0, ncols=0
2558        AI[0] = 0
2559        for irow from 0 <= irow < nrows:
2560            CHKERR(MatGetRow(self.mat, irow+rstart, &ncols, NULL, NULL))
2561            AI[irow+1] = AI[irow] + ncols
2562            CHKERR(MatRestoreRow(self.mat, irow+rstart, &ncols, NULL, NULL))
2563        # second pass: column indices and values
2564        cdef PetscInt *AJ = NULL
2565        cdef ndarray aj = oarray_i(empty_i(AI[nrows]), NULL, &AJ)
2566        cdef PetscScalar *AV = NULL
2567        cdef ndarray av = oarray_s(empty_s(AI[nrows]), NULL, &AV)
2568        cdef const PetscInt *cols = NULL
2569        cdef const PetscScalar *vals = NULL
2570        for irow from 0 <= irow < nrows:
2571            CHKERR(MatGetRow(self.mat, irow+rstart, &ncols, &cols, &vals))
2572            CHKERR(PetscMemcpy(AJ+AI[irow], cols, <size_t>ncols*sizeof(PetscInt)))
2573            CHKERR(PetscMemcpy(AV+AI[irow], vals, <size_t>ncols*sizeof(PetscScalar)))
2574            CHKERR(MatRestoreRow(self.mat, irow+rstart, &ncols, &cols, &vals))
2575        #
2576        return (ai, aj, av)
2577
2578    def getRow(self, row: int) -> tuple[ArrayInt, ArrayScalar]:
2579        """Return the column indices and values for the requested row.
2580
2581        Not collective.
2582
2583        See Also
2584        --------
2585        petsc.MatGetRow
2586
2587        """
2588        cdef PetscInt irow = asInt(row)
2589        cdef PetscInt ncols = 0
2590        cdef const PetscInt *icols=NULL
2591        cdef const PetscScalar *svals=NULL
2592        CHKERR(MatGetRow(self.mat, irow, &ncols, &icols, &svals))
2593        cdef object cols = array_i(ncols, icols)
2594        cdef object vals = array_s(ncols, svals)
2595        CHKERR(MatRestoreRow(self.mat, irow, &ncols, &icols, &svals))
2596        return (cols, vals)
2597
2598    def getRowIJ(self, symmetric: bool = False, compressed: bool = False) -> tuple[ArrayInt, ArrayInt]:
2599        """Return the CSR representation of the local sparsity pattern.
2600
2601        Collective.
2602
2603        Parameters
2604        ----------
2605        symmetric
2606            If `True`, return the symmetrized graph.
2607        compressed
2608            If `True`, return the compressed graph.
2609
2610        See Also
2611        --------
2612        petsc.MatGetRowIJ
2613
2614        """
2615        cdef PetscInt shift=0
2616        cdef PetscBool symm=symmetric
2617        cdef PetscBool bcmp=compressed
2618        cdef PetscInt n=0
2619        cdef const PetscInt *ia=NULL
2620        cdef const PetscInt *ja=NULL
2621        cdef PetscBool done=PETSC_FALSE
2622        CHKERR(MatGetRowIJ(self.mat, shift, symm, bcmp, &n, &ia, &ja, &done))
2623        cdef object ai=None, aj=None
2624        if done != PETSC_FALSE: ai = array_i(n+1, ia)
2625        if done != PETSC_FALSE: aj = array_i(ia[n], ja)
2626        CHKERR(MatRestoreRowIJ(self.mat, shift, symm, bcmp, &n, &ia, &ja, &done))
2627        return (ai, aj)
2628
2629    def getColumnIJ(self, symmetric: bool = False, compressed: bool = False) -> tuple[ArrayInt, ArrayInt]:
2630        """Return the CSC representation of the local sparsity pattern.
2631
2632        Collective.
2633
2634        Parameters
2635        ----------
2636        symmetric
2637            If `True`, return the symmetrized graph.
2638        compressed
2639            If `True`, return the compressed graph.
2640
2641        See Also
2642        --------
2643        petsc.MatGetRowIJ
2644
2645        """
2646        cdef PetscInt shift=0
2647        cdef PetscBool symm=symmetric, bcmp=compressed
2648        cdef PetscInt n=0
2649        cdef const PetscInt *ia=NULL
2650        cdef const PetscInt *ja=NULL
2651        cdef PetscBool done=PETSC_FALSE
2652        CHKERR(MatGetColumnIJ(self.mat, shift, symm, bcmp, &n, &ia, &ja, &done))
2653        cdef object ai=None, aj=None
2654        if done != PETSC_FALSE: ai = array_i(n+1, ia)
2655        if done != PETSC_FALSE: aj = array_i(ia[n], ja)
2656        CHKERR(MatRestoreColumnIJ(self.mat, shift, symm, bcmp, &n, &ia, &ja, &done))
2657        return (ai, aj)
2658
2659    def setValue(
2660        self,
2661        row: int,
2662        col: int,
2663        value: Scalar,
2664        addv: InsertModeSpec = None) -> None:
2665        """Set a value to the ``(row, col)`` entry of the matrix.
2666
2667        Not collective.
2668
2669        Parameters
2670        ----------
2671        row
2672            Row index.
2673        col
2674            Column index.
2675        value
2676            The scalar value.
2677        addv
2678            Insertion mode.
2679
2680        See Also
2681        --------
2682        petsc.MatSetValues
2683
2684        """
2685        cdef PetscInt    ival1 = asInt(row)
2686        cdef PetscInt    ival2 = asInt(col)
2687        cdef PetscScalar sval  = asScalar(value)
2688        cdef PetscInsertMode caddv = insertmode(addv)
2689        CHKERR(MatSetValues(self.mat, 1, &ival1, 1, &ival2, &sval, caddv))
2690
2691    def setValues(
2692        self,
2693        rows: Sequence[int],
2694        cols: Sequence[int],
2695        values: Sequence[Scalar],
2696        addv: InsertModeSpec = None) -> None:
2697        """Set values to the rows ⊗ cols entries of the matrix.
2698
2699        Not collective.
2700
2701        Parameters
2702        ----------
2703        rows
2704            Row indices.
2705        cols
2706            Column indices.
2707        values
2708            The scalar values. A sequence of length at least ``len(rows) * len(cols)``.
2709        addv
2710            Insertion mode.
2711
2712        See Also
2713        --------
2714        petsc.MatSetValues
2715
2716        """
2717        matsetvalues(self.mat, rows, cols, values, addv, 0, 0)
2718
2719    def setValuesRCV(self, R, C, V, addv=None) -> None:
2720        """Undocumented."""
2721        matsetvalues_rcv(self.mat, R, C, V, addv, 0, 0)
2722
2723    def setValuesIJV(
2724        self,
2725        I: Sequence[int],
2726        J: Sequence[int],
2727        V: Sequence[Scalar],
2728        addv: InsertModeSpec = None,
2729        rowmap: Sequence[int] | None = None) -> None:
2730        """Set a subset of values stored in CSR format.
2731
2732        Not collective.
2733
2734        Parameters
2735        ----------
2736        I
2737            Row pointers.
2738        J
2739            Column indices.
2740        V
2741            The scalar values.
2742        addv
2743            Insertion mode.
2744        rowmap
2745            Optional iterable indicating which row to insert.
2746
2747        See Also
2748        --------
2749        petsc.MatSetValues
2750
2751        """
2752        matsetvalues_ijv(self.mat, I, J, V, addv, rowmap, 0, 0)
2753
2754    def setValuesCOO(
2755        self,
2756        coo_v: Sequence[Scalar],
2757        addv: InsertModeSpec = None) -> None:
2758        """Set values after preallocation with coordinate format.
2759
2760        Collective.
2761
2762        Parameters
2763        ----------
2764        coo_v
2765            The matrix values.
2766        addv
2767            Insertion mode.
2768
2769        See Also
2770        --------
2771        setPreallocationCOO, petsc.MatSetValuesCOO
2772        """
2773        matsetvalues_coo(self.mat, coo_v, addv)
2774
2775    def setValuesCSR(
2776        self,
2777        I: Sequence[int],
2778        J: Sequence[int],
2779        V: Sequence[Scalar],
2780        addv: InsertModeSpec = None) -> None:
2781        """Set values stored in CSR format.
2782
2783        Not collective.
2784
2785        Parameters
2786        ----------
2787        I
2788            Row pointers.
2789        J
2790            Column indices.
2791        V
2792            The scalar values.
2793        addv
2794            Insertion mode.
2795
2796        See Also
2797        --------
2798        petsc.MatSetValues
2799
2800        """
2801        matsetvalues_csr(self.mat, I, J, V, addv, 0, 0)
2802
2803    def setValuesBlocked(
2804        self,
2805        rows: Sequence[int],
2806        cols: Sequence[int],
2807        values: Sequence[Scalar],
2808        addv: InsertModeSpec = None) -> None:
2809        """Set values to the rows ⊗ col block entries of the matrix.
2810
2811        Not collective.
2812
2813        Parameters
2814        ----------
2815        rows
2816            Block row indices.
2817        cols
2818            Block column indices.
2819        values
2820            The scalar values. A sequence of length at least
2821            ``len(rows) * len(cols) * bs * bs``,
2822            where ``bs`` is the block size of the matrix.
2823        addv
2824            Insertion mode.
2825
2826        See Also
2827        --------
2828        petsc.MatSetValuesBlocked
2829
2830        """
2831        matsetvalues(self.mat, rows, cols, values, addv, 1, 0)
2832
2833    def setValuesBlockedRCV(self, R, C, V, addv=None) -> None:
2834        """Undocumented."""
2835        matsetvalues_rcv(self.mat, R, C, V, addv, 1, 0)
2836
2837    def setValuesBlockedIJV(
2838        self,
2839        I: Sequence[int],
2840        J: Sequence[int],
2841        V: Sequence[Scalar],
2842        addv: InsertModeSpec = None,
2843        rowmap: Sequence[int] | None = None) -> None:
2844        """Set a subset of values stored in block CSR format.
2845
2846        Not collective.
2847
2848        Parameters
2849        ----------
2850        I
2851            Block row pointers.
2852        J
2853            Block column indices.
2854        V
2855            The scalar values.
2856        addv
2857            Insertion mode.
2858        rowmap
2859            Optional iterable indicating which block row to insert.
2860
2861        See Also
2862        --------
2863        petsc.MatSetValuesBlocked
2864
2865        """
2866        matsetvalues_ijv(self.mat, I, J, V, addv, rowmap, 1, 0)
2867
2868    def setValuesBlockedCSR(
2869        self,
2870        I: Sequence[int],
2871        J: Sequence[int],
2872        V: Sequence[Scalar],
2873        addv: InsertModeSpec = None) -> None:
2874        """Set values stored in block CSR format.
2875
2876        Not collective.
2877
2878        Parameters
2879        ----------
2880        I
2881            Block row pointers.
2882        J
2883            Block column indices.
2884        V
2885            The scalar values.
2886        addv
2887            Insertion mode.
2888
2889        See Also
2890        --------
2891        petsc.MatSetValuesBlocked
2892
2893        """
2894        matsetvalues_csr(self.mat, I, J, V, addv, 1, 0)
2895
2896    def setLGMap(self, LGMap rmap, LGMap cmap=None) -> None:
2897        """Set the local-to-global mappings.
2898
2899        Collective.
2900
2901        Parameters
2902        ----------
2903        rmap
2904            Row mapping.
2905        cmap
2906            Column mapping. If `None`, ``cmap = rmap``.
2907
2908        See Also
2909        --------
2910        getLGMap, petsc.MatSetLocalToGlobalMapping
2911
2912        """
2913        if cmap is None: cmap = rmap
2914        CHKERR(MatSetLocalToGlobalMapping(self.mat, rmap.lgm, cmap.lgm))
2915
2916    def getLGMap(self) -> tuple[LGMap, LGMap]:
2917        """Return the local-to-global mappings.
2918
2919        Not collective.
2920
2921        See Also
2922        --------
2923        setLGMap, petsc.MatGetLocalToGlobalMapping
2924
2925        """
2926        cdef LGMap cmap = LGMap()
2927        cdef LGMap rmap = LGMap()
2928        CHKERR(MatGetLocalToGlobalMapping(self.mat, &rmap.lgm, &cmap.lgm))
2929        CHKERR(PetscINCREF(cmap.obj))
2930        CHKERR(PetscINCREF(rmap.obj))
2931        return (rmap, cmap)
2932
2933    def setValueLocal(
2934        self,
2935        row: int,
2936        col: int,
2937        value: Scalar,
2938        addv: InsertModeSpec = None) -> None:
2939        """Set a value to the ``(row, col)`` entry of the matrix in local ordering.
2940
2941        Not collective.
2942
2943        Parameters
2944        ----------
2945        row
2946            Local row index.
2947        col
2948            Local column index.
2949        value
2950            The scalar value.
2951        addv
2952            Insertion mode.
2953
2954        See Also
2955        --------
2956        petsc.MatSetValuesLocal
2957
2958        """
2959        cdef PetscInt    ival1 = asInt(row)
2960        cdef PetscInt    ival2 = asInt(col)
2961        cdef PetscScalar sval  = asScalar(value)
2962        cdef PetscInsertMode caddv = insertmode(addv)
2963        CHKERR(MatSetValuesLocal(
2964                self.mat, 1, &ival1, 1, &ival2, &sval, caddv))
2965
2966    def setValuesLocal(
2967        self,
2968        rows: Sequence[int],
2969        cols: Sequence[int],
2970        values: Sequence[Scalar],
2971        addv: InsertModeSpec = None) -> None:
2972        """Set values to the rows ⊗ col entries of the matrix in local ordering.
2973
2974        Not collective.
2975
2976        Parameters
2977        ----------
2978        rows
2979            Local row indices.
2980        cols
2981            Local column indices.
2982        values
2983            The scalar values. A sequence of length at least ``len(rows) * len(cols)``.
2984        addv
2985            Insertion mode.
2986
2987        See Also
2988        --------
2989        petsc.MatSetValuesLocal
2990
2991        """
2992        matsetvalues(self.mat, rows, cols, values, addv, 0, 1)
2993
2994    def setValuesLocalRCV(self, R, C, V, addv=None) -> None:
2995        """Undocumented."""
2996        matsetvalues_rcv(self.mat, R, C, V, addv, 0, 1)
2997
2998    def setValuesLocalIJV(
2999        self,
3000        I: Sequence[int],
3001        J: Sequence[int],
3002        V: Sequence[Scalar],
3003        addv: InsertModeSpec = None,
3004        rowmap: Sequence[int] | None = None) -> None:
3005        """Set a subset of values stored in CSR format.
3006
3007        Not collective.
3008
3009        Parameters
3010        ----------
3011        I
3012            Row pointers.
3013        J
3014            Local column indices.
3015        V
3016            The scalar values.
3017        addv
3018            Insertion mode.
3019        rowmap
3020            Optional iterable indicating which row to insert.
3021
3022        See Also
3023        --------
3024        petsc.MatSetValuesLocal
3025
3026        """
3027        matsetvalues_ijv(self.mat, I, J, V, addv, rowmap, 0, 1)
3028
3029    def setValuesLocalCSR(
3030        self,
3031        I: Sequence[int],
3032        J: Sequence[int],
3033        V: Sequence[Scalar],
3034        addv: InsertModeSpec = None) -> None:
3035        """Set values stored in CSR format.
3036
3037        Not collective.
3038
3039        Parameters
3040        ----------
3041        I
3042            Row pointers.
3043        J
3044            Local column indices.
3045        V
3046            The scalar values.
3047        addv
3048            Insertion mode.
3049
3050        See Also
3051        --------
3052        petsc.MatSetValuesLocal
3053
3054        """
3055        matsetvalues_csr(self.mat, I, J, V, addv, 0, 1)
3056
3057    def setValuesBlockedLocal(
3058        self,
3059        rows: Sequence[int],
3060        cols: Sequence[int],
3061        values: Sequence[Scalar],
3062        addv: InsertModeSpec = None) -> None:
3063        """Set values to the rows ⊗ col block entries of the matrix in local ordering.
3064
3065        Not collective.
3066
3067        Parameters
3068        ----------
3069        rows
3070            Local block row indices.
3071        cols
3072            Local block column indices.
3073        values
3074            The scalar values. A sequence of length at least
3075            ``len(rows) * len(cols) * bs * bs``,
3076            where ``bs`` is the block size of the matrix.
3077        addv
3078            Insertion mode.
3079
3080        See Also
3081        --------
3082        petsc.MatSetValuesBlockedLocal
3083
3084        """
3085        matsetvalues(self.mat, rows, cols, values, addv, 1, 1)
3086
3087    def setValuesBlockedLocalRCV(self, R, C, V, addv=None) -> None:
3088        """Undocumented."""
3089        matsetvalues_rcv(self.mat, R, C, V, addv, 1, 1)
3090
3091    def setValuesBlockedLocalIJV(
3092        self,
3093        I: Sequence[int],
3094        J: Sequence[int],
3095        V: Sequence[Scalar],
3096        addv: InsertModeSpec = None,
3097        rowmap: Sequence[int] | None = None) -> None:
3098        """Set a subset of values stored in block CSR format.
3099
3100        Not collective.
3101
3102        Parameters
3103        ----------
3104        I
3105            Block row pointers.
3106        J
3107            Local block column indices.
3108        V
3109            The scalar values.
3110        addv
3111            Insertion mode.
3112        rowmap
3113            Optional iterable indicating which block row to insert.
3114
3115        See Also
3116        --------
3117        petsc.MatSetValuesBlockedLocal
3118
3119        """
3120        matsetvalues_ijv(self.mat, I, J, V, addv, rowmap, 1, 1)
3121
3122    def setValuesBlockedLocalCSR(
3123        self,
3124        I: Sequence[int],
3125        J: Sequence[int],
3126        V: Sequence[Scalar],
3127        addv: InsertModeSpec = None) -> None:
3128        """Set values stored in block CSR format.
3129
3130        Not collective.
3131
3132        Parameters
3133        ----------
3134        I
3135            Block row pointers.
3136        J
3137            Local block column indices.
3138        V
3139            The scalar values.
3140        addv
3141            Insertion mode.
3142
3143        See Also
3144        --------
3145        petsc.MatSetValuesBlockedLocal
3146
3147        """
3148        matsetvalues_csr(self.mat, I, J, V, addv, 1, 1)
3149
3150    #
3151
3152    Stencil = MatStencil
3153
3154    def setStencil(self, dims: DimsSpec, starts: DimsSpec | None = None, dof: int = 1) -> None:
3155        """Set matrix stencil.
3156
3157        Not collective.
3158
3159        See Also
3160        --------
3161        petsc.MatSetStencil
3162
3163        """
3164        cdef PetscInt ndim, ndof
3165        cdef PetscInt cdims[3], cstarts[3]
3166        cdims[0] = cdims[1] = cdims[2] = 1
3167        cstarts[0] = cstarts[1] = cstarts[2] = 0
3168        ndim = asDims(dims, &cdims[0], &cdims[1], &cdims[2])
3169        ndof = asInt(dof)
3170        if starts is not None:
3171            asDims(dims, &cstarts[0], &cstarts[1], &cstarts[2])
3172        CHKERR(MatSetStencil(self.mat, ndim, cdims, cstarts, ndof))
3173
3174    def setValueStencil(
3175        self,
3176        MatStencil row: Stencil,
3177        MatStencil col: Stencil,
3178        value: Sequence[Scalar],
3179        addv: InsertModeSpec = None) -> None:
3180        """Set a value to row and col stencil.
3181
3182        Not collective.
3183
3184        Parameters
3185        ----------
3186        row
3187            Row stencil.
3188        col
3189            Column stencil.
3190        value
3191            The scalar values.
3192        addv
3193            Insertion mode.
3194
3195        See Also
3196        --------
3197        petsc.MatSetValuesStencil
3198
3199        """
3200        cdef MatStencil r = row, c = col
3201        cdef PetscInsertMode im = insertmode(addv)
3202        matsetvaluestencil(self.mat, r, c, value, im, 0)
3203
3204    def setValueStagStencil(self, row, col, value, addv=None) -> None:
3205        """Not implemented."""
3206        raise NotImplementedError
3207
3208    def setValueBlockedStencil(
3209        self,
3210        row: Stencil,
3211        col: Stencil,
3212        value: Sequence[Scalar],
3213        addv: InsertModeSpec = None) -> None:
3214        """Set a block of values to row and col stencil.
3215
3216        Not collective.
3217
3218        Parameters
3219        ----------
3220        row
3221            Row stencil.
3222        col
3223            Column stencil.
3224        value
3225            The scalar values.
3226        addv
3227            Insertion mode.
3228
3229        See Also
3230        --------
3231        petsc.MatSetValuesBlockedStencil
3232
3233        """
3234        cdef MatStencil r = row, c = col
3235        cdef PetscInsertMode im = insertmode(addv)
3236        matsetvaluestencil(self.mat, r, c, value, im, 1)
3237
3238    def setValueBlockedStagStencil(self, row, col, value, addv=None) -> None:
3239        """Not implemented."""
3240        raise NotImplementedError
3241
3242    def zeroRows(self, rows: IS | Sequence[int], diag: Scalar = 1.0, Vec x=None, Vec b=None) -> None:
3243        """Zero selected rows of the matrix.
3244
3245        Collective.
3246
3247        Parameters
3248        ----------
3249        rows
3250            Row indices to be zeroed.
3251        diag
3252            Scalar value to be inserted into the diagonal.
3253        x
3254            Optional solution vector to be modified for zeroed rows.
3255        b
3256            Optional right-hand side vector to be modified.
3257            It will be adjusted with provided solution entries.
3258
3259        See Also
3260        --------
3261        zeroRowsLocal, petsc.MatZeroRows, petsc.MatZeroRowsIS
3262
3263        """
3264        cdef PetscInt ni=0, *i=NULL
3265        cdef PetscScalar sval = asScalar(diag)
3266        cdef PetscVec xvec=NULL, bvec=NULL
3267        if x is not None: xvec = x.vec
3268        if b is not None: bvec = b.vec
3269        if isinstance(rows, IS):
3270            CHKERR(MatZeroRowsIS(self.mat, (<IS>rows).iset, sval, xvec, bvec))
3271        else:
3272            rows = iarray_i(rows, &ni, &i)
3273            CHKERR(MatZeroRows(self.mat, ni, i, sval, xvec, bvec))
3274
3275    def zeroRowsLocal(self, rows: IS | Sequence[int], diag: Scalar = 1.0, Vec x=None, Vec b=None) -> None:
3276        """Zero selected rows of the matrix in local ordering.
3277
3278        Collective.
3279
3280        Parameters
3281        ----------
3282        rows
3283            Local row indices to be zeroed.
3284        diag
3285            Scalar value to be inserted into the diagonal.
3286        x
3287            Optional solution vector to be modified for zeroed rows.
3288        b
3289            Optional right-hand side vector to be modified.
3290            It will be adjusted with provided solution entries.
3291
3292        See Also
3293        --------
3294        zeroRows, petsc.MatZeroRowsLocal, petsc.MatZeroRowsLocalIS
3295
3296        """
3297        cdef PetscInt ni=0, *i=NULL
3298        cdef PetscScalar sval = asScalar(diag)
3299        cdef PetscVec xvec=NULL, bvec=NULL
3300        if x is not None: xvec = x.vec
3301        if b is not None: bvec = b.vec
3302        if isinstance(rows, IS):
3303            CHKERR(MatZeroRowsLocalIS(self.mat, (<IS>rows).iset, sval, xvec, bvec))
3304        else:
3305            rows = iarray_i(rows, &ni, &i)
3306            CHKERR(MatZeroRowsLocal(self.mat, ni, i, sval, xvec, bvec))
3307
3308    def zeroRowsColumns(self, rows: IS | Sequence[int], diag: Scalar = 1.0, Vec x=None, Vec b=None) -> None:
3309        """Zero selected rows and columns of the matrix.
3310
3311        Collective.
3312
3313        Parameters
3314        ----------
3315        rows
3316            Row/column indices to be zeroed.
3317        diag
3318            Scalar value to be inserted into the diagonal.
3319        x
3320            Optional solution vector to be modified for zeroed rows.
3321        b
3322            Optional right-hand side vector to be modified.
3323            It will be adjusted with provided solution entries.
3324
3325        See Also
3326        --------
3327        zeroRowsColumnsLocal, zeroRows, petsc.MatZeroRowsColumns
3328        petsc.MatZeroRowsColumnsIS
3329
3330        """
3331        cdef PetscInt ni=0, *i=NULL
3332        cdef PetscScalar sval = asScalar(diag)
3333        cdef PetscVec xvec=NULL, bvec=NULL
3334        if x is not None: xvec = x.vec
3335        if b is not None: bvec = b.vec
3336        if isinstance(rows, IS):
3337            CHKERR(MatZeroRowsColumnsIS(self.mat, (<IS>rows).iset, sval, xvec, bvec))
3338        else:
3339            rows = iarray_i(rows, &ni, &i)
3340            CHKERR(MatZeroRowsColumns(self.mat, ni, i, sval, xvec, bvec))
3341
3342    def zeroRowsColumnsLocal(self, rows: IS | Sequence[int], diag: Scalar = 1.0, Vec x=None, Vec b=None) -> None:
3343        """Zero selected rows and columns of the matrix in local ordering.
3344
3345        Collective.
3346
3347        Parameters
3348        ----------
3349        rows
3350            Local row/column indices to be zeroed.
3351        diag
3352            Scalar value to be inserted into the diagonal.
3353        x
3354            Optional solution vector to be modified for zeroed rows.
3355        b
3356            Optional right-hand side vector to be modified.
3357            It will be adjusted with provided solution entries.
3358
3359        See Also
3360        --------
3361        zeroRowsLocal, zeroRowsColumns, petsc.MatZeroRowsColumnsLocal
3362        petsc.MatZeroRowsColumnsLocalIS
3363
3364        """
3365        cdef PetscInt ni=0, *i=NULL
3366        cdef PetscScalar sval = asScalar(diag)
3367        cdef PetscVec xvec=NULL, bvec=NULL
3368        if x is not None: xvec = x.vec
3369        if b is not None: bvec = b.vec
3370        if isinstance(rows, IS):
3371            CHKERR(MatZeroRowsColumnsLocalIS(self.mat, (<IS>rows).iset, sval, xvec, bvec))
3372        else:
3373            rows = iarray_i(rows, &ni, &i)
3374            CHKERR(MatZeroRowsColumnsLocal(self.mat, ni, i, sval, xvec, bvec))
3375
3376    def zeroRowsColumnsStencil(self, rows: Sequence[Stencil], diag: Scalar = 1.0, Vec x=None, Vec b=None) -> None:
3377        """Zero selected rows and columns of the matrix.
3378
3379        Collective.
3380
3381        Parameters
3382        ----------
3383        rows
3384            Iterable of stencil rows and columns.
3385        diag
3386            Scalar value to be inserted into the diagonal.
3387        x
3388            Optional solution vector to be modified for zeroed rows.
3389        b
3390            Optional right-hand side vector to be modified.
3391            It will be adjusted with provided solution entries.
3392
3393        See Also
3394        --------
3395        zeroRowsLocal, zeroRowsColumns, petsc.MatZeroRowsColumnsStencil
3396
3397        """
3398        cdef PetscScalar sval = asScalar(diag)
3399        cdef PetscInt nrows = asInt(len(rows))
3400        cdef PetscMatStencil *crows = NULL
3401        CHKERR(PetscMalloc(<size_t>(nrows+1)*sizeof(PetscMatStencil), &crows))
3402        for i in range(nrows):
3403            crows[i] = (<MatStencil?>rows[i]).stencil
3404        cdef PetscVec xvec = NULL, bvec = NULL
3405        if x is not None: xvec = x.vec
3406        if b is not None: bvec = b.vec
3407        CHKERR(MatZeroRowsColumnsStencil(self.mat, nrows, crows, sval, xvec, bvec))
3408        CHKERR(PetscFree(crows))
3409
3410    def storeValues(self) -> None:
3411        """Stash a copy of the matrix values.
3412
3413        Collective.
3414
3415        See Also
3416        --------
3417        retrieveValues, petsc.MatStoreValues
3418
3419        """
3420        CHKERR(MatStoreValues(self.mat))
3421
3422    def retrieveValues(self) -> None:
3423        """Retrieve a copy of the matrix values previously stored with `storeValues`.
3424
3425        Collective.
3426
3427        See Also
3428        --------
3429        storeValues, petsc.MatRetrieveValues
3430
3431        """
3432        CHKERR(MatRetrieveValues(self.mat))
3433
3434    def assemblyBegin(self, assembly: MatAssemblySpec = None) -> None:
3435        """Begin an assembling stage of the matrix.
3436
3437        Collective.
3438
3439        Parameters
3440        ----------
3441        assembly
3442            The assembly type.
3443
3444        See Also
3445        --------
3446        assemblyEnd, assemble, petsc.MatAssemblyBegin
3447
3448        """
3449        cdef PetscMatAssemblyType flag = assemblytype(assembly)
3450        CHKERR(MatAssemblyBegin(self.mat, flag))
3451
3452    def assemblyEnd(self, assembly: MatAssemblySpec = None) -> None:
3453        """Complete an assembling stage of the matrix initiated with `assemblyBegin`.
3454
3455        Collective.
3456
3457        Parameters
3458        ----------
3459        assembly
3460            The assembly type.
3461
3462        See Also
3463        --------
3464        assemblyBegin, assemble, petsc.MatAssemblyEnd
3465
3466        """
3467        cdef PetscMatAssemblyType flag = assemblytype(assembly)
3468        CHKERR(MatAssemblyEnd(self.mat, flag))
3469
3470    def assemble(self, assembly: MatAssemblySpec = None) -> None:
3471        """Assemble the matrix.
3472
3473        Collective.
3474
3475        Parameters
3476        ----------
3477        assembly
3478            The assembly type.
3479
3480        See Also
3481        --------
3482        assemblyBegin, assemblyEnd
3483
3484        """
3485        cdef PetscMatAssemblyType flag = assemblytype(assembly)
3486        CHKERR(MatAssemblyBegin(self.mat, flag))
3487        CHKERR(MatAssemblyEnd(self.mat, flag))
3488
3489    def isAssembled(self) -> bool:
3490        """The boolean flag indicating if the matrix is assembled.
3491
3492        Not collective.
3493
3494        See Also
3495        --------
3496        assemble, petsc.MatAssembled
3497
3498        """
3499        cdef PetscBool flag = PETSC_FALSE
3500        CHKERR(MatAssembled(self.mat, &flag))
3501        return toBool(flag)
3502
3503    def findZeroRows(self) -> IS:
3504        """Return the index set of empty rows.
3505
3506        Collective.
3507
3508        See Also
3509        --------
3510        petsc.MatFindZeroRows
3511
3512        """
3513        cdef IS zerorows = IS()
3514        CHKERR(MatFindZeroRows(self.mat, &zerorows.iset))
3515        return zerorows
3516
3517    def createVecs(
3518        self,
3519        side: Literal['r', 'R', 'right', 'Right', 'RIGHT', 'l', 'L', 'left', 'Left', 'LEFT'] | None = None) -> Vec | tuple[Vec, Vec]:
3520        """Return vectors that can be used in matrix vector products.
3521
3522        Collective.
3523
3524        Parameters
3525        ----------
3526        side
3527            If `None` returns a 2-tuple of vectors ``(right, left)``.
3528            Otherwise it just returns a left or right vector.
3529
3530        Notes
3531        -----
3532        ``right`` is a vector that the matrix can be multiplied against.
3533        ``left`` is a vector that the matrix-vector product can be stored in.
3534
3535        See Also
3536        --------
3537        createVecLeft, createVecRight, petsc.MatCreateVecs
3538
3539        """
3540        cdef Vec vecr, vecl
3541        if side is None:
3542            vecr = Vec(); vecl = Vec()
3543            CHKERR(MatCreateVecs(self.mat, &vecr.vec, &vecl.vec))
3544            return (vecr, vecl)
3545        elif side in ('r', 'R', 'right', 'Right', 'RIGHT'):
3546            vecr = Vec()
3547            CHKERR(MatCreateVecs(self.mat, &vecr.vec, NULL))
3548            return vecr
3549        elif side in ('l', 'L', 'left',  'Left', 'LEFT'):
3550            vecl = Vec()
3551            CHKERR(MatCreateVecs(self.mat, NULL, &vecl.vec))
3552            return vecl
3553        else:
3554            raise ValueError("side '%r' not understood" % side)
3555
3556    def createVecRight(self) -> Vec:
3557        """Return a right vector, a vector that the matrix can be multiplied against.
3558
3559        Collective.
3560
3561        See Also
3562        --------
3563        createVecs, createVecLeft, petsc.MatCreateVecs
3564
3565        """
3566        cdef Vec vecr = Vec()
3567        CHKERR(MatCreateVecs(self.mat, &vecr.vec, NULL))
3568        return vecr
3569
3570    def createVecLeft(self) -> Vec:
3571        """Return a left vector, a vector that the matrix vector product can be stored in.
3572
3573        Collective.
3574
3575        See Also
3576        --------
3577        createVecs, createVecRight, petsc.MatCreateVecs
3578
3579        """
3580        cdef Vec vecl = Vec()
3581        CHKERR(MatCreateVecs(self.mat, NULL, &vecl.vec))
3582        return vecl
3583
3584    getVecs = createVecs
3585    getVecRight = createVecRight
3586    getVecLeft = createVecLeft
3587
3588    #
3589
3590    def getColumnVector(self, column: int, Vec result=None) -> Vec:
3591        """Return the columnᵗʰ column vector of the matrix.
3592
3593        Collective.
3594
3595        Parameters
3596        ----------
3597        column
3598            Column index.
3599        result
3600            Optional vector to store the result.
3601
3602        See Also
3603        --------
3604        petsc.MatGetColumnVector
3605
3606        """
3607        cdef PetscInt ival = asInt(column)
3608        if result is None:
3609            result = Vec()
3610        if result.vec == NULL:
3611            CHKERR(MatCreateVecs(self.mat, NULL, &result.vec))
3612        CHKERR(MatGetColumnVector(self.mat, result.vec, ival))
3613        return result
3614
3615    def getRedundantMatrix(self, nsubcomm: int, subcomm: Comm | None = None, Mat out=None) -> Mat:
3616        """Return redundant matrices on subcommunicators.
3617
3618        Collective.
3619
3620        Parameters
3621        ----------
3622        nsubcomm
3623            The number of subcommunicators.
3624        subcomm
3625            Communicator split or `None` for the null communicator.
3626        out
3627            Optional resultant matrix.
3628            When `None`, a new matrix is created, and ``MAT_INITIAL_MATRIX`` is used.
3629            When not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
3630
3631        See Also
3632        --------
3633        petsc.MatCreateRedundantMatrix
3634
3635        """
3636        cdef PetscInt _nsubcomm   = asInt(nsubcomm)
3637        cdef MPI_Comm _subcomm    = MPI_COMM_NULL
3638        if subcomm:   _subcomm    = def_Comm(subcomm, PETSC_COMM_DEFAULT)
3639        cdef PetscMatReuse reuse  = MAT_INITIAL_MATRIX
3640        if out is None: out       = Mat()
3641        if out.mat != NULL: reuse = MAT_REUSE_MATRIX
3642        CHKERR(MatCreateRedundantMatrix(self.mat, _nsubcomm, _subcomm, reuse, &out.mat))
3643        return out
3644
3645    def getDiagonal(self, Vec result=None) -> Vec:
3646        """Return the diagonal of the matrix.
3647
3648        Collective.
3649
3650        Parameters
3651        ----------
3652        result
3653            Optional vector to store the result.
3654
3655        See Also
3656        --------
3657        setDiagonal, petsc.MatGetDiagonal
3658
3659        """
3660        if result is None:
3661            result = Vec()
3662        if result.vec == NULL:
3663            CHKERR(MatCreateVecs(self.mat, NULL, &result.vec))
3664        CHKERR(MatGetDiagonal(self.mat, result.vec))
3665        return result
3666
3667    def getRowSum(self, Vec result=None) -> Vec:
3668        """Return the row-sum vector.
3669
3670        Collective.
3671
3672        Parameters
3673        ----------
3674        result
3675            Optional vector to store the result.
3676
3677        See Also
3678        --------
3679        petsc.MatGetRowSum
3680
3681        """
3682        if result is None:
3683            result = Vec()
3684        if result.vec == NULL:
3685            CHKERR(MatCreateVecs(self.mat, NULL, &result.vec))
3686        CHKERR(MatGetRowSum(self.mat, result.vec))
3687        return result
3688
3689    def setDiagonal(self, Vec diag, addv: InsertModeSpec = None) -> None:
3690        """Set the diagonal values of the matrix.
3691
3692        Collective.
3693
3694        Parameters
3695        ----------
3696        diag
3697            Vector storing diagonal values.
3698        addv
3699            Insertion mode.
3700
3701        See Also
3702        --------
3703        getDiagonal, petsc.MatDiagonalSet
3704
3705        """
3706        cdef PetscInsertMode caddv = insertmode(addv)
3707        CHKERR(MatDiagonalSet(self.mat, diag.vec, caddv))
3708
3709    def diagonalScale(self, Vec L=None, Vec R=None) -> None:
3710        """Perform left and/or right diagonal scaling of the matrix.
3711
3712        Collective.
3713
3714        Parameters
3715        ----------
3716        L
3717            Optional left scaling vector.
3718        R
3719            Optional right scaling vector.
3720
3721        See Also
3722        --------
3723        petsc.MatDiagonalScale
3724
3725        """
3726        cdef PetscVec vecl=NULL, vecr=NULL
3727        if L is not None: vecl = L.vec
3728        if R is not None: vecr = R.vec
3729        CHKERR(MatDiagonalScale(self.mat, vecl, vecr))
3730
3731    def invertBlockDiagonal(self) -> ArrayScalar:
3732        """Return the inverse of the block-diagonal entries.
3733
3734        Collective.
3735
3736        See Also
3737        --------
3738        petsc.MatInvertBlockDiagonal
3739
3740        """
3741        cdef PetscInt bs = 0, m = 0
3742        cdef const PetscScalar *cibdiag = NULL
3743        CHKERR(MatGetBlockSize(self.mat, &bs))
3744        CHKERR(MatGetLocalSize(self.mat, &m, NULL))
3745        CHKERR(MatInvertBlockDiagonal(self.mat, &cibdiag))
3746        cdef ndarray ibdiag = array_s(m*bs, cibdiag)
3747        ibdiag.shape = (toInt(m//bs), toInt(bs), toInt(bs))
3748        return ibdiag.transpose(0, 2, 1)
3749
3750    # null space
3751
3752    def setNullSpace(self, NullSpace nsp) -> None:
3753        """Set the nullspace.
3754
3755        Collective.
3756
3757        See Also
3758        --------
3759        getNullSpace, petsc.MatSetNullSpace
3760
3761        """
3762        CHKERR(MatSetNullSpace(self.mat, nsp.nsp))
3763
3764    def getNullSpace(self) -> NullSpace:
3765        """Return the nullspace.
3766
3767        Not collective.
3768
3769        See Also
3770        --------
3771        setNullSpace, petsc.MatGetNullSpace
3772
3773        """
3774        cdef NullSpace nsp = NullSpace()
3775        CHKERR(MatGetNullSpace(self.mat, &nsp.nsp))
3776        CHKERR(PetscINCREF(nsp.obj))
3777        return nsp
3778
3779    def setTransposeNullSpace(self, NullSpace nsp) -> None:
3780        """Set the transpose nullspace.
3781
3782        Collective.
3783
3784        See Also
3785        --------
3786        setNullSpace, getTransposeNullSpace, petsc.MatSetTransposeNullSpace
3787
3788        """
3789        CHKERR(MatSetTransposeNullSpace(self.mat, nsp.nsp))
3790
3791    def getTransposeNullSpace(self) -> NullSpace:
3792        """Return the transpose nullspace.
3793
3794        Not collective.
3795
3796        See Also
3797        --------
3798        getNullSpace, setTransposeNullSpace, petsc.MatGetTransposeNullSpace
3799
3800        """
3801        cdef NullSpace nsp = NullSpace()
3802        CHKERR(MatGetTransposeNullSpace(self.mat, &nsp.nsp))
3803        CHKERR(PetscINCREF(nsp.obj))
3804        return nsp
3805
3806    def setNearNullSpace(self, NullSpace nsp) -> None:
3807        """Set the near-nullspace.
3808
3809        Collective.
3810
3811        See Also
3812        --------
3813        setNullSpace, getNearNullSpace, petsc.MatSetNearNullSpace
3814
3815        """
3816        CHKERR(MatSetNearNullSpace(self.mat, nsp.nsp))
3817
3818    def getNearNullSpace(self) -> NullSpace:
3819        """Return the near-nullspace.
3820
3821        Not collective.
3822
3823        See Also
3824        --------
3825        getNullSpace, setNearNullSpace, petsc.MatSetNearNullSpace
3826
3827        """
3828        cdef NullSpace nsp = NullSpace()
3829        CHKERR(MatGetNearNullSpace(self.mat, &nsp.nsp))
3830        CHKERR(PetscINCREF(nsp.obj))
3831        return nsp
3832
3833    # matrix-vector product
3834
3835    def mult(self, Vec x, Vec y) -> None:
3836        """Perform the matrix vector product y = A @ x.
3837
3838        Collective.
3839
3840        Parameters
3841        ----------
3842        x
3843            The input vector.
3844        y
3845            The output vector.
3846
3847        See Also
3848        --------
3849        petsc.MatMult
3850
3851        """
3852        CHKERR(MatMult(self.mat, x.vec, y.vec))
3853
3854    def multAdd(self, Vec x, Vec v, Vec y) -> None:
3855        """Perform the matrix vector product with addition y = A @ x + v.
3856
3857        Collective.
3858
3859        Parameters
3860        ----------
3861        x
3862            The input vector for the matrix-vector product.
3863        v
3864            The input vector to be added to.
3865        y
3866            The output vector.
3867
3868        See Also
3869        --------
3870        petsc.MatMultAdd
3871
3872        """
3873        CHKERR(MatMultAdd(self.mat, x.vec, v.vec, y.vec))
3874
3875    def multTranspose(self, Vec x, Vec y) -> None:
3876        """Perform the transposed matrix vector product y = A^T @ x.
3877
3878        Collective.
3879
3880        Parameters
3881        ----------
3882        x
3883            The input vector.
3884        y
3885            The output vector.
3886
3887        See Also
3888        --------
3889        petsc.MatMultTranspose
3890
3891        """
3892        CHKERR(MatMultTranspose(self.mat, x.vec, y.vec))
3893
3894    def multTransposeAdd(self, Vec x, Vec v, Vec y) -> None:
3895        """Perform the transposed matrix vector product with addition y = A^T @ x + v.
3896
3897        Collective.
3898
3899        Parameters
3900        ----------
3901        x
3902            The input vector for the transposed matrix-vector product.
3903        v
3904            The input vector to be added to.
3905        y
3906            The output vector.
3907
3908        See Also
3909        --------
3910        petsc.MatMultTransposeAdd
3911
3912        """
3913        CHKERR(MatMultTransposeAdd(self.mat, x.vec, v.vec, y.vec))
3914
3915    def multHermitian(self, Vec x, Vec y) -> None:
3916        """Perform the Hermitian matrix vector product y = A^H @ x.
3917
3918        Collective.
3919
3920        Parameters
3921        ----------
3922        x
3923            The input vector for the Hermitian matrix-vector product.
3924        y
3925            The output vector.
3926
3927        See Also
3928        --------
3929        petsc.MatMultHermitianTranspose
3930
3931        """
3932        CHKERR(MatMultHermitian(self.mat, x.vec, y.vec))
3933
3934    def multHermitianAdd(self, Vec x, Vec v, Vec y) -> None:
3935        """Perform the Hermitian matrix vector product with addition y = A^H @ x + v.
3936
3937        Collective.
3938
3939        Parameters
3940        ----------
3941        x
3942            The input vector for the Hermitian matrix-vector product.
3943        v
3944            The input vector to be added to.
3945        y
3946            The output vector.
3947
3948        See Also
3949        --------
3950        petsc.MatMultHermitianTransposeAdd
3951
3952        """
3953        CHKERR(MatMultHermitianAdd(self.mat, x.vec, v.vec, y.vec))
3954
3955    # SOR
3956
3957    def SOR(
3958        self,
3959        Vec b,
3960        Vec x,
3961        omega: float = 1.0,
3962        sortype: SORType | None = None,
3963        shift: float = 0.0,
3964        its: int = 1,
3965        lits: int = 1) -> None:
3966        """Compute relaxation (SOR, Gauss-Seidel) sweeps.
3967
3968        Neighborwise collective.
3969
3970        See Also
3971        --------
3972        petsc.MatSOR
3973
3974        """
3975        cdef PetscReal comega = asReal(omega)
3976        cdef PetscMatSORType csortype = SOR_LOCAL_SYMMETRIC_SWEEP
3977        if sortype is not None:
3978            csortype = <PetscMatSORType> asInt(sortype)
3979        cdef PetscReal cshift = asReal(shift)
3980        cdef PetscInt cits = asInt(its)
3981        cdef PetscInt clits = asInt(lits)
3982        CHKERR(MatSOR(self.mat, b.vec, comega, csortype, cshift, cits, clits, x.vec))
3983
3984    #
3985
3986    def getDiagonalBlock(self) -> Mat:
3987        """Return the part of the matrix associated with the on-process coupling.
3988
3989        Not collective.
3990
3991        See Also
3992        --------
3993        petsc.MatGetDiagonalBlock
3994
3995        """
3996        cdef Mat submat = Mat()
3997        CHKERR(MatGetDiagonalBlock(self.mat, &submat.mat))
3998        CHKERR(PetscINCREF(submat.obj))
3999        return submat
4000
4001    def increaseOverlap(self, IS iset, overlap: int = 1) -> None:
4002        """Increase the overlap of a index set.
4003
4004        Collective.
4005
4006        See Also
4007        --------
4008        petsc.MatIncreaseOverlap
4009
4010        """
4011        cdef PetscInt ival = asInt(overlap)
4012        CHKERR(MatIncreaseOverlap(self.mat, 1, &iset.iset, ival))
4013
4014    def createSubMatrix(self, IS isrow, IS iscol=None, Mat submat=None) -> Mat:
4015        """Return a submatrix.
4016
4017        Collective.
4018
4019        Parameters
4020        ----------
4021        isrow
4022            Row index set.
4023        iscol
4024            Column index set. If `None`, ``iscol = isrow``.
4025        submat
4026            Optional resultant matrix.
4027            When `None`, a new matrix is created, and ``MAT_INITIAL_MATRIX`` is used.
4028            When not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4029
4030        See Also
4031        --------
4032        petsc.MatCreateSubMatrix
4033
4034        """
4035        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4036        cdef PetscIS ciscol = NULL
4037        if iscol is not None: ciscol = iscol.iset
4038        if submat is None: submat = Mat()
4039        if submat.mat != NULL: reuse = MAT_REUSE_MATRIX
4040        CHKERR(MatCreateSubMatrix(self.mat, isrow.iset, ciscol,
4041                                  reuse, &submat.mat))
4042        return submat
4043
4044    def createSubMatrices(
4045        self,
4046        isrows: IS | Sequence[IS],
4047        iscols: IS | Sequence[IS] | None = None,
4048        submats: Mat | Sequence[Mat] | None = None) -> Sequence[Mat]:
4049        """Return several sequential submatrices.
4050
4051        Collective.
4052
4053        Parameters
4054        ----------
4055        isrows
4056            Row index sets.
4057        iscols
4058            Column index sets. If `None`, ``iscols = isrows``.
4059        submats
4060            Optional resultant matrices.
4061            When `None`, new matrices are created, and ``MAT_INITIAL_MATRIX`` is used.
4062            When not `None`, the matrices are reused with ``MAT_REUSE_MATRIX``.
4063
4064        See Also
4065        --------
4066        petsc.MatCreateSubMatrices
4067
4068        """
4069        if iscols is None: iscols = isrows
4070        isrows = [isrows] if isinstance(isrows, IS) else list(isrows)
4071        iscols = [iscols] if isinstance(iscols, IS) else list(iscols)
4072        assert len(isrows) == len(iscols)
4073        cdef Py_ssize_t i, n = len(isrows)
4074        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4075        cdef PetscIS  *cisrows = NULL
4076        cdef PetscIS  *ciscols = NULL
4077        cdef PetscMat *cmats   = NULL
4078        cdef Mat mat
4079        cdef object unused1 = oarray_p(empty_p(<PetscInt>n), NULL, <void**>&cisrows)
4080        for i from 0 <= i < n: cisrows[i] = (<IS?>isrows[i]).iset
4081        cdef object unused2 = oarray_p(empty_p(<PetscInt>n), NULL, <void**>&ciscols)
4082        for i from 0 <= i < n: ciscols[i] = (<IS?>iscols[i]).iset
4083        if submats is not None:
4084            reuse = MAT_REUSE_MATRIX
4085            submats = list(submats)
4086            assert len(submats) == len(isrows)
4087            CHKERR(PetscMalloc(<size_t>(n+1)*sizeof(PetscMat), &cmats))
4088            for i from 0 <= i < n: cmats[i] = (<Mat?>submats[i]).mat
4089        CHKERR(MatCreateSubMatrices(self.mat, <PetscInt>n, cisrows, ciscols, reuse, &cmats))
4090        for i from 0 <= i < n: CHKERR(PetscINCREF(<PetscObject*>&cmats[i]))
4091        if reuse == MAT_INITIAL_MATRIX:
4092            submats = [None] * n
4093            for i from 0 <= i < n:
4094                submats[i] = mat = Mat()
4095                mat.mat = cmats[i]
4096        CHKERR(MatDestroyMatrices(<PetscInt>n, &cmats))
4097        return submats
4098
4099    #
4100
4101    def createSchurComplement(self, Mat A00, Mat Ap00, Mat A01, Mat A10, Mat A11=None) -> Self:
4102        """Create a `Type.SCHURCOMPLEMENT` matrix.
4103
4104        Collective.
4105
4106        Parameters
4107        ----------
4108        A00
4109            the upper-left block of the original matrix A = [A00 A01; A10 A11].
4110        Ap00
4111            used to construct the preconditioner used in ksp(A00,Ap00) to
4112            approximate the action of A00^{-1}.
4113        A01
4114            the upper-right block of the original matrix A = [A00 A01; A10 A11].
4115        A10
4116            the lower-left block of the original matrix A = [A00 A01; A10 A11].
4117        A11
4118            Optional lower-right block of the original matrix
4119            A = [A00 A01; A10 A11].
4120
4121        See Also
4122        --------
4123        petsc.MatCreateSchurComplement
4124
4125        """
4126        cdef PetscMat newmat = NULL, A11_mat = NULL
4127        if A11 is not None:
4128            A11_mat = A11.mat
4129        CHKERR(MatCreateSchurComplement(A00.mat, Ap00.mat, A01.mat, A10.mat, A11_mat, &newmat))
4130        CHKERR(PetscCLEAR(self.obj)); self.mat = newmat
4131        return self
4132
4133    #
4134
4135    def getSchurComplementSubMatrices(self) -> tuple[Mat, Mat, Mat, Mat, Mat]:
4136        """Return Schur complement sub-matrices.
4137
4138        Collective.
4139
4140        See Also
4141        --------
4142        petsc.MatSchurComplementGetSubMatrices
4143
4144        """
4145        cdef Mat A00 = Mat(), Ap00 = Mat(), A01 = Mat(), A10 = Mat(), A11 = Mat()
4146        CHKERR(MatSchurComplementGetSubMatrices(self.mat, &A00.mat, &Ap00.mat, &A01.mat, &A10.mat, &A11.mat))
4147        CHKERR(PetscINCREF(A00.obj))
4148        CHKERR(PetscINCREF(Ap00.obj))
4149        CHKERR(PetscINCREF(A01.obj))
4150        CHKERR(PetscINCREF(A10.obj))
4151        CHKERR(PetscINCREF(A11.obj))
4152        return A00, Ap00, A01, A10, A11
4153
4154    #
4155
4156    def getLocalSubMatrix(self, IS isrow, IS iscol, Mat submat=None) -> Mat:
4157        """Return a reference to a submatrix specified in local numbering.
4158
4159        Collective.
4160
4161        Parameters
4162        ----------
4163        isrow
4164            Row index set.
4165        iscol
4166            Column index set.
4167        submat
4168            Optional resultant matrix.
4169            When `None`, a new matrix is created.
4170            When not `None`, the matrix is first destroyed and then recreated.
4171
4172        See Also
4173        --------
4174        restoreLocalSubMatrix, petsc.MatGetLocalSubMatrix
4175
4176        """
4177        if submat is None: submat = Mat()
4178        else: CHKERR(MatDestroy(&submat.mat))
4179        CHKERR(MatGetLocalSubMatrix(self.mat, isrow.iset, iscol.iset, &submat.mat))
4180        return submat
4181
4182    def restoreLocalSubMatrix(self, IS isrow, IS iscol, Mat submat) -> None:
4183        """Restore a reference to a submatrix obtained with `getLocalSubMatrix`.
4184
4185        Collective.
4186
4187        Parameters
4188        ----------
4189        isrow
4190            Row index set.
4191        iscol
4192            Column index set.
4193        submat
4194            The submatrix.
4195
4196        See Also
4197        --------
4198        getLocalSubMatrix, petsc.MatRestoreLocalSubMatrix
4199
4200        """
4201        CHKERR(MatRestoreLocalSubMatrix(self.mat, isrow.iset, iscol.iset, &submat.mat))
4202
4203    #
4204
4205    def norm(
4206        self,
4207        norm_type: NormTypeSpec = None) -> float | tuple[float, float]:
4208        """Compute the requested matrix norm.
4209
4210        Collective.
4211
4212        A 2-tuple is returned if `NormType.NORM_1_AND_2` is specified.
4213
4214        See Also
4215        --------
4216        petsc.MatNorm, petsc.NormType
4217
4218        """
4219        cdef PetscNormType norm_1_2 = PETSC_NORM_1_AND_2
4220        cdef PetscNormType ntype = PETSC_NORM_FROBENIUS
4221        if norm_type is not None: ntype = norm_type
4222        cdef PetscReal rval[2]
4223        CHKERR(MatNorm(self.mat, ntype, rval))
4224        if ntype != norm_1_2: return toReal(rval[0])
4225        else: return (toReal(rval[0]), toReal(rval[1]))
4226
4227    def scale(self, alpha: Scalar) -> None:
4228        """Scale the matrix.
4229
4230        Collective.
4231
4232        See Also
4233        --------
4234        petsc.MatScale
4235
4236        """
4237        cdef PetscScalar sval = asScalar(alpha)
4238        CHKERR(MatScale(self.mat, sval))
4239
4240    def shift(self, alpha: Scalar) -> None:
4241        """Shift the matrix.
4242
4243        Collective.
4244
4245        See Also
4246        --------
4247        petsc.MatShift
4248
4249        """
4250        cdef PetscScalar sval = asScalar(alpha)
4251        CHKERR(MatShift(self.mat, sval))
4252
4253    def chop(self, tol: float) -> None:
4254        """Set entries smallest of tol (in absolute values) to zero.
4255
4256        Collective.
4257
4258        See Also
4259        --------
4260        petsc.MatFilter
4261
4262        """
4263        cdef PetscReal rval = asReal(tol)
4264        CHKERR(MatFilter(self.mat, rval, PETSC_FALSE, PETSC_FALSE))
4265
4266    def setRandom(self, Random random=None) -> None:
4267        """Set random values in the matrix.
4268
4269        Collective.
4270
4271        Parameters
4272        ----------
4273        random
4274            The random number generator object or `None` for the default.
4275
4276        See Also
4277        --------
4278        petsc.MatSetRandom
4279
4280        """
4281        cdef PetscRandom rnd = NULL
4282        if random is not None: rnd = random.rnd
4283        CHKERR(MatSetRandom(self.mat, rnd))
4284
4285    def axpy(self, alpha: Scalar, Mat X, structure: Structure | None = None) -> None:
4286        """Perform the matrix summation ``self`` + = ɑ·X.
4287
4288        Collective.
4289
4290        Parameters
4291        ----------
4292        alpha
4293            The scalar.
4294        X
4295            The matrix to be added.
4296        structure
4297            The structure of the operation.
4298
4299        See Also
4300        --------
4301        petsc.MatAXPY
4302
4303        """
4304        cdef PetscScalar sval = asScalar(alpha)
4305        cdef PetscMatStructure flag = matstructure(structure)
4306        CHKERR(MatAXPY(self.mat, sval, X.mat, flag))
4307
4308    def aypx(self, alpha: Scalar, Mat X, structure: Structure | None = None) -> None:
4309        """Perform the matrix summation ``self`` = ɑ·``self`` + X.
4310
4311        Collective.
4312
4313        Parameters
4314        ----------
4315        alpha
4316            The scalar.
4317        X
4318            The matrix to be added.
4319        structure
4320            The structure of the operation.
4321
4322        See Also
4323        --------
4324        petsc.MatAYPX
4325
4326        """
4327        cdef PetscScalar sval = asScalar(alpha)
4328        cdef PetscMatStructure flag = matstructure(structure)
4329        CHKERR(MatAYPX(self.mat, sval, X.mat, flag))
4330
4331    # matrix-matrix product
4332
4333    def matMult(
4334        self,
4335        Mat mat,
4336        Mat result=None,
4337        fill: float | None = None) -> Mat:
4338        """Perform matrix-matrix multiplication C=AB.
4339
4340        Neighborwise collective.
4341
4342        Parameters
4343        ----------
4344        mat
4345            The right hand matrix B.
4346        result
4347            The optional resultant matrix C. When `None`, a new matrix
4348            is created, and ``MAT_INITIAL_MATRIX`` is used. When C is
4349            not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4350        fill
4351            Expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use
4352            `None` if you do not have a good estimate. If the
4353            result is a dense matrix this is irrelevant.
4354
4355        Returns
4356        -------
4357        result : Mat
4358            The resultant product matrix C.
4359
4360        Notes
4361        -----
4362        To determine the correct fill value, run with -info and search
4363        for the string "Fill ratio" to see the value actually needed.
4364
4365        See Also
4366        --------
4367        petsc.MatMatMult, petsc.MatReuse
4368
4369        """
4370        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4371        cdef PetscReal rval = 2
4372        if result is None:
4373            result = Mat()
4374        elif result.mat != NULL:
4375            reuse = MAT_REUSE_MATRIX
4376        if fill is not None: rval = asReal(fill)
4377        CHKERR(MatMatMult(self.mat, mat.mat, reuse, rval, &result.mat))
4378        return result
4379
4380    def matTransposeMult(
4381        self,
4382        Mat mat,
4383        Mat result=None,
4384        fill: float | None = None) -> Mat:
4385        """Perform matrix-matrix multiplication C=ABᵀ.
4386
4387        Neighborwise collective.
4388
4389        Parameters
4390        ----------
4391        mat
4392            The right hand matrix B.
4393        result
4394            The optional resultant matrix C. When `None`, a new matrix
4395            is created, and ``MAT_INITIAL_MATRIX`` is used. When C is
4396            not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4397        fill
4398            Expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use
4399            `None` if you do not have a good estimate. If the
4400            result is a dense matrix this is irrelevant.
4401
4402        Returns
4403        -------
4404        result : Mat
4405            The resultant product matrix C.
4406
4407        Notes
4408        -----
4409        To determine the correct fill value, run with -info and search
4410        for the string "Fill ratio" to see the value actually needed.
4411
4412        See Also
4413        --------
4414        petsc.MatMatTransposeMult, petsc.MatReuse
4415
4416        """
4417        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4418        cdef PetscReal rval = 2
4419        if result is None:
4420            result = Mat()
4421        elif result.mat != NULL:
4422            reuse = MAT_REUSE_MATRIX
4423        if fill is not None: rval = asReal(fill)
4424        CHKERR(MatMatTransposeMult(self.mat, mat.mat, reuse, rval, &result.mat))
4425        return result
4426
4427    def transposeMatMult(
4428        self,
4429        Mat mat,
4430        Mat result=None,
4431        fill: float | None = None) -> Mat:
4432        """Perform matrix-matrix multiplication C=AᵀB.
4433
4434        Neighborwise collective.
4435
4436        Parameters
4437        ----------
4438        mat
4439            The right hand matrix B.
4440        result
4441            The optional resultant matrix C. When `None`, a new matrix
4442            is created, and ``MAT_INITIAL_MATRIX`` is used. When C is
4443            not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4444        fill
4445            Expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use
4446            `None` if you do not have a good estimate. If the
4447            result is a dense matrix this is irrelevant.
4448
4449        Returns
4450        -------
4451        result : Mat
4452            The resultant product matrix C.
4453
4454        Notes
4455        -----
4456        To determine the correct fill value, run with -info and search
4457        for the string "Fill ratio" to see the value actually needed.
4458
4459        See Also
4460        --------
4461        petsc.MatTransposeMatMult, petsc.MatReuse
4462
4463        """
4464        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4465        cdef PetscReal rval = 2
4466        if result is None:
4467            result = Mat()
4468        elif result.mat != NULL:
4469            reuse = MAT_REUSE_MATRIX
4470        if fill is not None: rval = asReal(fill)
4471        CHKERR(MatTransposeMatMult(self.mat, mat.mat, reuse, rval, &result.mat))
4472        return result
4473
4474    def ptap(
4475        self,
4476        Mat P,
4477        Mat result=None,
4478        fill: float | None = None) -> Mat:
4479        """Creates the matrix product C = PᵀAP.
4480
4481        Neighborwise collective.
4482
4483        Parameters
4484        ----------
4485        P
4486            The matrix P.
4487        result
4488            The optional resultant matrix C. When `None`, a new matrix
4489            is created, and ``MAT_INITIAL_MATRIX`` is used. When C is
4490            not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4491        fill
4492            Expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use
4493            `None` if you do not have a good estimate. If the
4494            result is a dense matrix this is irrelevant.
4495
4496        Returns
4497        -------
4498        result : Mat
4499            The resultant product matrix C.
4500
4501        Notes
4502        -----
4503        To determine the correct fill value, run with -info and search
4504        for the string "Fill ratio" to see the value actually needed.
4505
4506        An alternative approach to this function is to use
4507        `petsc.MatProductCreate` and set the desired options before the
4508        computation is done.
4509
4510        See Also
4511        --------
4512        petsc.MatPtAP, petsc.MatReuse
4513
4514        """
4515        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4516        cdef PetscReal cfill = PETSC_DEFAULT
4517        if result is None:
4518            result = Mat()
4519        elif result.mat != NULL:
4520            reuse = MAT_REUSE_MATRIX
4521        if fill is not None: cfill = asReal(fill)
4522        CHKERR(MatPtAP(self.mat, P.mat, reuse, cfill, &result.mat))
4523        return result
4524
4525    def rart(
4526        self,
4527        Mat R,
4528        Mat result=None,
4529        fill: float | None = None) -> Mat:
4530        """Create the matrix product C = RARᵀ.
4531
4532        Neighborwise collective.
4533
4534        Parameters
4535        ----------
4536        R
4537            The projection matrix.
4538        result
4539            The optional resultant matrix C. When `None`, a new matrix
4540            is created, and ``MAT_INITIAL_MATRIX`` is used. When C is
4541            not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4542        fill
4543            Expected fill as ratio of nnz(C)/nnz(A), use `None` if
4544            you do not have a good estimate. If the result is a dense
4545            matrix this is irrelevant.
4546
4547        Returns
4548        -------
4549        result : Mat
4550            The resultant product matrix C.
4551
4552        Notes
4553        -----
4554        To determine the correct fill value, run with -info and search
4555        for the string "Fill ratio" to see the value actually needed.
4556
4557        See Also
4558        --------
4559        petsc.MatRARt, petsc.MatReuse
4560
4561        """
4562        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4563        cdef PetscReal cfill = PETSC_DEFAULT
4564        if result is None:
4565            result = Mat()
4566        elif result.mat != NULL:
4567            reuse = MAT_REUSE_MATRIX
4568        if fill is not None: cfill = asReal(fill)
4569        CHKERR(MatRARt(self.mat, R.mat, reuse, cfill, &result.mat))
4570        return result
4571
4572    def matMatMult(
4573        self,
4574        Mat B,
4575        Mat C,
4576        Mat result=None,
4577        fill: float | None = None) -> Mat:
4578        """Perform matrix-matrix-matrix multiplication D=ABC.
4579
4580        Neighborwise collective.
4581
4582        Parameters
4583        ----------
4584        B
4585            The middle matrix B.
4586        C
4587            The right hand matrix C.
4588        result
4589            The optional resultant matrix D. When `None`, a new matrix
4590            is created, and ``MAT_INITIAL_MATRIX`` is used. When D is
4591            not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4592        fill
4593            Expected fill as ratio of nnz(C)/nnz(A), use `None` if
4594            you do not have a good estimate. If the result is a dense
4595            matrix this is irrelevant.
4596
4597        Returns
4598        -------
4599        result : Mat
4600            The resultant product matrix D.
4601
4602        See Also
4603        --------
4604        petsc.MatMatMatMult, petsc.MatReuse
4605
4606        """
4607        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4608        cdef PetscReal cfill = PETSC_DEFAULT
4609        if result is None:
4610            result = Mat()
4611        elif result.mat != NULL:
4612            reuse = MAT_REUSE_MATRIX
4613        if fill is not None: cfill = asReal(fill)
4614        CHKERR(MatMatMatMult(self.mat, B.mat, C.mat, reuse, cfill, &result.mat))
4615        return result
4616
4617    def kron(
4618        self,
4619        Mat mat,
4620        Mat result=None) -> Mat:
4621        """Compute C, the Kronecker product of A and B.
4622
4623        Collective.
4624
4625        Parameters
4626        ----------
4627        mat
4628            The right hand matrix B.
4629        result
4630            The optional resultant matrix. When `None`, a new matrix
4631            is created, and ``MAT_INITIAL_MATRIX`` is used. When it is
4632            not `None`, the matrix is reused with ``MAT_REUSE_MATRIX``.
4633
4634        Returns
4635        -------
4636        result : Mat
4637            The resultant matrix C, the Kronecker product of A and B.
4638
4639        See Also
4640        --------
4641        petsc.MatSeqAIJKron, petsc.MatReuse
4642
4643        """
4644        cdef PetscMatReuse reuse = MAT_INITIAL_MATRIX
4645        if result is None:
4646            result = Mat()
4647        elif result.mat != NULL:
4648            reuse = MAT_REUSE_MATRIX
4649        CHKERR(MatSeqAIJKron(self.mat, mat.mat, reuse, &result.mat))
4650        return result
4651
4652    def bindToCPU(self, flg: bool) -> None:
4653        """Mark a matrix to temporarily stay on the CPU.
4654
4655        Collective.
4656
4657        Once marked, perform computations on the CPU.
4658
4659        Parameters
4660        ----------
4661        flg
4662            Bind to the CPU if `True`.
4663
4664        See Also
4665        --------
4666        petsc.MatBindToCPU
4667
4668        """
4669        cdef PetscBool bindFlg = asBool(flg)
4670        CHKERR(MatBindToCPU(self.mat, bindFlg))
4671
4672    def boundToCPU(self) -> bool:
4673        """Query if a matrix is bound to the CPU.
4674
4675        Not collective.
4676
4677        See Also
4678        --------
4679        petsc.MatBoundToCPU
4680
4681        """
4682        cdef PetscBool flg = PETSC_TRUE
4683        CHKERR(MatBoundToCPU(self.mat, &flg))
4684        return toBool(flg)
4685
4686    # XXX factorization
4687
4688    def getOrdering(self, ord_type: OrderingType) -> tuple[IS, IS]:
4689        """Return a reordering for a matrix to improve a LU factorization.
4690
4691        Collective.
4692
4693        Parameters
4694        ----------
4695        ord_type
4696            The type of reordering.
4697
4698        Returns
4699        -------
4700        rp : IS
4701            The row permutation indices.
4702        cp : IS
4703            The column permutation indices.
4704
4705        See Also
4706        --------
4707        petsc.MatGetOrdering
4708
4709        """
4710        cdef PetscMatOrderingType cval = NULL
4711        ord_type = str2bytes(ord_type, &cval)
4712        cdef IS rp = IS(), cp = IS()
4713        CHKERR(MatGetOrdering(self.mat, cval, &rp.iset, &cp.iset))
4714        return (rp, cp)
4715
4716    def reorderForNonzeroDiagonal(
4717        self,
4718        IS isrow,
4719        IS iscol,
4720        atol: float = 0) -> None:
4721        """Change a matrix ordering to remove zeros from the diagonal.
4722
4723        Collective.
4724
4725        Parameters
4726        ----------
4727        isrow
4728            The row reordering.
4729        iscol
4730            The column reordering.
4731        atol
4732            The absolute tolerance. Values along the diagonal whose absolute value
4733            are smaller than this tolerance are moved off the diagonal.
4734
4735        See Also
4736        --------
4737        getOrdering, petsc.MatReorderForNonzeroDiagonal
4738
4739        """
4740        cdef PetscReal rval = asReal(atol)
4741        cdef PetscIS rp = isrow.iset, cp = iscol.iset
4742        CHKERR(MatReorderForNonzeroDiagonal(self.mat, rval, rp, cp))
4743
4744    def factorLU(
4745        self,
4746        IS isrow,
4747        IS iscol,
4748        options: dict[str, Any] | None = None) -> None:
4749        """Perform an in-place LU factorization.
4750
4751        Collective.
4752
4753        Parameters
4754        ----------
4755        isrow
4756            The row permutation.
4757        iscol
4758            The column permutation.
4759        options
4760            An optional dictionary of options for the factorization. These include
4761            ``fill``, the expected fill as a ratio of the original fill and
4762            ``dtcol``, the pivot tolerance where ``0`` indicates no pivot and ``1``
4763            indicates full column pivoting.
4764
4765        See Also
4766        --------
4767        petsc.MatLUFactor
4768
4769        """
4770        cdef PetscMatFactorInfo info
4771        matfactorinfo(PETSC_FALSE, PETSC_FALSE, options, &info)
4772        CHKERR(MatLUFactor(self.mat, isrow.iset, iscol.iset, &info))
4773
4774    def factorSymbolicLU(self, Mat mat, IS isrow, IS iscol, options=None) -> None:
4775        """Not implemented."""
4776        raise NotImplementedError
4777
4778    def factorNumericLU(self, Mat mat, options=None) -> None:
4779        """Not implemented."""
4780        raise NotImplementedError
4781
4782    def factorILU(
4783        self,
4784        IS isrow,
4785        IS iscol,
4786        options: dict[str, Any] | None = None) -> None:
4787        """Perform an in-place ILU factorization.
4788
4789        Collective.
4790
4791        Parameters
4792        ----------
4793        isrow
4794            The row permutation.
4795        iscol
4796            The column permutation.
4797        options
4798            An optional dictionary of options for the factorization. These include
4799            ``levels``, the number of levels of fill, ``fill``, the expected fill
4800            as a ratio of the original fill, and ``dtcol``, the pivot tolerance
4801            where ``0`` indicates no pivot and ``1`` indicates full column pivoting.
4802
4803        See Also
4804        --------
4805        petsc.MatILUFactor
4806
4807        """
4808        cdef PetscMatFactorInfo info
4809        matfactorinfo(PETSC_TRUE, PETSC_FALSE, options, &info)
4810        CHKERR(MatILUFactor(self.mat, isrow.iset, iscol.iset, &info))
4811
4812    def factorSymbolicILU(self, IS isrow, IS iscol, options=None) -> None:
4813        """Not implemented."""
4814        raise NotImplementedError
4815
4816    def factorCholesky(
4817        self,
4818        IS isperm,
4819        options: dict[str, Any] | None = None) -> None:
4820        """Perform an in-place Cholesky factorization.
4821
4822        Collective.
4823
4824        Parameters
4825        ----------
4826        isperm
4827            The row and column permutations.
4828        options
4829            An optional dictionary of options for the factorization. These include
4830            ``fill``, the expected fill as a ratio of the original fill.
4831
4832        See Also
4833        --------
4834        factorLU, petsc.MatCholeskyFactor
4835
4836        """
4837        cdef PetscMatFactorInfo info
4838        matfactorinfo(PETSC_FALSE, PETSC_TRUE, options, &info)
4839        CHKERR(MatCholeskyFactor(self.mat, isperm.iset, &info))
4840
4841    def factorSymbolicCholesky(self, IS isperm, options=None) -> None:
4842        """Not implemented."""
4843        raise NotImplementedError
4844
4845    def factorNumericCholesky(self, Mat mat, options=None) -> None:
4846        """Not implemented."""
4847        raise NotImplementedError
4848
4849    def factorICC(
4850        self,
4851        IS isperm,
4852        options: dict[str, Any] | None = None) -> None:
4853        """Perform an in-place an incomplete Cholesky factorization.
4854
4855        Collective.
4856
4857        Parameters
4858        ----------
4859        isperm
4860            The row and column permutations
4861        options
4862            An optional dictionary of options for the factorization. These include
4863            ``fill``, the expected fill as a ratio of the original fill.
4864
4865        See Also
4866        --------
4867        factorILU, petsc.MatICCFactor
4868
4869        """
4870        cdef PetscMatFactorInfo info
4871        matfactorinfo(PETSC_TRUE, PETSC_TRUE, options, &info)
4872        CHKERR(MatICCFactor(self.mat, isperm.iset, &info))
4873
4874    def factorSymbolicICC(self, IS isperm, options=None) -> None:
4875        """Not implemented."""
4876        raise NotImplementedError
4877
4878    def getInertia(self) -> tuple[int, int, int]:
4879        """Return the inertia from a factored matrix.
4880
4881        Collective.
4882
4883        The matrix must have been factored by calling `factorCholesky`.
4884
4885        Returns
4886        -------
4887        n : int
4888            The number of negative eigenvalues.
4889        z : int
4890            The number of zero eigenvalues.
4891        p : int
4892            The number of positive eigenvalues.
4893
4894        See Also
4895        --------
4896        petsc.MatGetInertia
4897
4898        """
4899        cdef PetscInt ival1 = 0, ival2 = 0, ival3 = 0
4900        CHKERR(MatGetInertia(self.mat, &ival1, &ival2, &ival3))
4901        return (toInt(ival1), toInt(ival2), toInt(ival3))
4902
4903    def setUnfactored(self) -> None:
4904        """Set a factored matrix to be treated as unfactored.
4905
4906        Logically collective.
4907
4908        See Also
4909        --------
4910        petsc.MatSetUnfactored
4911
4912        """
4913        CHKERR(MatSetUnfactored(self.mat))
4914
4915    # IS
4916
4917    def setISAllowRepeated(self, allow: bool = True) -> None:
4918        """Allow repeated entries in the local to global map.
4919
4920        Logically collective.
4921
4922        Parameters
4923        ----------
4924        allow
4925            When `True`, local dofs are allowed to map to the same global dof.
4926
4927        See Also
4928        --------
4929        getISAllowRepeated, petsc.MatISSetAllowRepeated
4930
4931        """
4932        cdef PetscBool callow = asBool(allow)
4933        CHKERR(MatISSetAllowRepeated(self.mat, callow))
4934
4935    def getISAllowRepeated(self) -> bool:
4936        """Get the flag for repeated entries in the local to global map.
4937
4938        Not collective.
4939
4940        See Also
4941        --------
4942        setISAllowRepeated, petsc.MatISGetAllowRepeated
4943
4944        """
4945        cdef PetscBool callow = PETSC_FALSE
4946        CHKERR(MatISGetAllowRepeated(self.mat, &callow))
4947        return asBool(callow)
4948
4949    def fixISLocalEmpty(self, fix: bool = True) -> None:
4950        """Compress out zero local rows from the local matrices.
4951
4952        Collective.
4953
4954        Parameters
4955        ----------
4956        fix
4957            When `True`, new local matrices and local to global maps are generated
4958            during the final assembly process.
4959
4960        See Also
4961        --------
4962        petsc.MatISFixLocalEmpty
4963
4964        """
4965        cdef PetscBool cfix = asBool(fix)
4966        CHKERR(MatISFixLocalEmpty(self.mat, cfix))
4967
4968    def getISLocalMat(self) -> Mat:
4969        """Return the local matrix stored inside a `Type.IS` matrix.
4970
4971        Not collective.
4972
4973        See Also
4974        --------
4975        petsc.MatISGetLocalMat
4976
4977        """
4978        cdef Mat local = Mat()
4979        CHKERR(MatISGetLocalMat(self.mat, &local.mat))
4980        CHKERR(PetscINCREF(local.obj))
4981        return local
4982
4983    def restoreISLocalMat(self, Mat local not None) -> None:
4984        """Restore the local matrix obtained with `getISLocalMat`.
4985
4986        Not collective.
4987
4988        Parameters
4989        ----------
4990        local
4991            The local matrix.
4992
4993        See Also
4994        --------
4995        petsc.MatISRestoreLocalMat
4996
4997        """
4998        CHKERR(MatISRestoreLocalMat(self.mat, &local.mat))
4999
5000    def setISLocalMat(self, Mat local not None) -> None:
5001        """Set the local matrix stored inside a `Type.IS`.
5002
5003        Not collective.
5004
5005        Parameters
5006        ----------
5007        local
5008            The local matrix.
5009
5010        See Also
5011        --------
5012        petsc.MatISSetLocalMat
5013
5014        """
5015        CHKERR(MatISSetLocalMat(self.mat, local.mat))
5016
5017    def setISPreallocation(
5018        self,
5019        nnz: Sequence[int],
5020        onnz: Sequence[int]) -> Self:
5021        """Preallocate memory for a `Type.IS` parallel matrix.
5022
5023        Collective.
5024
5025        Parameters
5026        ----------
5027        nnz
5028            The sequence whose length corresponds to the number of local rows
5029            and values which represent the number of nonzeros in the various
5030            rows of the *diagonal* of the local submatrix.
5031        onnz:
5032            The sequence whose length corresponds to the number of local rows
5033            and values which represent the number of nonzeros in the various
5034            rows of the *off-diagonal* of the local submatrix.
5035
5036        See Also
5037        --------
5038        petsc.MatISSetPreallocation
5039
5040        """
5041        cdef PetscInt *cnnz = NULL
5042        cdef PetscInt *connz = NULL
5043        nnz = iarray_i(nnz, NULL, &cnnz)
5044        onnz = iarray_i(onnz, NULL, &connz)
5045        CHKERR(MatISSetPreallocation(self.mat, 0, cnnz, 0, connz))
5046        return self
5047
5048    # LRC
5049
5050    def getLRCMats(self) -> tuple[Mat, Mat, Vec, Mat]:
5051        """Return the constituents of a `Type.LRC` matrix.
5052
5053        Not collective.
5054
5055        Returns
5056        -------
5057        A : Mat
5058            The ``A`` matrix.
5059        U : Mat
5060            The first dense rectangular matrix.
5061        c : Vec
5062            The sequential vector containing the diagonal of ``C``.
5063        V : Mat
5064            The second dense rectangular matrix.
5065
5066        See Also
5067        --------
5068        petsc.MatLRCGetMats
5069
5070        """
5071        cdef Mat A = Mat()
5072        cdef Mat U = Mat()
5073        cdef Vec c = Vec()
5074        cdef Mat V = Mat()
5075        CHKERR(MatLRCGetMats(self.mat, &A.mat, &U.mat, &c.vec, &V.mat))
5076        CHKERR(PetscINCREF(A.obj))
5077        CHKERR(PetscINCREF(U.obj))
5078        CHKERR(PetscINCREF(c.obj))
5079        CHKERR(PetscINCREF(V.obj))
5080        return (A, U, c, V)
5081
5082    def setLRCMats(self, Mat A, Mat U, Vec c=None, Mat V=None) -> None:
5083        """Set the constituents of a `Type.LRC` matrix.
5084
5085        Logically collective.
5086
5087        Parameters
5088        ----------
5089        A : Mat
5090            The ``A`` matrix, or `None` to omit ``A``.
5091        U : Mat
5092            The first dense rectangular matrix.
5093        c : Vec
5094            The sequential vector containing the diagonal of ``C``,
5095            or `None` for all ones.
5096        V : Mat
5097            The second dense rectangular matrix, or `None` for a copy of ``U``.
5098
5099        See Also
5100        --------
5101        petsc.MatLRCSetMats
5102
5103        """
5104        cdef PetscMat Amat = A.mat if A is not None else <PetscMat>NULL
5105        cdef PetscVec cvec = c.vec if c is not None else <PetscVec>NULL
5106        cdef PetscMat Vmat = V.mat if V is not None else <PetscMat>NULL
5107        CHKERR(MatLRCSetMats(self.mat, Amat, U.mat, cvec, Vmat))
5108
5109    # H2Opus
5110
5111    def H2OpusOrthogonalize(self) -> Self:
5112        """Orthogonalize the basis tree of a hierarchical matrix.
5113
5114        Collective.
5115
5116        See Also
5117        --------
5118        petsc.MatH2OpusOrthogonalize
5119
5120        """
5121        CHKERR(MatH2OpusOrthogonalize(self.mat))
5122        return self
5123
5124    def H2OpusCompress(self, tol: float) -> Self:
5125        """Compress a hierarchical matrix.
5126
5127        Collective.
5128
5129        Parameters
5130        ----------
5131        tol
5132            The absolute truncation threshold.
5133
5134        See Also
5135        --------
5136        petsc.MatH2OpusCompress
5137
5138        """
5139        cdef PetscReal _tol = asReal(tol)
5140        CHKERR(MatH2OpusCompress(self.mat, _tol))
5141        return self
5142
5143    def H2OpusLowRankUpdate(self, Mat U, Mat V=None, s: float = 1.0) -> Self:
5144        """Perform a low-rank update of the form ``self`` += sUVᵀ.
5145
5146        Collective.
5147
5148        Parameters
5149        ----------
5150        U
5151            The dense low-rank update matrix.
5152        V
5153            The dense low-rank update matrix. If `None`, ``V = U``.
5154        s
5155            The scaling factor.
5156
5157        See Also
5158        --------
5159        petsc.MatH2OpusLowRankUpdate
5160
5161        """
5162        cdef PetscScalar _s = asScalar(s)
5163        cdef PetscMat vmat = NULL
5164        if V is not None:
5165            vmat = V.mat
5166        CHKERR(MatH2OpusLowRankUpdate(self.mat, U.mat, vmat, _s))
5167        return self
5168
5169    # LMVM
5170
5171    def getLMVMJ0(self) -> Mat:
5172        """Get the initial Jacobian of the LMVM matrix.
5173
5174        Not collective.
5175
5176        See Also
5177        --------
5178        setLMVMJ0, petsc.MatLMVMGetJ0
5179        """
5180        cdef Mat M = Mat()
5181        CHKERR(MatLMVMGetJ0(self.mat, &M.mat))
5182        CHKERR(PetscINCREF(M.obj))
5183        return M
5184
5185    def setLMVMJ0(self, Mat J0) -> None:
5186        """Set the initial Jacobian of the LMVM matrix.
5187
5188        Logically collective.
5189
5190        Parameters
5191        ----------
5192        J0:
5193            The initial Jacobian matrix.
5194
5195        See Also
5196        --------
5197        getLMVMJ0, petsc.MatLMVMSetJ0
5198        """
5199        cdef PetscMat ctype = J0.mat
5200        CHKERR(MatLMVMSetJ0(self.mat, ctype))
5201
5202    def getLMVMJ0KSP(self) -> Mat:
5203        """Get the KSP of the LMVM matrix.
5204
5205        Not collective.
5206
5207        See Also
5208        --------
5209        setLMVMJ0KSP, petsc.MatLMVMGetJ0KSP
5210        """
5211        cdef KSP ksp = KSP()
5212        CHKERR(MatLMVMGetJ0KSP(self.mat, &ksp.ksp))
5213        CHKERR(PetscINCREF(ksp.obj))
5214        return ksp
5215
5216    def setLMVMJ0KSP(self, KSP ksp) -> None:
5217        """Set the KSP of the LMVM matrix.
5218
5219        Logically collective.
5220
5221        Parameters
5222        ----------
5223        ksp:
5224            The KSP.
5225
5226        See Also
5227        --------
5228        getLMVMJ0KSP, petsc.MatLMVMSetJ0KSP
5229        """
5230        cdef PetscKSP ctype = ksp.ksp
5231        CHKERR(MatLMVMSetJ0KSP(self.mat, ctype))
5232
5233    def allocateLMVM(self, Vec x, Vec f) -> None:
5234        """Allocate all necessary common memory LMVM matrix.
5235
5236        Logically collective.
5237
5238        Parameters
5239        ----------
5240        x:
5241            Solution vector.
5242        f:
5243            Function vector.
5244
5245        See Also
5246        --------
5247        petsc.MatLMVMAllocate
5248        """
5249        cdef PetscVec xvec = x.vec
5250        cdef PetscVec fvec = f.vec
5251        CHKERR(MatLMVMAllocate(self.mat, xvec, fvec))
5252
5253    def updateLMVM(self, Vec x, Vec f) -> None:
5254        """Adds (X-Xprev) and (F-Fprev) updates to LMVM matrix.
5255
5256        Logically collective.
5257
5258        Parameters
5259        ----------
5260        x:
5261            Solution vector.
5262        f:
5263            Function vector.
5264
5265        See Also
5266        --------
5267        petsc.MatLMVMUpdate
5268        """
5269        cdef PetscVec xvec = x.vec
5270        cdef PetscVec fvec = f.vec
5271        CHKERR(MatLMVMUpdate(self.mat, xvec, fvec))
5272
5273    def resetLMVM(self, destructive: bool = False) -> None:
5274        """Flushes all of the accumulated updates out of the LMVM matrix.
5275
5276        Logically collective.
5277
5278        Parameters
5279        ----------
5280        destructive:
5281            Flag for enabling destruction of data structures.
5282
5283        See Also
5284        --------
5285        petsc.MatLMVMReset
5286        """
5287        cdef PetscBool cdestructive = asBool(destructive)
5288        CHKERR(MatLMVMReset(self.mat, cdestructive))
5289
5290    # MUMPS
5291
5292    def setMumpsIcntl(self, icntl: int, ival: int) -> None:
5293        """Set a MUMPS parameter, ``ICNTL[icntl] = ival``.
5294
5295        Logically collective.
5296
5297        Parameters
5298        ----------
5299        icntl
5300            The index of the MUMPS parameter array.
5301        ival
5302            The value to set.
5303
5304        See Also
5305        --------
5306        petsc_options, petsc.MatMumpsSetIcntl
5307
5308        """
5309        cdef PetscInt _icntl = asInt(icntl)
5310        cdef PetscInt _ival = asInt(ival)
5311        CHKERR(MatMumpsSetIcntl(self.mat, _icntl, _ival))
5312
5313    def getMumpsIcntl(self, icntl: int) -> int:
5314        """Return the MUMPS parameter, ``ICNTL[icntl]``.
5315
5316        Logically collective.
5317
5318        See Also
5319        --------
5320        petsc_options, petsc.MatMumpsGetIcntl
5321
5322        """
5323        cdef PetscInt _icntl = asInt(icntl)
5324        cdef PetscInt ival = 0
5325        CHKERR(MatMumpsGetIcntl(self.mat, _icntl, &ival))
5326        return toInt(ival)
5327
5328    def setMumpsCntl(self, icntl: int, val: float) -> None:
5329        """Set a MUMPS parameter, ``CNTL[icntl] = val``.
5330
5331        Logically collective.
5332
5333        Parameters
5334        ----------
5335        icntl
5336            The index of the MUMPS parameter array.
5337        val
5338            The value to set.
5339
5340        See Also
5341        --------
5342        petsc_options, petsc.MatMumpsSetCntl
5343
5344        """
5345        cdef PetscInt _icntl = asInt(icntl)
5346        cdef PetscReal _val = asReal(val)
5347        CHKERR(MatMumpsSetCntl(self.mat, _icntl, _val))
5348
5349    def getMumpsCntl(self, icntl: int) -> float:
5350        """Return the MUMPS parameter, ``CNTL[icntl]``.
5351
5352        Logically collective.
5353
5354        See Also
5355        --------
5356        petsc_options, petsc.MatMumpsGetCntl
5357
5358        """
5359        cdef PetscInt _icntl = asInt(icntl)
5360        cdef PetscReal val = 0
5361        CHKERR(MatMumpsGetCntl(self.mat, _icntl, &val))
5362        return toReal(val)
5363
5364    def getMumpsInfo(self, icntl: int) -> int:
5365        """Return the MUMPS parameter, ``INFO[icntl]``.
5366
5367        Logically collective.
5368
5369        Parameters
5370        ----------
5371        icntl
5372            The index of the MUMPS INFO array.
5373
5374        See Also
5375        --------
5376        petsc.MatMumpsGetInfo
5377
5378        """
5379        cdef PetscInt _icntl = asInt(icntl)
5380        cdef PetscInt ival = 0
5381        CHKERR(MatMumpsGetInfo(self.mat, _icntl, &ival))
5382        return toInt(ival)
5383
5384    def getMumpsInfog(self, icntl: int) -> int:
5385        """Return the MUMPS parameter, ``INFOG[icntl]``.
5386
5387        Logically collective.
5388
5389        Parameters
5390        ----------
5391        icntl
5392            The index of the MUMPS INFOG array.
5393
5394        See Also
5395        --------
5396        petsc.MatMumpsGetInfog
5397
5398        """
5399        cdef PetscInt _icntl = asInt(icntl)
5400        cdef PetscInt ival = 0
5401        CHKERR(MatMumpsGetInfog(self.mat, _icntl, &ival))
5402        return toInt(ival)
5403
5404    def getMumpsRinfo(self, icntl: int) -> float:
5405        """Return the MUMPS parameter, ``RINFO[icntl]``.
5406
5407        Logically collective.
5408
5409        Parameters
5410        ----------
5411        icntl
5412            The index of the MUMPS RINFO array.
5413
5414        See Also
5415        --------
5416        petsc.MatMumpsGetRinfo
5417
5418        """
5419        cdef PetscInt _icntl = asInt(icntl)
5420        cdef PetscReal val = 0
5421        CHKERR(MatMumpsGetRinfo(self.mat, _icntl, &val))
5422        return toReal(val)
5423
5424    def getMumpsRinfog(self, icntl: int) -> float:
5425        """Return the MUMPS parameter, ``RINFOG[icntl]``.
5426
5427        Logically collective.
5428
5429        Parameters
5430        ----------
5431        icntl
5432            The index of the MUMPS RINFOG array.
5433
5434        See Also
5435        --------
5436        petsc.MatMumpsGetRinfog
5437
5438        """
5439        cdef PetscInt _icntl = asInt(icntl)
5440        cdef PetscReal val = 0
5441        CHKERR(MatMumpsGetRinfog(self.mat, _icntl, &val))
5442        return toReal(val)
5443
5444    # solve
5445
5446    def solveForward(self, Vec b, Vec x) -> None:
5447        """Solve Lx = b, given a factored matrix A = LU.
5448
5449        Neighborwise collective.
5450
5451        Parameters
5452        ----------
5453        b
5454            The right-hand side vector.
5455        x
5456            The output solution vector.
5457
5458        See Also
5459        --------
5460        petsc.MatForwardSolve
5461
5462        """
5463        CHKERR(MatForwardSolve(self.mat, b.vec, x.vec))
5464
5465    def solveBackward(self, Vec b, Vec x) -> None:
5466        """Solve Ux=b, given a factored matrix A=LU.
5467
5468        Neighborwise collective.
5469
5470        Parameters
5471        ----------
5472        b
5473            The right-hand side vector.
5474        x
5475            The output solution vector.
5476
5477        See Also
5478        --------
5479        petsc.MatBackwardSolve
5480
5481        """
5482        CHKERR(MatBackwardSolve(self.mat, b.vec, x.vec))
5483
5484    def solve(self, Vec b, Vec x) -> None:
5485        """Solve Ax=b, given a factored matrix.
5486
5487        Neighborwise collective.
5488
5489        The vectors ``b`` and ``x`` cannot be the same.
5490        Most users should employ the `KSP` interface for linear solvers instead
5491        of working directly with matrix algebra routines.
5492
5493        Parameters
5494        ----------
5495        b
5496            The right-hand side vector.
5497        x
5498            The output solution vector, must be different than ``b``.
5499
5500        See Also
5501        --------
5502        KSP.create, solveTranspose, petsc.MatSolve
5503
5504        """
5505        CHKERR(MatSolve(self.mat, b.vec, x.vec))
5506
5507    def solveTranspose(self, Vec b, Vec x) -> None:
5508        """Solve Aᵀx=b, given a factored matrix.
5509
5510        Neighborwise collective.
5511
5512        The vectors ``b`` and ``x`` cannot be the same.
5513
5514        Parameters
5515        ----------
5516        b
5517            The right-hand side vector.
5518        x
5519            The output solution vector, must be different than ``b``.
5520
5521        See Also
5522        --------
5523        KSP.create, petsc.MatSolve, petsc.MatSolveTranspose
5524
5525        """
5526        CHKERR(MatSolveTranspose(self.mat, b.vec, x.vec))
5527
5528    def solveAdd(self, Vec b, Vec y, Vec x) -> None:
5529        """Solve x=y+A⁻¹b, given a factored matrix.
5530
5531        Neighborwise collective.
5532
5533        The vectors ``b`` and ``x`` cannot be the same.
5534
5535        Parameters
5536        ----------
5537        b
5538            The right-hand side vector.
5539        y
5540            The vector to be added
5541        x
5542            The output solution vector, must be different than ``b``.
5543
5544        See Also
5545        --------
5546        KSP.create, petsc.MatSolve, petsc.MatSolveAdd
5547
5548        """
5549        CHKERR(MatSolveAdd(self.mat, b.vec, y.vec, x.vec))
5550
5551    def solveTransposeAdd(self, Vec b, Vec y, Vec x) -> None:
5552        """Solve x=y+A⁻ᵀb, given a factored matrix.
5553
5554        Neighborwise collective.
5555
5556        The vectors ``b`` and ``x`` cannot be the same.
5557
5558        Parameters
5559        ----------
5560        b
5561            The right-hand side vector.
5562        y
5563            The vector to be added
5564        x
5565            The output solution vector, must be different than ``b``.
5566
5567        See Also
5568        --------
5569        KSP.create, petsc.MatSolve, petsc.MatSolveTransposeAdd
5570
5571        """
5572        CHKERR(MatSolveTransposeAdd(self.mat, b.vec, y.vec, x.vec))
5573
5574    def matSolve(self, Mat B, Mat X) -> None:
5575        """Solve AX=B, given a factored matrix A.
5576
5577        Neighborwise collective.
5578
5579        Parameters
5580        ----------
5581        B
5582            The right-hand side matrix of type `Type.DENSE`. Can be of type
5583            `Type.AIJ` if using MUMPS.
5584        X
5585            The output solution matrix, must be different than ``B``.
5586
5587        See Also
5588        --------
5589        KSP.create, petsc.MatMatSolve
5590
5591        """
5592        CHKERR(MatMatSolve(self.mat, B.mat, X.mat))
5593
5594    # dense matrices
5595
5596    def setDenseLDA(self, lda: int) -> None:
5597        """Set the leading dimension of the array used by the dense matrix.
5598
5599        Not collective.
5600
5601        Parameters
5602        ----------
5603        lda
5604            The leading dimension.
5605
5606        See Also
5607        --------
5608        petsc.MatDenseSetLDA
5609
5610        """
5611        cdef PetscInt _ilda = asInt(lda)
5612        CHKERR(MatDenseSetLDA(self.mat, _ilda))
5613
5614    def getDenseLDA(self) -> int:
5615        """Return the leading dimension of the array used by the dense matrix.
5616
5617        Not collective.
5618
5619        See Also
5620        --------
5621        petsc.MatDenseGetLDA
5622
5623        """
5624        cdef PetscInt lda=0
5625        CHKERR(MatDenseGetLDA(self.mat, &lda))
5626        return toInt(lda)
5627
5628    def getDenseArray(self, readonly: bool = False) -> ArrayScalar:
5629        """Return the array where the data is stored.
5630
5631        Not collective.
5632
5633        Parameters
5634        ----------
5635        readonly
5636            Enable to obtain a read only array.
5637
5638        See Also
5639        --------
5640        petsc.MatDenseGetArrayRead, petsc.MatDenseGetArray
5641
5642        """
5643        cdef PetscInt m=0, N=0, lda=0
5644        cdef PetscScalar *data = NULL
5645        CHKERR(MatGetLocalSize(self.mat, &m, NULL))
5646        CHKERR(MatGetSize(self.mat, NULL, &N))
5647        CHKERR(MatDenseGetLDA(self.mat, &lda))
5648        if readonly:
5649            CHKERR(MatDenseGetArrayRead(self.mat, <const PetscScalar**>&data))
5650        else:
5651            CHKERR(MatDenseGetArray(self.mat, &data))
5652        cdef int typenum = NPY_PETSC_SCALAR
5653        cdef int itemsize = <int>sizeof(PetscScalar)
5654        cdef int flags = NPY_ARRAY_FARRAY_RO if readonly else NPY_ARRAY_FARRAY
5655        cdef npy_intp dims[2], strides[2]
5656        dims[0] = <npy_intp>m; strides[0] = <npy_intp>sizeof(PetscScalar)
5657        dims[1] = <npy_intp>N; strides[1] = <npy_intp>(lda*sizeof(PetscScalar))
5658        cdef ndarray array = PyArray_New(<PyTypeObject*>ndarray, 2,
5659                                         dims, typenum, strides,
5660                                         data, itemsize, flags, NULL)
5661        Py_INCREF(<PyObject*>self)
5662        PyArray_SetBaseObject(array, self)
5663        if readonly:
5664            CHKERR(MatDenseRestoreArrayRead(self.mat, <const PetscScalar**>&data))
5665        else:
5666            CHKERR(MatDenseRestoreArray(self.mat, &data))
5667        return array
5668
5669    def getDenseLocalMatrix(self) -> Mat:
5670        """Return the local part of the dense matrix.
5671
5672        Not collective.
5673
5674        See Also
5675        --------
5676        petsc.MatDenseGetLocalMatrix
5677
5678        """
5679        cdef Mat mat = type(self)()
5680        CHKERR(MatDenseGetLocalMatrix(self.mat, &mat.mat))
5681        CHKERR(PetscINCREF(mat.obj))
5682        return mat
5683
5684    def getDenseSubMatrix(self,
5685                          rbegin: int = DECIDE,
5686                          rend: int = DECIDE,
5687                          cbegin: int = DECIDE,
5688                          cend: int = DECIDE) -> Mat:
5689        """Get access to a submatrix of a `Type.DENSE` matrix.
5690
5691        Collective.
5692
5693        Parameters
5694        ----------
5695        rbegin
5696            the first global row index.
5697        rend
5698            the global row index past the last one.
5699        cbegin
5700            the first global column index.
5701        cend
5702            the global column index past the last one.
5703
5704        See Also
5705        --------
5706        restoreDenseSubMatrix, petsc.MatDenseGetSubMatrix
5707
5708        """
5709        cdef Mat mat = type(self)()
5710        cdef PetscInt crbegin = asInt(rbegin)
5711        cdef PetscInt crend = asInt(rend)
5712        cdef PetscInt ccbegin = asInt(cbegin)
5713        cdef PetscInt ccend = asInt(cend)
5714        CHKERR(MatDenseGetSubMatrix(self.mat, crbegin, crend, ccbegin, ccend, &mat.mat))
5715        CHKERR(PetscINCREF(mat.obj))
5716        return mat
5717
5718    def restoreDenseSubMatrix(self, Mat mat) -> None:
5719        """Restore access to a submatrix of a `Type.DENSE` matrix.
5720
5721        Collective.
5722
5723        Parameters
5724        ----------
5725        mat
5726            the matrix obtained from `getDenseSubMatrix`.
5727
5728        See Also
5729        --------
5730        getDenseSubMatrix, petsc.MatDenseRestoreSubMatrix
5731
5732        """
5733        cdef PetscMat v = mat.mat
5734        CHKERR(MatDenseRestoreSubMatrix(self.mat, &v))
5735        CHKERR(PetscCLEAR(mat.obj))
5736
5737    def getDenseColumnVec(self, i: int, mode: AccessModeSpec = 'rw') -> Vec:
5738        """Return the iᵗʰ column vector of the dense matrix.
5739
5740        Collective.
5741
5742        Parameters
5743        ----------
5744        i
5745            The column index to access.
5746        mode
5747            The access type of the vector to be returned.
5748
5749        See Also
5750        --------
5751        restoreDenseColumnVec, petsc.MatDenseGetColumnVec
5752        petsc.MatDenseGetColumnVecRead, petsc.MatDenseGetColumnVecWrite
5753
5754        """
5755        if mode is None: mode = 'rw'
5756        if mode not in ['rw', 'r', 'w']:
5757            raise ValueError("Invalid mode: expected 'rw', 'r', or 'w'")
5758        cdef Vec v = Vec()
5759        cdef PetscInt _i = asInt(i)
5760        if mode == 'rw':
5761            CHKERR(MatDenseGetColumnVec(self.mat, _i, &v.vec))
5762        elif mode == 'r':
5763            CHKERR(MatDenseGetColumnVecRead(self.mat, _i, &v.vec))
5764        else:
5765            CHKERR(MatDenseGetColumnVecWrite(self.mat, _i, &v.vec))
5766        CHKERR(PetscINCREF(v.obj))
5767        return v
5768
5769    def restoreDenseColumnVec(self, i: int, mode: AccessModeSpec = 'rw', Vec V=None) -> None:
5770        """Restore the iᵗʰ column vector of the dense matrix.
5771
5772        Collective.
5773
5774        Parameters
5775        ----------
5776        i
5777            The column index to be restored.
5778        mode
5779            The access type of the vector to be restored.
5780        V
5781            The vector obtained from calling `getDenseColumnVec`.
5782
5783        See Also
5784        --------
5785        getDenseColumnVec, petsc.MatDenseRestoreColumnVec
5786        petsc.MatDenseRestoreColumnVecRead, petsc.MatDenseRestoreColumnVecWrite
5787
5788        """
5789        cdef PetscVec v = NULL
5790        if V is not None:
5791            v = V.vec
5792        cdef PetscInt _i = asInt(i)
5793        if mode == 'rw':
5794            CHKERR(MatDenseRestoreColumnVec(self.mat, _i, &v))
5795        elif mode == 'r':
5796            CHKERR(MatDenseRestoreColumnVecRead(self.mat, _i, &v))
5797        else:
5798            CHKERR(MatDenseRestoreColumnVecWrite(self.mat, _i, &v))
5799        if V is not None:
5800            CHKERR(PetscCLEAR(V.obj))
5801
5802    # Nest
5803
5804    def getNestSize(self) -> tuple[int, int]:
5805        """Return the number of rows and columns of the matrix.
5806
5807        Not collective.
5808
5809        See Also
5810        --------
5811        petsc.MatNestGetSize
5812
5813        """
5814        cdef PetscInt nrows = 0, ncols = 0
5815        CHKERR(MatNestGetSize(self.mat, &nrows, &ncols))
5816        return toInt(nrows), toInt(ncols)
5817
5818    def getNestISs(self) -> tuple[list[IS], list[IS]]:
5819        """Return the index sets representing the row and column spaces.
5820
5821        Not collective.
5822
5823        See Also
5824        --------
5825        petsc.MatNestGetISs
5826
5827        """
5828        cdef PetscInt nrows = 0, ncols = 0
5829        cdef PetscIS *cisrows = NULL
5830        cdef PetscIS *ciscols = NULL
5831        CHKERR(MatNestGetSize(self.mat, &nrows, &ncols))
5832        cdef object unusedr = oarray_p(empty_p(nrows), NULL, <void**>&cisrows)
5833        cdef object unusedc = oarray_p(empty_p(ncols), NULL, <void**>&ciscols)
5834        CHKERR(MatNestGetISs(self.mat, cisrows, ciscols))
5835        isetsrows = [ref_IS(cisrows[i]) for i from 0 <= i < nrows]
5836        isetscols = [ref_IS(ciscols[i]) for i from 0 <= i < ncols]
5837        return isetsrows, isetscols
5838
5839    def getNestLocalISs(self) -> tuple[list[IS], list[IS]]:
5840        """Return the local index sets representing the row and column spaces.
5841
5842        Not collective.
5843
5844        See Also
5845        --------
5846        petsc.MatNestGetLocalISs
5847
5848        """
5849        cdef PetscInt nrows = 0, ncols = 0
5850        cdef PetscIS *cisrows = NULL
5851        cdef PetscIS *ciscols = NULL
5852        CHKERR(MatNestGetSize(self.mat, &nrows, &ncols))
5853        cdef object unusedr = oarray_p(empty_p(nrows), NULL, <void**>&cisrows)
5854        cdef object unusedc = oarray_p(empty_p(ncols), NULL, <void**>&ciscols)
5855        CHKERR(MatNestGetLocalISs(self.mat, cisrows, ciscols))
5856        isetsrows = [ref_IS(cisrows[i]) for i from 0 <= i < nrows]
5857        isetscols = [ref_IS(ciscols[i]) for i from 0 <= i < ncols]
5858        return isetsrows, isetscols
5859
5860    def getNestSubMatrix(self, i: int, j: int) -> Mat:
5861        """Return a single submatrix.
5862
5863        Not collective.
5864
5865        Parameters
5866        ----------
5867        i
5868            The first index of the matrix within the nesting.
5869        j
5870            The second index of the matrix within the nesting.
5871
5872        See Also
5873        --------
5874        petsc.MatNestGetSubMat
5875
5876        """
5877        cdef Mat submat = Mat()
5878        cdef PetscInt idxm = asInt(i)
5879        cdef PetscInt jdxm = asInt(j)
5880        CHKERR(MatNestGetSubMat(self.mat, idxm, jdxm, &submat.mat))
5881        CHKERR(PetscINCREF(submat.obj))
5882        return submat
5883
5884    # DM
5885
5886    def getDM(self) -> DM:
5887        """Return the DM defining the data layout of the matrix.
5888
5889        Not collective.
5890
5891        See Also
5892        --------
5893        petsc.MatGetDM
5894
5895        """
5896        cdef PetscDM newdm = NULL
5897        CHKERR(MatGetDM(self.mat, &newdm))
5898        cdef DM dm = subtype_DM(newdm)()
5899        dm.dm = newdm
5900        CHKERR(PetscINCREF(dm.obj))
5901        return dm
5902
5903    def setDM(self, DM dm) -> None:
5904        """Set the DM defining the data layout of the matrix.
5905
5906        Not collective.
5907
5908        Parameters
5909        ----------
5910        dm
5911            The `DM`.
5912
5913        See Also
5914        --------
5915        petsc.MatSetDM
5916
5917        """
5918        CHKERR(MatSetDM(self.mat, dm.dm))
5919
5920    # backward compatibility
5921
5922    PtAP = ptap
5923
5924    #
5925
5926    property sizes:
5927        """Matrix local and global sizes."""
5928        def __get__(self) -> tuple[tuple[int, int], tuple[int, int]]:
5929            return self.getSizes()
5930
5931        def __set__(self, value):
5932            self.setSizes(value)
5933
5934    property size:
5935        """Matrix global size."""
5936        def __get__(self) -> tuple[int, int]:
5937            return self.getSize()
5938
5939    property local_size:
5940        """Matrix local size."""
5941        def __get__(self) -> int:
5942            return self.getLocalSize()
5943
5944    property block_size:
5945        """Matrix block size."""
5946        def __get__(self) -> int:
5947            return self.getBlockSize()
5948
5949    property block_sizes:
5950        """Matrix row and column block sizes."""
5951        def __get__(self) -> tuple[int, int]:
5952            return self.getBlockSizes()
5953
5954    property owner_range:
5955        """Matrix local row range."""
5956        def __get__(self) -> tuple[int, int]:
5957            return self.getOwnershipRange()
5958
5959    property owner_ranges:
5960        """Matrix row ranges."""
5961        def __get__(self) -> ArrayInt:
5962            return self.getOwnershipRanges()
5963
5964    #
5965
5966    property assembled:
5967        """The boolean flag indicating if the matrix is assembled."""
5968        def __get__(self) -> bool:
5969            return self.isAssembled()
5970    property symmetric:
5971        """The boolean flag indicating if the matrix is symmetric."""
5972        def __get__(self) -> bool:
5973            return self.isSymmetric()
5974    property hermitian:
5975        """The boolean flag indicating if the matrix is Hermitian."""
5976        def __get__(self) -> bool:
5977            return self.isHermitian()
5978    property structsymm:
5979        """The boolean flag indicating if the matrix is structurally symmetric."""
5980        def __get__(self) -> bool:
5981            return self.isStructurallySymmetric()
5982
5983    # TODO Stream
5984    def __dlpack__(self, stream=-1):
5985        return self.toDLPack('rw')
5986
5987    def __dlpack_device__(self):
5988        (dltype, devId, _, _, _) = mat_get_dlpack_ctx(self)
5989        return (dltype, devId)
5990
5991    def toDLPack(self, mode: AccessModeSpec = 'rw') -> Any:
5992        """Return a DLPack `PyCapsule` wrapping the vector data."""
5993        if mode is None: mode = 'rw'
5994        if mode is None: mode = 'rw'
5995        if mode not in ['rw', 'r', 'w']:
5996            raise ValueError("Invalid mode: expected 'rw', 'r', or 'w'")
5997
5998        cdef int64_t ndim = 0
5999        (device_type, device_id, ndim, shape, strides) = mat_get_dlpack_ctx(self)
6000        hostmem = (device_type == kDLCPU)
6001
6002        cdef DLManagedTensor* dlm_tensor = <DLManagedTensor*>malloc(sizeof(DLManagedTensor))
6003        cdef DLTensor* dl_tensor = &dlm_tensor.dl_tensor
6004        cdef PetscScalar *a = NULL
6005        cdef int64_t* shape_strides = NULL
6006        dl_tensor.byte_offset = 0
6007
6008        # DLPack does not currently play well with our get/restore model
6009        # Call restore right-away and hope that the consumer will do the right thing
6010        # and not modify memory requested with read access
6011        # By restoring now, we guarantee the sanity of the ObjectState
6012        if mode == 'w':
6013            if hostmem:
6014                CHKERR(MatDenseGetArrayWrite(self.mat, <PetscScalar**>&a))
6015                CHKERR(MatDenseRestoreArrayWrite(self.mat, NULL))
6016            else:
6017                CHKERR(MatDenseGetArrayWriteAndMemType(self.mat, <PetscScalar**>&a, NULL))
6018                CHKERR(MatDenseRestoreArrayWriteAndMemType(self.mat, NULL))
6019        elif mode == 'r':
6020            if hostmem:
6021                CHKERR(MatDenseGetArrayRead(self.mat, <const PetscScalar**>&a))
6022                CHKERR(MatDenseRestoreArrayRead(self.mat, NULL))
6023            else:
6024                CHKERR(MatDenseGetArrayReadAndMemType(self.mat, <const PetscScalar**>&a, NULL))
6025                CHKERR(MatDenseRestoreArrayReadAndMemType(self.mat, NULL))
6026        else:
6027            if hostmem:
6028                CHKERR(MatDenseGetArray(self.mat, <PetscScalar**>&a))
6029                CHKERR(MatDenseRestoreArray(self.mat, NULL))
6030            else:
6031                CHKERR(MatDenseGetArrayAndMemType(self.mat, <PetscScalar**>&a, NULL))
6032                CHKERR(MatDenseRestoreArrayAndMemType(self.mat, NULL))
6033        dl_tensor.data = <void *>a
6034
6035        cdef DLContext* ctx = &dl_tensor.ctx
6036        ctx.device_type = device_type
6037        ctx.device_id = device_id
6038        shape_strides = <int64_t*>malloc(sizeof(int64_t)*2*ndim)
6039        for i in range(ndim):
6040            shape_strides[i] = shape[i]
6041        for i in range(ndim):
6042            shape_strides[i+ndim] = strides[i]
6043        dl_tensor.ndim = <int>ndim
6044        dl_tensor.shape = shape_strides
6045        dl_tensor.strides = shape_strides + ndim
6046
6047        cdef DLDataType* dtype = &dl_tensor.dtype
6048        dtype.code = <uint8_t>DLDataTypeCode.kDLFloat
6049        if sizeof(PetscScalar) == 8:
6050            dtype.bits = <uint8_t>64
6051        elif sizeof(PetscScalar) == 4:
6052            dtype.bits = <uint8_t>32
6053        else:
6054            raise ValueError('Unsupported PetscScalar type')
6055        dtype.lanes = <uint16_t>1
6056        dlm_tensor.manager_ctx = <void *>self.mat
6057        CHKERR(PetscObjectReference(<PetscObject>self.mat))
6058        dlm_tensor.manager_deleter = manager_deleter
6059        dlm_tensor.del_obj = <dlpack_manager_del_obj>PetscDEALLOC
6060        return PyCapsule_New(dlm_tensor, 'dltensor', pycapsule_deleter)
6061
6062# --------------------------------------------------------------------
6063
6064cdef class NullSpace(Object):
6065    """Nullspace object.
6066
6067    See Also
6068    --------
6069    petsc.MatNullSpace
6070
6071    """
6072    #
6073
6074    def __cinit__(self):
6075        self.obj  = <PetscObject*> &self.nsp
6076        self.nsp = NULL
6077
6078    def __call__(self, vec):
6079        self.remove(vec)
6080
6081    #
6082
6083    def view(self, Viewer viewer=None) -> None:
6084        """View the null space.
6085
6086        Collective.
6087
6088        Parameters
6089        ----------
6090        viewer
6091            A `Viewer` instance or `None` for the default viewer.
6092
6093        See Also
6094        --------
6095        Viewer, petsc.MatNullSpaceView
6096
6097        """
6098        cdef PetscViewer vwr = NULL
6099        if viewer is not None: vwr = viewer.vwr
6100        CHKERR(MatNullSpaceView(self.nsp, vwr))
6101
6102    def destroy(self) -> Self:
6103        """Destroy the null space.
6104
6105        Collective.
6106
6107        See Also
6108        --------
6109        create, petsc.MatNullSpaceDestroy
6110
6111        """
6112        CHKERR(MatNullSpaceDestroy(&self.nsp))
6113        return self
6114
6115    def create(
6116        self,
6117        constant: bool = False,
6118        vectors: Sequence[Vec] = (),
6119        comm=None) -> Self:
6120        """Create the null space.
6121
6122        Collective.
6123
6124        Parameters
6125        ----------
6126        constant
6127            A flag to indicate the null space contains the constant vector.
6128        vectors
6129            The sequence of vectors that span the null space.
6130        comm
6131            MPI communicator, defaults to `Sys.getDefaultComm`.
6132
6133        See Also
6134        --------
6135        destroy, petsc.MatNullSpaceCreate
6136
6137        """
6138        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
6139        cdef PetscBool has_const = PETSC_FALSE
6140        if constant: has_const = PETSC_TRUE
6141        cdef PetscInt i = 0, nv = <PetscInt>len(vectors)
6142        cdef PetscVec *v = NULL
6143        cdef object unused2 = oarray_p(empty_p(nv), NULL, <void**>&v)
6144        for i from 0 <= i < nv:
6145            v[i] = (<Vec?>(vectors[<Py_ssize_t>i])).vec
6146        cdef PetscNullSpace newnsp = NULL
6147        CHKERR(MatNullSpaceCreate(ccomm, has_const, nv, v, &newnsp))
6148        CHKERR(PetscCLEAR(self.obj)); self.nsp = newnsp
6149        return self
6150
6151    def createRigidBody(self, Vec coords) -> Self:
6152        """Create rigid body modes from coordinates.
6153
6154        Collective.
6155
6156        Parameters
6157        ----------
6158        coords
6159            The block coordinates of each node.
6160            Requires the block size to have been set.
6161
6162        See Also
6163        --------
6164        petsc.MatNullSpaceCreateRigidBody
6165
6166        """
6167        cdef PetscNullSpace newnsp = NULL
6168        CHKERR(MatNullSpaceCreateRigidBody(coords.vec, &newnsp))
6169        CHKERR(PetscCLEAR(self.obj)); self.nsp = newnsp
6170        return self
6171
6172    def setFunction(
6173        self,
6174        function: MatNullFunction,
6175        args: tuple[Any, ...] | None = None,
6176        kargs: dict[str, Any] | None = None) -> None:
6177        """Set the callback to remove the nullspace.
6178
6179        Logically collective.
6180
6181        Parameters
6182        ----------
6183        function
6184            The callback.
6185        args
6186            Positional arguments for the callback.
6187        kargs
6188            Keyword arguments for the callback.
6189
6190        See Also
6191        --------
6192        getFunction, petsc.MatNullSpaceSetFunction
6193
6194        """
6195        if function is not None:
6196            CHKERR(MatNullSpaceSetFunction(
6197                    self.nsp, NullSpace_Function, NULL))
6198            if args is None: args = ()
6199            if kargs is None: kargs = {}
6200            self.set_attr('__function__', (function, args, kargs))
6201        else:
6202            CHKERR(MatNullSpaceSetFunction(self.nsp, NULL, NULL))
6203            self.set_attr('__function__', None)
6204    #
6205
6206    def hasConstant(self) -> bool:
6207        """Return whether the null space contains the constant.
6208
6209        Not collective.
6210
6211        See Also
6212        --------
6213        petsc.MatNullSpaceGetVecs
6214
6215        """
6216        cdef PetscBool flag = PETSC_FALSE
6217        CHKERR(MatNullSpaceGetVecs(self.nsp, &flag, NULL, NULL))
6218        return toBool(flag)
6219
6220    def getVecs(self) -> list[Vec]:
6221        """Return the vectors defining the null space.
6222
6223        Not collective.
6224
6225        See Also
6226        --------
6227        petsc.MatNullSpaceGetVecs
6228
6229        """
6230        cdef PetscInt i = 0, nv = 0
6231        cdef const PetscVec *v = NULL
6232        CHKERR(MatNullSpaceGetVecs(self.nsp, NULL, &nv, &v))
6233        cdef Vec vec = None
6234        cdef list vectors = []
6235        for i from 0 <= i < nv:
6236            vec = Vec()
6237            vec.vec = v[i]
6238            CHKERR(PetscINCREF(vec.obj))
6239            vectors.append(vec)
6240        return vectors
6241
6242    def getFunction(self) -> MatNullFunction:
6243        """Return the callback to remove the nullspace.
6244
6245        Not collective.
6246
6247        See Also
6248        --------
6249        setFunction
6250
6251        """
6252        return self.get_attr('__function__')
6253
6254    #
6255
6256    def remove(self, Vec vec) -> None:
6257        """Remove all components of a null space from a vector.
6258
6259        Collective.
6260
6261        Parameters
6262        ----------
6263        vec
6264            The vector from which the null space is removed.
6265
6266        See Also
6267        --------
6268        petsc.MatNullSpaceRemove
6269
6270        """
6271        CHKERR(MatNullSpaceRemove(self.nsp, vec.vec))
6272
6273    def test(self, Mat mat) -> bool:
6274        """Return if the claimed null space is valid for a matrix.
6275
6276        Collective.
6277
6278        Parameters
6279        ----------
6280        mat
6281            The matrix to check.
6282
6283        See Also
6284        --------
6285        petsc.MatNullSpaceTest
6286
6287        """
6288        cdef PetscBool flag = PETSC_FALSE
6289        CHKERR(MatNullSpaceTest(self.nsp, mat.mat, &flag))
6290        return toBool(flag)
6291
6292# --------------------------------------------------------------------
6293
6294del MatType
6295del MatOption
6296del MatAssemblyType
6297del MatInfoType
6298del MatStructure
6299del MatDuplicateOption
6300del MatOrderingType
6301del MatSolverType
6302del MatFactorShiftType
6303del MatSORType
6304
6305# --------------------------------------------------------------------
6306