xref: /petsc/src/mat/interface/matrix.c (revision 38b83642f90ca7c29d17300cee5f7fcf84bc0cc1)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameter:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameter:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameter:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](chapter_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameter:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](chapter_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameter:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameter:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
665 
666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameter:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameter:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 /*@
903    MatSetUp - Sets up the internal matrix data structures for later use.
904 
905    Collective
906 
907    Input Parameter:
908 .  A - the matrix
909 
910    Level: intermediate
911 
912    Notes:
913    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
914    setting values in the matrix.
915 
916    If a suitable preallocation routine is used, this function does not need to be called.
917 
918    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
919 
920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
921 @*/
922 PetscErrorCode MatSetUp(Mat A)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
926   if (!((PetscObject)A)->type_name) {
927     PetscMPIInt size;
928 
929     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
930     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
931   }
932   if (!A->preallocated) PetscTryTypeMethod(A, setup);
933   PetscCall(PetscLayoutSetUp(A->rmap));
934   PetscCall(PetscLayoutSetUp(A->cmap));
935   A->preallocated = PETSC_TRUE;
936   PetscFunctionReturn(PETSC_SUCCESS);
937 }
938 
939 #if defined(PETSC_HAVE_SAWS)
940   #include <petscviewersaws.h>
941 #endif
942 
943 /*@C
944    MatViewFromOptions - View properties of the matrix based on options set in the options database
945 
946    Collective
947 
948    Input Parameters:
949 +  A - the matrix
950 .  obj - optional additional object that provides the options prefix to use
951 -  name - command line option
952 
953   Options Database Key:
954 .  -mat_view [viewertype]:... - the viewer and its options
955 
956    Level: intermediate
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
971 @*/
972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
973 {
974   PetscFunctionBegin;
975   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
976   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
977   PetscFunctionReturn(PETSC_SUCCESS);
978 }
979 
980 /*@C
981    MatView - display information about a matrix in a variety ways
982 
983    Collective
984 
985    Input Parameters:
986 +  mat - the matrix
987 -  viewer - visualization context
988 
989    Options Database Keys:
990 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
991 .  -mat_view ::ascii_info_detail - Prints more detailed info
992 .  -mat_view - Prints matrix in ASCII format
993 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
994 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
995 .  -display <name> - Sets display name (default is host)
996 .  -draw_pause <sec> - Sets number of seconds to pause after display
997 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
998 .  -viewer_socket_machine <machine> -
999 .  -viewer_socket_port <port> -
1000 .  -mat_view binary - save matrix to file in binary format
1001 -  -viewer_binary_filename <name> -
1002 
1003    Level: beginner
1004 
1005   Notes:
1006   The available visualization contexts include
1007 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1008 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1009 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1010 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1011 
1012    The user can open alternative visualization contexts with
1013 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1014 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1015          specified file; corresponding input uses `MatLoad()`
1016 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1017          an X window display
1018 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1019          Currently only the `MATSEQDENSE` and `MATAIJ`
1020          matrix types support the Socket viewer.
1021 
1022    The user can call `PetscViewerPushFormat()` to specify the output
1023    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1024    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1025 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1026 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1027 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1028 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1029          format common among all matrix types
1030 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1031          format (which is in many cases the same as the default)
1032 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1033          size and structure (not the matrix entries)
1034 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1035          the matrix structure
1036 
1037     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1038     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1039 
1040     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1041 
1042     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1043       viewer is used.
1044 
1045       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1046       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1047 
1048       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1049       and then use the following mouse functions.
1050 .vb
1051   left mouse: zoom in
1052   middle mouse: zoom out
1053   right mouse: continue with the simulation
1054 .ve
1055 
1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1057           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1058 @*/
1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1060 {
1061   PetscInt          rows, cols, rbs, cbs;
1062   PetscBool         isascii, isstring, issaws;
1063   PetscViewerFormat format;
1064   PetscMPIInt       size;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1068   PetscValidType(mat, 1);
1069   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1070   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1071   PetscCheckSameComm(mat, 1, viewer, 2);
1072 
1073   PetscCall(PetscViewerGetFormat(viewer, &format));
1074   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1075   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1076 
1077   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1080   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1081 
1082   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1083   if (isascii) {
1084     if (!mat->preallocated) {
1085       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1086       PetscFunctionReturn(PETSC_SUCCESS);
1087     }
1088     if (!mat->assembled) {
1089       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1090       PetscFunctionReturn(PETSC_SUCCESS);
1091     }
1092     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1093     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1094       MatNullSpace nullsp, transnullsp;
1095 
1096       PetscCall(PetscViewerASCIIPushTab(viewer));
1097       PetscCall(MatGetSize(mat, &rows, &cols));
1098       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1099       if (rbs != 1 || cbs != 1) {
1100         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1101         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1102       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1103       if (mat->factortype) {
1104         MatSolverType solver;
1105         PetscCall(MatFactorGetSolverType(mat, &solver));
1106         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1107       }
1108       if (mat->ops->getinfo) {
1109         MatInfo info;
1110         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1111         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1112         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1113       }
1114       PetscCall(MatGetNullSpace(mat, &nullsp));
1115       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1116       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1117       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1118       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatProductView(mat, viewer));
1122       PetscCall(PetscViewerASCIIPopTab(viewer));
1123     }
1124   } else if (issaws) {
1125 #if defined(PETSC_HAVE_SAWS)
1126     PetscMPIInt rank;
1127 
1128     PetscCall(PetscObjectName((PetscObject)mat));
1129     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1130     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1131 #endif
1132   } else if (isstring) {
1133     const char *type;
1134     PetscCall(MatGetType(mat, &type));
1135     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1136     PetscTryTypeMethod(mat, view, viewer);
1137   }
1138   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1139     PetscCall(PetscViewerASCIIPushTab(viewer));
1140     PetscUseTypeMethod(mat, viewnative, viewer);
1141     PetscCall(PetscViewerASCIIPopTab(viewer));
1142   } else if (mat->ops->view) {
1143     PetscCall(PetscViewerASCIIPushTab(viewer));
1144     PetscUseTypeMethod(mat, view, viewer);
1145     PetscCall(PetscViewerASCIIPopTab(viewer));
1146   }
1147   if (isascii) {
1148     PetscCall(PetscViewerGetFormat(viewer, &format));
1149     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1150   }
1151   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1152   PetscFunctionReturn(PETSC_SUCCESS);
1153 }
1154 
1155 #if defined(PETSC_USE_DEBUG)
1156   #include <../src/sys/totalview/tv_data_display.h>
1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1158 {
1159   TV_add_row("Local rows", "int", &mat->rmap->n);
1160   TV_add_row("Local columns", "int", &mat->cmap->n);
1161   TV_add_row("Global rows", "int", &mat->rmap->N);
1162   TV_add_row("Global columns", "int", &mat->cmap->N);
1163   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1164   return TV_format_OK;
1165 }
1166 #endif
1167 
1168 /*@C
1169    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1170    with `MatView()`.  The matrix format is determined from the options database.
1171    Generates a parallel MPI matrix if the communicator has more than one
1172    processor.  The default matrix type is `MATAIJ`.
1173 
1174    Collective
1175 
1176    Input Parameters:
1177 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1178             or some related function before a call to `MatLoad()`
1179 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1180 
1181    Options Database Keys:
1182    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1183    block size
1184 .    -matload_block_size <bs> - set block size
1185 
1186    Level: beginner
1187 
1188    Notes:
1189    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1190    `Mat` before calling this routine if you wish to set it from the options database.
1191 
1192    `MatLoad()` automatically loads into the options database any options
1193    given in the file filename.info where filename is the name of the file
1194    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1195    file will be ignored if you use the -viewer_binary_skip_info option.
1196 
1197    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1198    sets the default matrix type AIJ and sets the local and global sizes.
1199    If type and/or size is already set, then the same are used.
1200 
1201    In parallel, each processor can load a subset of rows (or the
1202    entire matrix).  This routine is especially useful when a large
1203    matrix is stored on disk and only part of it is desired on each
1204    processor.  For example, a parallel solver may access only some of
1205    the rows from each processor.  The algorithm used here reads
1206    relatively small blocks of data rather than reading the entire
1207    matrix and then subsetting it.
1208 
1209    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1210    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1211    or the sequence like
1212 .vb
1213     `PetscViewer` v;
1214     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1215     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1216     `PetscViewerSetFromOptions`(v);
1217     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1218     `PetscViewerFileSetName`(v,"datafile");
1219 .ve
1220    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1221 $ -viewer_type {binary, hdf5}
1222 
1223    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1224    and src/mat/tutorials/ex10.c with the second approach.
1225 
1226    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1227    is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1228    Multiple objects, both matrices and vectors, can be stored within the same file.
1229    Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1230 
1231    Most users should not need to know the details of the binary storage
1232    format, since `MatLoad()` and `MatView()` completely hide these details.
1233    But for anyone who is interested, the standard binary matrix storage
1234    format is
1235 
1236 .vb
1237     PetscInt    MAT_FILE_CLASSID
1238     PetscInt    number of rows
1239     PetscInt    number of columns
1240     PetscInt    total number of nonzeros
1241     PetscInt    *number nonzeros in each row
1242     PetscInt    *column indices of all nonzeros (starting index is zero)
1243     PetscScalar *values of all nonzeros
1244 .ve
1245    If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1246    stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1247    case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1248 
1249    PETSc automatically does the byte swapping for
1250    machines that store the bytes reversed. Thus if you write your own binary
1251    read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1252    and `PetscBinaryWrite()` to see how this may be done.
1253 
1254    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1255    Each processor's chunk is loaded independently by its owning MPI process.
1256    Multiple objects, both matrices and vectors, can be stored within the same file.
1257    They are looked up by their PetscObject name.
1258 
1259    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1260    by default the same structure and naming of the AIJ arrays and column count
1261    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1262 $    save example.mat A b -v7.3
1263    can be directly read by this routine (see Reference 1 for details).
1264 
1265    Depending on your MATLAB version, this format might be a default,
1266    otherwise you can set it as default in Preferences.
1267 
1268    Unless -nocompression flag is used to save the file in MATLAB,
1269    PETSc must be configured with ZLIB package.
1270 
1271    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1272 
1273    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1274 
1275    Corresponding `MatView()` is not yet implemented.
1276 
1277    The loaded matrix is actually a transpose of the original one in MATLAB,
1278    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1279    With this format, matrix is automatically transposed by PETSc,
1280    unless the matrix is marked as SPD or symmetric
1281    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1282 
1283    References:
1284 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1285 
1286 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1287  @*/
1288 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1289 {
1290   PetscBool flg;
1291 
1292   PetscFunctionBegin;
1293   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1294   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1295 
1296   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1297 
1298   flg = PETSC_FALSE;
1299   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1300   if (flg) {
1301     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1302     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1303   }
1304   flg = PETSC_FALSE;
1305   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1306   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1307 
1308   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1309   PetscUseTypeMethod(mat, load, viewer);
1310   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1311   PetscFunctionReturn(PETSC_SUCCESS);
1312 }
1313 
1314 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1315 {
1316   Mat_Redundant *redund = *redundant;
1317 
1318   PetscFunctionBegin;
1319   if (redund) {
1320     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1321       PetscCall(ISDestroy(&redund->isrow));
1322       PetscCall(ISDestroy(&redund->iscol));
1323       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1324     } else {
1325       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1326       PetscCall(PetscFree(redund->sbuf_j));
1327       PetscCall(PetscFree(redund->sbuf_a));
1328       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1329         PetscCall(PetscFree(redund->rbuf_j[i]));
1330         PetscCall(PetscFree(redund->rbuf_a[i]));
1331       }
1332       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1333     }
1334 
1335     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1336     PetscCall(PetscFree(redund));
1337   }
1338   PetscFunctionReturn(PETSC_SUCCESS);
1339 }
1340 
1341 /*@C
1342    MatDestroy - Frees space taken by a matrix.
1343 
1344    Collective
1345 
1346    Input Parameter:
1347 .  A - the matrix
1348 
1349    Level: beginner
1350 
1351    Developer Note:
1352    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1353    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1354    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1355    if changes are needed here.
1356 
1357 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1358 @*/
1359 PetscErrorCode MatDestroy(Mat *A)
1360 {
1361   PetscFunctionBegin;
1362   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1363   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1364   if (--((PetscObject)(*A))->refct > 0) {
1365     *A = NULL;
1366     PetscFunctionReturn(PETSC_SUCCESS);
1367   }
1368 
1369   /* if memory was published with SAWs then destroy it */
1370   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1371   PetscTryTypeMethod((*A), destroy);
1372 
1373   PetscCall(PetscFree((*A)->factorprefix));
1374   PetscCall(PetscFree((*A)->defaultvectype));
1375   PetscCall(PetscFree((*A)->defaultrandtype));
1376   PetscCall(PetscFree((*A)->bsizes));
1377   PetscCall(PetscFree((*A)->solvertype));
1378   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1379   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1380   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1381   PetscCall(MatProductClear(*A));
1382   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1383   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1384   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1385   PetscCall(MatDestroy(&(*A)->schur));
1386   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1387   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1388   PetscCall(PetscHeaderDestroy(A));
1389   PetscFunctionReturn(PETSC_SUCCESS);
1390 }
1391 
1392 /*@C
1393    MatSetValues - Inserts or adds a block of values into a matrix.
1394    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1395    MUST be called after all calls to `MatSetValues()` have been completed.
1396 
1397    Not Collective
1398 
1399    Input Parameters:
1400 +  mat - the matrix
1401 .  v - a logically two-dimensional array of values
1402 .  m - the number of rows
1403 .  idxm - the global indices of the rows
1404 .  n - the number of columns
1405 .  idxn - the global indices of the columns
1406 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1407 
1408    Level: beginner
1409 
1410    Notes:
1411    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1412 
1413    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1414    options cannot be mixed without intervening calls to the assembly
1415    routines.
1416 
1417    `MatSetValues()` uses 0-based row and column numbers in Fortran
1418    as well as in C.
1419 
1420    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1421    simply ignored. This allows easily inserting element stiffness matrices
1422    with homogeneous Dirchlet boundary conditions that you don't want represented
1423    in the matrix.
1424 
1425    Efficiency Alert:
1426    The routine `MatSetValuesBlocked()` may offer much better efficiency
1427    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1428 
1429    Developer Note:
1430    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1431    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1432 
1433 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1434           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1435 @*/
1436 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1437 {
1438   PetscFunctionBeginHot;
1439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1440   PetscValidType(mat, 1);
1441   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1442   PetscValidIntPointer(idxm, 3);
1443   PetscValidIntPointer(idxn, 5);
1444   MatCheckPreallocated(mat, 1);
1445 
1446   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1447   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1448 
1449   if (PetscDefined(USE_DEBUG)) {
1450     PetscInt i, j;
1451 
1452     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1453     for (i = 0; i < m; i++) {
1454       for (j = 0; j < n; j++) {
1455         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1456 #if defined(PETSC_USE_COMPLEX)
1457           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1458 #else
1459           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1460 #endif
1461       }
1462     }
1463     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1464     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1465   }
1466 
1467   if (mat->assembled) {
1468     mat->was_assembled = PETSC_TRUE;
1469     mat->assembled     = PETSC_FALSE;
1470   }
1471   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1472   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1473   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1474   PetscFunctionReturn(PETSC_SUCCESS);
1475 }
1476 
1477 /*@C
1478    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1479    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1480    MUST be called after all calls to `MatSetValues()` have been completed.
1481 
1482    Not Collective
1483 
1484    Input Parameters:
1485 +  mat - the matrix
1486 .  v - a logically two-dimensional array of values
1487 .  ism - the rows to provide
1488 .  isn - the columns to provide
1489 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1490 
1491    Level: beginner
1492 
1493    Notes:
1494    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1495 
1496    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1497    options cannot be mixed without intervening calls to the assembly
1498    routines.
1499 
1500    `MatSetValues()` uses 0-based row and column numbers in Fortran
1501    as well as in C.
1502 
1503    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1504    simply ignored. This allows easily inserting element stiffness matrices
1505    with homogeneous Dirchlet boundary conditions that you don't want represented
1506    in the matrix.
1507 
1508    Efficiency Alert:
1509    The routine `MatSetValuesBlocked()` may offer much better efficiency
1510    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1511 
1512     This is currently not optimized for any particular `ISType`
1513 
1514    Developer Notes:
1515     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1516                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1517 
1518 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1519           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1520 @*/
1521 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1522 {
1523   PetscInt        m, n;
1524   const PetscInt *rows, *cols;
1525 
1526   PetscFunctionBeginHot;
1527   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1528   PetscCall(ISGetIndices(ism, &rows));
1529   PetscCall(ISGetIndices(isn, &cols));
1530   PetscCall(ISGetLocalSize(ism, &m));
1531   PetscCall(ISGetLocalSize(isn, &n));
1532   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1533   PetscCall(ISRestoreIndices(ism, &rows));
1534   PetscCall(ISRestoreIndices(isn, &cols));
1535   PetscFunctionReturn(PETSC_SUCCESS);
1536 }
1537 
1538 /*@
1539    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1540         values into a matrix
1541 
1542    Not Collective
1543 
1544    Input Parameters:
1545 +  mat - the matrix
1546 .  row - the (block) row to set
1547 -  v - a logically two-dimensional array of values
1548 
1549    Level: intermediate
1550 
1551    Notes:
1552    The values, `v`, are column-oriented (for the block version) and sorted
1553 
1554    All the nonzeros in the row must be provided
1555 
1556    The matrix must have previously had its column indices set, likely by having been assembled.
1557 
1558    The row must belong to this process
1559 
1560 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1561           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1562 @*/
1563 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1564 {
1565   PetscInt globalrow;
1566 
1567   PetscFunctionBegin;
1568   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1569   PetscValidType(mat, 1);
1570   PetscValidScalarPointer(v, 3);
1571   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1572   PetscCall(MatSetValuesRow(mat, globalrow, v));
1573   PetscFunctionReturn(PETSC_SUCCESS);
1574 }
1575 
1576 /*@
1577    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1578         values into a matrix
1579 
1580    Not Collective
1581 
1582    Input Parameters:
1583 +  mat - the matrix
1584 .  row - the (block) row to set
1585 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1586 
1587    Level: advanced
1588 
1589    Notes:
1590    The values, `v`, are column-oriented for the block version.
1591 
1592    All the nonzeros in the row must be provided
1593 
1594    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1595 
1596    The row must belong to this process
1597 
1598 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1599           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1600 @*/
1601 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1602 {
1603   PetscFunctionBeginHot;
1604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1605   PetscValidType(mat, 1);
1606   MatCheckPreallocated(mat, 1);
1607   PetscValidScalarPointer(v, 3);
1608   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1609   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1610   mat->insertmode = INSERT_VALUES;
1611 
1612   if (mat->assembled) {
1613     mat->was_assembled = PETSC_TRUE;
1614     mat->assembled     = PETSC_FALSE;
1615   }
1616   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1617   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1618   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1619   PetscFunctionReturn(PETSC_SUCCESS);
1620 }
1621 
1622 /*@
1623    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1624      Using structured grid indexing
1625 
1626    Not Collective
1627 
1628    Input Parameters:
1629 +  mat - the matrix
1630 .  m - number of rows being entered
1631 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1632 .  n - number of columns being entered
1633 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1634 .  v - a logically two-dimensional array of values
1635 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1636 
1637    Level: beginner
1638 
1639    Notes:
1640    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1641 
1642    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1643    options cannot be mixed without intervening calls to the assembly
1644    routines.
1645 
1646    The grid coordinates are across the entire grid, not just the local portion
1647 
1648    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1649    as well as in C.
1650 
1651    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1652 
1653    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1654    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1655 
1656    The columns and rows in the stencil passed in MUST be contained within the
1657    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1658    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1659    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1660    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1661 
1662    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1663    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1664    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1665    `DM_BOUNDARY_PERIODIC` boundary type.
1666 
1667    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1668    a single value per point) you can skip filling those indices.
1669 
1670    Inspired by the structured grid interface to the HYPRE package
1671    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1672 
1673    Efficiency Alert:
1674    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1675    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1676 
1677    Fortran Note:
1678    `idxm` and `idxn` should be declared as
1679 $     MatStencil idxm(4,m),idxn(4,n)
1680    and the values inserted using
1681 .vb
1682     idxm(MatStencil_i,1) = i
1683     idxm(MatStencil_j,1) = j
1684     idxm(MatStencil_k,1) = k
1685     idxm(MatStencil_c,1) = c
1686     etc
1687 .ve
1688 
1689 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1690           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1691 @*/
1692 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1693 {
1694   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1695   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1696   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1697 
1698   PetscFunctionBegin;
1699   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1701   PetscValidType(mat, 1);
1702   PetscValidPointer(idxm, 3);
1703   PetscValidPointer(idxn, 5);
1704 
1705   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1706     jdxm = buf;
1707     jdxn = buf + m;
1708   } else {
1709     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1710     jdxm = bufm;
1711     jdxn = bufn;
1712   }
1713   for (i = 0; i < m; i++) {
1714     for (j = 0; j < 3 - sdim; j++) dxm++;
1715     tmp = *dxm++ - starts[0];
1716     for (j = 0; j < dim - 1; j++) {
1717       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1718       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1719     }
1720     if (mat->stencil.noc) dxm++;
1721     jdxm[i] = tmp;
1722   }
1723   for (i = 0; i < n; i++) {
1724     for (j = 0; j < 3 - sdim; j++) dxn++;
1725     tmp = *dxn++ - starts[0];
1726     for (j = 0; j < dim - 1; j++) {
1727       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1728       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1729     }
1730     if (mat->stencil.noc) dxn++;
1731     jdxn[i] = tmp;
1732   }
1733   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1734   PetscCall(PetscFree2(bufm, bufn));
1735   PetscFunctionReturn(PETSC_SUCCESS);
1736 }
1737 
1738 /*@
1739    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1740      Using structured grid indexing
1741 
1742    Not Collective
1743 
1744    Input Parameters:
1745 +  mat - the matrix
1746 .  m - number of rows being entered
1747 .  idxm - grid coordinates for matrix rows being entered
1748 .  n - number of columns being entered
1749 .  idxn - grid coordinates for matrix columns being entered
1750 .  v - a logically two-dimensional array of values
1751 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1752 
1753    Level: beginner
1754 
1755    Notes:
1756    By default the values, `v`, are row-oriented and unsorted.
1757    See `MatSetOption()` for other options.
1758 
1759    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1760    options cannot be mixed without intervening calls to the assembly
1761    routines.
1762 
1763    The grid coordinates are across the entire grid, not just the local portion
1764 
1765    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1766    as well as in C.
1767 
1768    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1769 
1770    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1771    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1772 
1773    The columns and rows in the stencil passed in MUST be contained within the
1774    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1775    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1776    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1777    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1778 
1779    Negative indices may be passed in idxm and idxn, these rows and columns are
1780    simply ignored. This allows easily inserting element stiffness matrices
1781    with homogeneous Dirchlet boundary conditions that you don't want represented
1782    in the matrix.
1783 
1784    Inspired by the structured grid interface to the HYPRE package
1785    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1786 
1787    Fortran Note:
1788    `idxm` and `idxn` should be declared as
1789 $     MatStencil idxm(4,m),idxn(4,n)
1790    and the values inserted using
1791 .vb
1792     idxm(MatStencil_i,1) = i
1793     idxm(MatStencil_j,1) = j
1794     idxm(MatStencil_k,1) = k
1795    etc
1796 .ve
1797 
1798 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1799           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1800           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1801 @*/
1802 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1803 {
1804   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1805   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1806   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1807 
1808   PetscFunctionBegin;
1809   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1811   PetscValidType(mat, 1);
1812   PetscValidPointer(idxm, 3);
1813   PetscValidPointer(idxn, 5);
1814   PetscValidScalarPointer(v, 6);
1815 
1816   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1817     jdxm = buf;
1818     jdxn = buf + m;
1819   } else {
1820     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1821     jdxm = bufm;
1822     jdxn = bufn;
1823   }
1824   for (i = 0; i < m; i++) {
1825     for (j = 0; j < 3 - sdim; j++) dxm++;
1826     tmp = *dxm++ - starts[0];
1827     for (j = 0; j < sdim - 1; j++) {
1828       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1829       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1830     }
1831     dxm++;
1832     jdxm[i] = tmp;
1833   }
1834   for (i = 0; i < n; i++) {
1835     for (j = 0; j < 3 - sdim; j++) dxn++;
1836     tmp = *dxn++ - starts[0];
1837     for (j = 0; j < sdim - 1; j++) {
1838       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1839       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1840     }
1841     dxn++;
1842     jdxn[i] = tmp;
1843   }
1844   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1845   PetscCall(PetscFree2(bufm, bufn));
1846   PetscFunctionReturn(PETSC_SUCCESS);
1847 }
1848 
1849 /*@
1850    MatSetStencil - Sets the grid information for setting values into a matrix via
1851         `MatSetValuesStencil()`
1852 
1853    Not Collective
1854 
1855    Input Parameters:
1856 +  mat - the matrix
1857 .  dim - dimension of the grid 1, 2, or 3
1858 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1859 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1860 -  dof - number of degrees of freedom per node
1861 
1862    Level: beginner
1863 
1864    Notes:
1865    Inspired by the structured grid interface to the HYPRE package
1866    (www.llnl.gov/CASC/hyper)
1867 
1868    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1869    user.
1870 
1871 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1872           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1873 @*/
1874 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1875 {
1876   PetscFunctionBegin;
1877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1878   PetscValidIntPointer(dims, 3);
1879   PetscValidIntPointer(starts, 4);
1880 
1881   mat->stencil.dim = dim + (dof > 1);
1882   for (PetscInt i = 0; i < dim; i++) {
1883     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1884     mat->stencil.starts[i] = starts[dim - i - 1];
1885   }
1886   mat->stencil.dims[dim]   = dof;
1887   mat->stencil.starts[dim] = 0;
1888   mat->stencil.noc         = (PetscBool)(dof == 1);
1889   PetscFunctionReturn(PETSC_SUCCESS);
1890 }
1891 
1892 /*@C
1893    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1894 
1895    Not Collective
1896 
1897    Input Parameters:
1898 +  mat - the matrix
1899 .  v - a logically two-dimensional array of values
1900 .  m  - the number of block rows
1901 .  idxm - the global block indices
1902 .  n - the number of block columns
1903 .  idxn - the global block indices
1904 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1905 
1906    Level: intermediate
1907 
1908    Notes:
1909    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1910    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1911 
1912    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1913    NOT the total number of rows/columns; for example, if the block size is 2 and
1914    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1915    The values in idxm would be 1 2; that is the first index for each block divided by
1916    the block size.
1917 
1918    You must call `MatSetBlockSize()` when constructing this matrix (before
1919    preallocating it).
1920 
1921    By default the values, `v`, are row-oriented, so the layout of
1922    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1923 
1924    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1925    options cannot be mixed without intervening calls to the assembly
1926    routines.
1927 
1928    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1929    as well as in C.
1930 
1931    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1932    simply ignored. This allows easily inserting element stiffness matrices
1933    with homogeneous Dirchlet boundary conditions that you don't want represented
1934    in the matrix.
1935 
1936    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1937    internal searching must be done to determine where to place the
1938    data in the matrix storage space.  By instead inserting blocks of
1939    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1940    reduced.
1941 
1942    Example:
1943 .vb
1944    Suppose m=n=2 and block size(bs) = 2 The array is
1945 
1946    1  2  | 3  4
1947    5  6  | 7  8
1948    - - - | - - -
1949    9  10 | 11 12
1950    13 14 | 15 16
1951 
1952    v[] should be passed in like
1953    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1954 
1955   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1956    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1957 .ve
1958 
1959 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1960 @*/
1961 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1962 {
1963   PetscFunctionBeginHot;
1964   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1965   PetscValidType(mat, 1);
1966   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1967   PetscValidIntPointer(idxm, 3);
1968   PetscValidIntPointer(idxn, 5);
1969   MatCheckPreallocated(mat, 1);
1970   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1971   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1972   if (PetscDefined(USE_DEBUG)) {
1973     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1974     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1975   }
1976   if (PetscDefined(USE_DEBUG)) {
1977     PetscInt rbs, cbs, M, N, i;
1978     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1979     PetscCall(MatGetSize(mat, &M, &N));
1980     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1981     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1982   }
1983   if (mat->assembled) {
1984     mat->was_assembled = PETSC_TRUE;
1985     mat->assembled     = PETSC_FALSE;
1986   }
1987   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1988   if (mat->ops->setvaluesblocked) {
1989     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1990   } else {
1991     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1992     PetscInt i, j, bs, cbs;
1993 
1994     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1995     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1996       iidxm = buf;
1997       iidxn = buf + m * bs;
1998     } else {
1999       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2000       iidxm = bufr;
2001       iidxn = bufc;
2002     }
2003     for (i = 0; i < m; i++) {
2004       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2005     }
2006     if (m != n || bs != cbs || idxm != idxn) {
2007       for (i = 0; i < n; i++) {
2008         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2009       }
2010     } else iidxn = iidxm;
2011     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2012     PetscCall(PetscFree2(bufr, bufc));
2013   }
2014   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2015   PetscFunctionReturn(PETSC_SUCCESS);
2016 }
2017 
2018 /*@C
2019    MatGetValues - Gets a block of local values from a matrix.
2020 
2021    Not Collective; can only return values that are owned by the give process
2022 
2023    Input Parameters:
2024 +  mat - the matrix
2025 .  v - a logically two-dimensional array for storing the values
2026 .  m  - the number of rows
2027 .  idxm - the  global indices of the rows
2028 .  n - the number of columns
2029 -  idxn - the global indices of the columns
2030 
2031    Level: advanced
2032 
2033    Notes:
2034      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2035      The values, `v`, are then returned in a row-oriented format,
2036      analogous to that used by default in `MatSetValues()`.
2037 
2038      `MatGetValues()` uses 0-based row and column numbers in
2039      Fortran as well as in C.
2040 
2041      `MatGetValues()` requires that the matrix has been assembled
2042      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2043      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2044      without intermediate matrix assembly.
2045 
2046      Negative row or column indices will be ignored and those locations in `v` will be
2047      left unchanged.
2048 
2049      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2050      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2051      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2052 
2053 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2054 @*/
2055 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2056 {
2057   PetscFunctionBegin;
2058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2059   PetscValidType(mat, 1);
2060   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2061   PetscValidIntPointer(idxm, 3);
2062   PetscValidIntPointer(idxn, 5);
2063   PetscValidScalarPointer(v, 6);
2064   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2065   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2066   MatCheckPreallocated(mat, 1);
2067 
2068   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2069   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2070   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2071   PetscFunctionReturn(PETSC_SUCCESS);
2072 }
2073 
2074 /*@C
2075    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2076      defined previously by `MatSetLocalToGlobalMapping()`
2077 
2078    Not Collective
2079 
2080    Input Parameters:
2081 +  mat - the matrix
2082 .  nrow - number of rows
2083 .  irow - the row local indices
2084 .  ncol - number of columns
2085 -  icol - the column local indices
2086 
2087    Output Parameter:
2088 .  y -  a logically two-dimensional array of values
2089 
2090    Level: advanced
2091 
2092    Notes:
2093      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2094 
2095      This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering,
2096      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2097      determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2098      with `MatSetLocalToGlobalMapping()`.
2099 
2100    Developer Note:
2101       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2102       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2103 
2104 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2105           `MatSetValuesLocal()`, `MatGetValues()`
2106 @*/
2107 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2108 {
2109   PetscFunctionBeginHot;
2110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2111   PetscValidType(mat, 1);
2112   MatCheckPreallocated(mat, 1);
2113   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2114   PetscValidIntPointer(irow, 3);
2115   PetscValidIntPointer(icol, 5);
2116   if (PetscDefined(USE_DEBUG)) {
2117     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2118     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2119   }
2120   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2121   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2122   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2123   else {
2124     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2125     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2126       irowm = buf;
2127       icolm = buf + nrow;
2128     } else {
2129       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2130       irowm = bufr;
2131       icolm = bufc;
2132     }
2133     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2134     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2135     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2136     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2137     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2138     PetscCall(PetscFree2(bufr, bufc));
2139   }
2140   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2141   PetscFunctionReturn(PETSC_SUCCESS);
2142 }
2143 
2144 /*@
2145   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2146   the same size. Currently, this can only be called once and creates the given matrix.
2147 
2148   Not Collective
2149 
2150   Input Parameters:
2151 + mat - the matrix
2152 . nb - the number of blocks
2153 . bs - the number of rows (and columns) in each block
2154 . rows - a concatenation of the rows for each block
2155 - v - a concatenation of logically two-dimensional arrays of values
2156 
2157   Level: advanced
2158 
2159   Note:
2160   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2161 
2162   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2163 
2164 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2165           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2166 @*/
2167 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2168 {
2169   PetscFunctionBegin;
2170   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2171   PetscValidType(mat, 1);
2172   PetscValidIntPointer(rows, 4);
2173   PetscValidScalarPointer(v, 5);
2174   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2175 
2176   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2177   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2178   else {
2179     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2180   }
2181   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2182   PetscFunctionReturn(PETSC_SUCCESS);
2183 }
2184 
2185 /*@
2186    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2187    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2188    using a local (per-processor) numbering.
2189 
2190    Not Collective
2191 
2192    Input Parameters:
2193 +  x - the matrix
2194 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2195 -  cmapping - column mapping
2196 
2197    Level: intermediate
2198 
2199    Note:
2200    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2201 
2202 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2203 @*/
2204 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2205 {
2206   PetscFunctionBegin;
2207   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2208   PetscValidType(x, 1);
2209   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2210   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2211   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2212   else {
2213     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2214     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2215   }
2216   PetscFunctionReturn(PETSC_SUCCESS);
2217 }
2218 
2219 /*@
2220    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2221 
2222    Not Collective
2223 
2224    Input Parameter:
2225 .  A - the matrix
2226 
2227    Output Parameters:
2228 + rmapping - row mapping
2229 - cmapping - column mapping
2230 
2231    Level: advanced
2232 
2233 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2234 @*/
2235 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2236 {
2237   PetscFunctionBegin;
2238   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2239   PetscValidType(A, 1);
2240   if (rmapping) {
2241     PetscValidPointer(rmapping, 2);
2242     *rmapping = A->rmap->mapping;
2243   }
2244   if (cmapping) {
2245     PetscValidPointer(cmapping, 3);
2246     *cmapping = A->cmap->mapping;
2247   }
2248   PetscFunctionReturn(PETSC_SUCCESS);
2249 }
2250 
2251 /*@
2252    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2253 
2254    Logically Collective
2255 
2256    Input Parameters:
2257 +  A - the matrix
2258 . rmap - row layout
2259 - cmap - column layout
2260 
2261    Level: advanced
2262 
2263    Note:
2264    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2265 
2266 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2267 @*/
2268 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2269 {
2270   PetscFunctionBegin;
2271   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2272   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2273   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2274   PetscFunctionReturn(PETSC_SUCCESS);
2275 }
2276 
2277 /*@
2278    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2279 
2280    Not Collective
2281 
2282    Input Parameter:
2283 .  A - the matrix
2284 
2285    Output Parameters:
2286 + rmap - row layout
2287 - cmap - column layout
2288 
2289    Level: advanced
2290 
2291 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2292 @*/
2293 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2294 {
2295   PetscFunctionBegin;
2296   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2297   PetscValidType(A, 1);
2298   if (rmap) {
2299     PetscValidPointer(rmap, 2);
2300     *rmap = A->rmap;
2301   }
2302   if (cmap) {
2303     PetscValidPointer(cmap, 3);
2304     *cmap = A->cmap;
2305   }
2306   PetscFunctionReturn(PETSC_SUCCESS);
2307 }
2308 
2309 /*@C
2310    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2311    using a local numbering of the nodes.
2312 
2313    Not Collective
2314 
2315    Input Parameters:
2316 +  mat - the matrix
2317 .  nrow - number of rows
2318 .  irow - the row local indices
2319 .  ncol - number of columns
2320 .  icol - the column local indices
2321 .  y -  a logically two-dimensional array of values
2322 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2323 
2324    Level: intermediate
2325 
2326    Notes:
2327    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2328       `MatSetUp()` before using this routine
2329 
2330    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2331 
2332    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2333    options cannot be mixed without intervening calls to the assembly
2334    routines.
2335 
2336    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2337    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2338 
2339    Developer Note:
2340     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2341                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2342 
2343 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2344           `MatGetValuesLocal()`
2345 @*/
2346 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2347 {
2348   PetscFunctionBeginHot;
2349   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2350   PetscValidType(mat, 1);
2351   MatCheckPreallocated(mat, 1);
2352   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2353   PetscValidIntPointer(irow, 3);
2354   PetscValidIntPointer(icol, 5);
2355   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2356   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2357   if (PetscDefined(USE_DEBUG)) {
2358     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2359     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2360   }
2361 
2362   if (mat->assembled) {
2363     mat->was_assembled = PETSC_TRUE;
2364     mat->assembled     = PETSC_FALSE;
2365   }
2366   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2367   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2368   else {
2369     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2370     const PetscInt *irowm, *icolm;
2371 
2372     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2373       bufr  = buf;
2374       bufc  = buf + nrow;
2375       irowm = bufr;
2376       icolm = bufc;
2377     } else {
2378       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2379       irowm = bufr;
2380       icolm = bufc;
2381     }
2382     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2383     else irowm = irow;
2384     if (mat->cmap->mapping) {
2385       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2386         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2387       } else icolm = irowm;
2388     } else icolm = icol;
2389     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2390     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2391   }
2392   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2393   PetscFunctionReturn(PETSC_SUCCESS);
2394 }
2395 
2396 /*@C
2397    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2398    using a local ordering of the nodes a block at a time.
2399 
2400    Not Collective
2401 
2402    Input Parameters:
2403 +  x - the matrix
2404 .  nrow - number of rows
2405 .  irow - the row local indices
2406 .  ncol - number of columns
2407 .  icol - the column local indices
2408 .  y -  a logically two-dimensional array of values
2409 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2410 
2411    Level: intermediate
2412 
2413    Notes:
2414    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2415       `MatSetUp()` before using this routine
2416 
2417    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2418       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2419 
2420    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2421    options cannot be mixed without intervening calls to the assembly
2422    routines.
2423 
2424    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2425    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2426 
2427    Developer Note:
2428     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2429                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2430 
2431 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2432           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2433 @*/
2434 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2435 {
2436   PetscFunctionBeginHot;
2437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2438   PetscValidType(mat, 1);
2439   MatCheckPreallocated(mat, 1);
2440   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2441   PetscValidIntPointer(irow, 3);
2442   PetscValidIntPointer(icol, 5);
2443   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2444   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2445   if (PetscDefined(USE_DEBUG)) {
2446     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2447     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2448   }
2449 
2450   if (mat->assembled) {
2451     mat->was_assembled = PETSC_TRUE;
2452     mat->assembled     = PETSC_FALSE;
2453   }
2454   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2455     PetscInt irbs, rbs;
2456     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2457     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2458     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2459   }
2460   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2461     PetscInt icbs, cbs;
2462     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2463     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2464     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2465   }
2466   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2467   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2468   else {
2469     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2470     const PetscInt *irowm, *icolm;
2471 
2472     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2473       bufr  = buf;
2474       bufc  = buf + nrow;
2475       irowm = bufr;
2476       icolm = bufc;
2477     } else {
2478       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2479       irowm = bufr;
2480       icolm = bufc;
2481     }
2482     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2483     else irowm = irow;
2484     if (mat->cmap->mapping) {
2485       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2486         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2487       } else icolm = irowm;
2488     } else icolm = icol;
2489     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2490     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2491   }
2492   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2493   PetscFunctionReturn(PETSC_SUCCESS);
2494 }
2495 
2496 /*@
2497    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2498 
2499    Collective
2500 
2501    Input Parameters:
2502 +  mat - the matrix
2503 -  x   - the vector to be multiplied
2504 
2505    Output Parameter:
2506 .  y - the result
2507 
2508    Level: developer
2509 
2510    Note:
2511    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2512    call `MatMultDiagonalBlock`(A,y,y).
2513 
2514 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2515 @*/
2516 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2517 {
2518   PetscFunctionBegin;
2519   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2520   PetscValidType(mat, 1);
2521   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2522   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2523 
2524   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2525   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2526   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2527   MatCheckPreallocated(mat, 1);
2528 
2529   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2530   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2531   PetscFunctionReturn(PETSC_SUCCESS);
2532 }
2533 
2534 /*@
2535    MatMult - Computes the matrix-vector product, y = Ax.
2536 
2537    Neighbor-wise Collective
2538 
2539    Input Parameters:
2540 +  mat - the matrix
2541 -  x   - the vector to be multiplied
2542 
2543    Output Parameter:
2544 .  y - the result
2545 
2546    Level: beginner
2547 
2548    Note:
2549    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2550    call `MatMult`(A,y,y).
2551 
2552 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2553 @*/
2554 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2555 {
2556   PetscFunctionBegin;
2557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2558   PetscValidType(mat, 1);
2559   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2560   VecCheckAssembled(x);
2561   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2562   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2563   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2564   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2565   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2566   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2567   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2568   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2569   PetscCall(VecSetErrorIfLocked(y, 3));
2570   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2571   MatCheckPreallocated(mat, 1);
2572 
2573   PetscCall(VecLockReadPush(x));
2574   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2575   PetscUseTypeMethod(mat, mult, x, y);
2576   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2577   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2578   PetscCall(VecLockReadPop(x));
2579   PetscFunctionReturn(PETSC_SUCCESS);
2580 }
2581 
2582 /*@
2583    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2584 
2585    Neighbor-wise Collective
2586 
2587    Input Parameters:
2588 +  mat - the matrix
2589 -  x   - the vector to be multiplied
2590 
2591    Output Parameter:
2592 .  y - the result
2593 
2594    Level: beginner
2595 
2596    Notes:
2597    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2598    call `MatMultTranspose`(A,y,y).
2599 
2600    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2601    use `MatMultHermitianTranspose()`
2602 
2603 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2604 @*/
2605 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2606 {
2607   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2608 
2609   PetscFunctionBegin;
2610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2611   PetscValidType(mat, 1);
2612   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2613   VecCheckAssembled(x);
2614   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2615 
2616   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2617   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2618   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2619   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2620   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2621   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2622   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2623   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2624   MatCheckPreallocated(mat, 1);
2625 
2626   if (!mat->ops->multtranspose) {
2627     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2628     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2629   } else op = mat->ops->multtranspose;
2630   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2631   PetscCall(VecLockReadPush(x));
2632   PetscCall((*op)(mat, x, y));
2633   PetscCall(VecLockReadPop(x));
2634   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2635   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2636   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2637   PetscFunctionReturn(PETSC_SUCCESS);
2638 }
2639 
2640 /*@
2641    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2642 
2643    Neighbor-wise Collective
2644 
2645    Input Parameters:
2646 +  mat - the matrix
2647 -  x   - the vector to be multilplied
2648 
2649    Output Parameter:
2650 .  y - the result
2651 
2652    Level: beginner
2653 
2654    Notes:
2655    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2656    call `MatMultHermitianTranspose`(A,y,y).
2657 
2658    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2659 
2660    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2661 
2662 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2663 @*/
2664 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2665 {
2666   PetscFunctionBegin;
2667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2668   PetscValidType(mat, 1);
2669   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2670   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2671 
2672   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2673   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2674   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2675   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2676   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2677   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2678   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2679   MatCheckPreallocated(mat, 1);
2680 
2681   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2682 #if defined(PETSC_USE_COMPLEX)
2683   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2684     PetscCall(VecLockReadPush(x));
2685     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2686     else PetscUseTypeMethod(mat, mult, x, y);
2687     PetscCall(VecLockReadPop(x));
2688   } else {
2689     Vec w;
2690     PetscCall(VecDuplicate(x, &w));
2691     PetscCall(VecCopy(x, w));
2692     PetscCall(VecConjugate(w));
2693     PetscCall(MatMultTranspose(mat, w, y));
2694     PetscCall(VecDestroy(&w));
2695     PetscCall(VecConjugate(y));
2696   }
2697   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2698 #else
2699   PetscCall(MatMultTranspose(mat, x, y));
2700 #endif
2701   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2702   PetscFunctionReturn(PETSC_SUCCESS);
2703 }
2704 
2705 /*@
2706     MatMultAdd -  Computes v3 = v2 + A * v1.
2707 
2708     Neighbor-wise Collective
2709 
2710     Input Parameters:
2711 +   mat - the matrix
2712 .   v1 - the vector to be multiplied by `mat`
2713 -   v2 - the vector to be added to the result
2714 
2715     Output Parameter:
2716 .   v3 - the result
2717 
2718     Level: beginner
2719 
2720     Note:
2721     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2722     call `MatMultAdd`(A,v1,v2,v1).
2723 
2724 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2725 @*/
2726 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2727 {
2728   PetscFunctionBegin;
2729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2730   PetscValidType(mat, 1);
2731   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2732   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2733   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2734 
2735   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2736   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2737   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2738   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2739      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2740   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2741   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2742   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2743   MatCheckPreallocated(mat, 1);
2744 
2745   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2746   PetscCall(VecLockReadPush(v1));
2747   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2748   PetscCall(VecLockReadPop(v1));
2749   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2750   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2751   PetscFunctionReturn(PETSC_SUCCESS);
2752 }
2753 
2754 /*@
2755    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2756 
2757    Neighbor-wise Collective
2758 
2759    Input Parameters:
2760 +  mat - the matrix
2761 .  v1 - the vector to be multiplied by the transpose of the matrix
2762 -  v2 - the vector to be added to the result
2763 
2764    Output Parameter:
2765 .  v3 - the result
2766 
2767    Level: beginner
2768 
2769    Note:
2770    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2771    call `MatMultTransposeAdd`(A,v1,v2,v1).
2772 
2773 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2774 @*/
2775 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2776 {
2777   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2778 
2779   PetscFunctionBegin;
2780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2781   PetscValidType(mat, 1);
2782   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2783   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2784   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2785 
2786   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2787   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2788   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2789   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2790   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2791   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2792   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2793   MatCheckPreallocated(mat, 1);
2794 
2795   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2796   PetscCall(VecLockReadPush(v1));
2797   PetscCall((*op)(mat, v1, v2, v3));
2798   PetscCall(VecLockReadPop(v1));
2799   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2800   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2801   PetscFunctionReturn(PETSC_SUCCESS);
2802 }
2803 
2804 /*@
2805    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2806 
2807    Neighbor-wise Collective
2808 
2809    Input Parameters:
2810 +  mat - the matrix
2811 .  v1 - the vector to be multiplied by the Hermitian transpose
2812 -  v2 - the vector to be added to the result
2813 
2814    Output Parameter:
2815 .  v3 - the result
2816 
2817    Level: beginner
2818 
2819    Note:
2820    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2821    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2822 
2823 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2824 @*/
2825 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2826 {
2827   PetscFunctionBegin;
2828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2829   PetscValidType(mat, 1);
2830   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2831   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2832   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2833 
2834   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2835   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2836   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2837   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2838   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2839   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2840   MatCheckPreallocated(mat, 1);
2841 
2842   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2843   PetscCall(VecLockReadPush(v1));
2844   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2845   else {
2846     Vec w, z;
2847     PetscCall(VecDuplicate(v1, &w));
2848     PetscCall(VecCopy(v1, w));
2849     PetscCall(VecConjugate(w));
2850     PetscCall(VecDuplicate(v3, &z));
2851     PetscCall(MatMultTranspose(mat, w, z));
2852     PetscCall(VecDestroy(&w));
2853     PetscCall(VecConjugate(z));
2854     if (v2 != v3) {
2855       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2856     } else {
2857       PetscCall(VecAXPY(v3, 1.0, z));
2858     }
2859     PetscCall(VecDestroy(&z));
2860   }
2861   PetscCall(VecLockReadPop(v1));
2862   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2863   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2864   PetscFunctionReturn(PETSC_SUCCESS);
2865 }
2866 
2867 /*@C
2868    MatGetFactorType - gets the type of factorization it is
2869 
2870    Not Collective
2871 
2872    Input Parameter:
2873 .  mat - the matrix
2874 
2875    Output Parameter:
2876 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2877 
2878    Level: intermediate
2879 
2880 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2881           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2882 @*/
2883 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2884 {
2885   PetscFunctionBegin;
2886   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2887   PetscValidType(mat, 1);
2888   PetscValidPointer(t, 2);
2889   *t = mat->factortype;
2890   PetscFunctionReturn(PETSC_SUCCESS);
2891 }
2892 
2893 /*@C
2894    MatSetFactorType - sets the type of factorization it is
2895 
2896    Logically Collective
2897 
2898    Input Parameters:
2899 +  mat - the matrix
2900 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2901 
2902    Level: intermediate
2903 
2904 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2905           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2906 @*/
2907 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2908 {
2909   PetscFunctionBegin;
2910   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2911   PetscValidType(mat, 1);
2912   mat->factortype = t;
2913   PetscFunctionReturn(PETSC_SUCCESS);
2914 }
2915 
2916 /*@C
2917    MatGetInfo - Returns information about matrix storage (number of
2918    nonzeros, memory, etc.).
2919 
2920    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2921 
2922    Input Parameters:
2923 +  mat - the matrix
2924 -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2925 
2926    Output Parameter:
2927 .  info - matrix information context
2928 
2929    Options Database Key:
2930 .  -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2931 
2932    Notes:
2933    The `MatInfo` context contains a variety of matrix data, including
2934    number of nonzeros allocated and used, number of mallocs during
2935    matrix assembly, etc.  Additional information for factored matrices
2936    is provided (such as the fill ratio, number of mallocs during
2937    factorization, etc.).
2938 
2939    Example:
2940    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2941    data within the MatInfo context.  For example,
2942 .vb
2943       MatInfo info;
2944       Mat     A;
2945       double  mal, nz_a, nz_u;
2946 
2947       MatGetInfo(A, MAT_LOCAL, &info);
2948       mal  = info.mallocs;
2949       nz_a = info.nz_allocated;
2950 .ve
2951 
2952    Fortran users should declare info as a double precision
2953    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2954    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2955    a complete list of parameter names.
2956 .vb
2957       double  precision info(MAT_INFO_SIZE)
2958       double  precision mal, nz_a
2959       Mat     A
2960       integer ierr
2961 
2962       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2963       mal = info(MAT_INFO_MALLOCS)
2964       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2965 .ve
2966 
2967     Level: intermediate
2968 
2969     Developer Note:
2970     The Fortran interface is not autogenerated as the
2971     interface definition cannot be generated correctly [due to `MatInfo` argument]
2972 
2973 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2974 @*/
2975 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2976 {
2977   PetscFunctionBegin;
2978   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2979   PetscValidType(mat, 1);
2980   PetscValidPointer(info, 3);
2981   MatCheckPreallocated(mat, 1);
2982   PetscUseTypeMethod(mat, getinfo, flag, info);
2983   PetscFunctionReturn(PETSC_SUCCESS);
2984 }
2985 
2986 /*
2987    This is used by external packages where it is not easy to get the info from the actual
2988    matrix factorization.
2989 */
2990 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2991 {
2992   PetscFunctionBegin;
2993   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2994   PetscFunctionReturn(PETSC_SUCCESS);
2995 }
2996 
2997 /*@C
2998    MatLUFactor - Performs in-place LU factorization of matrix.
2999 
3000    Collective
3001 
3002    Input Parameters:
3003 +  mat - the matrix
3004 .  row - row permutation
3005 .  col - column permutation
3006 -  info - options for factorization, includes
3007 .vb
3008           fill - expected fill as ratio of original fill.
3009           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3010                    Run with the option -info to determine an optimal value to use
3011 .ve
3012    Level: developer
3013 
3014    Notes:
3015    Most users should employ the `KSP` interface for linear solvers
3016    instead of working directly with matrix algebra routines such as this.
3017    See, e.g., `KSPCreate()`.
3018 
3019    This changes the state of the matrix to a factored matrix; it cannot be used
3020    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3021 
3022    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3023    when not using `KSP`.
3024 
3025    Developer Note:
3026    The Fortran interface is not autogenerated as the
3027    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3028 
3029 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3030           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3031 @*/
3032 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3033 {
3034   MatFactorInfo tinfo;
3035 
3036   PetscFunctionBegin;
3037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3038   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3039   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3040   if (info) PetscValidPointer(info, 4);
3041   PetscValidType(mat, 1);
3042   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3043   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3044   MatCheckPreallocated(mat, 1);
3045   if (!info) {
3046     PetscCall(MatFactorInfoInitialize(&tinfo));
3047     info = &tinfo;
3048   }
3049 
3050   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3051   PetscUseTypeMethod(mat, lufactor, row, col, info);
3052   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3053   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3054   PetscFunctionReturn(PETSC_SUCCESS);
3055 }
3056 
3057 /*@C
3058    MatILUFactor - Performs in-place ILU factorization of matrix.
3059 
3060    Collective
3061 
3062    Input Parameters:
3063 +  mat - the matrix
3064 .  row - row permutation
3065 .  col - column permutation
3066 -  info - structure containing
3067 .vb
3068       levels - number of levels of fill.
3069       expected fill - as ratio of original fill.
3070       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3071                 missing diagonal entries)
3072 .ve
3073 
3074    Level: developer
3075 
3076    Notes:
3077    Most users should employ the `KSP` interface for linear solvers
3078    instead of working directly with matrix algebra routines such as this.
3079    See, e.g., `KSPCreate()`.
3080 
3081    Probably really in-place only when level of fill is zero, otherwise allocates
3082    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3083    when not using `KSP`.
3084 
3085    Developer Note:
3086    The Fortran interface is not autogenerated as the
3087    interface definition cannot be generated correctly [due to MatFactorInfo]
3088 
3089 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3090 @*/
3091 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3092 {
3093   PetscFunctionBegin;
3094   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3095   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3096   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3097   PetscValidPointer(info, 4);
3098   PetscValidType(mat, 1);
3099   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3100   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3101   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3102   MatCheckPreallocated(mat, 1);
3103 
3104   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3105   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3106   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3107   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3108   PetscFunctionReturn(PETSC_SUCCESS);
3109 }
3110 
3111 /*@C
3112    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3113    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3114 
3115    Collective
3116 
3117    Input Parameters:
3118 +  fact - the factor matrix obtained with `MatGetFactor()`
3119 .  mat - the matrix
3120 .  row - the row permutation
3121 .  col - the column permutation
3122 -  info - options for factorization, includes
3123 .vb
3124           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3125           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3126 .ve
3127 
3128    Level: developer
3129 
3130    Notes:
3131     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3132 
3133    Most users should employ the simplified `KSP` interface for linear solvers
3134    instead of working directly with matrix algebra routines such as this.
3135    See, e.g., `KSPCreate()`.
3136 
3137    Developer Note:
3138    The Fortran interface is not autogenerated as the
3139    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3140 
3141 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3142 @*/
3143 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3144 {
3145   MatFactorInfo tinfo;
3146 
3147   PetscFunctionBegin;
3148   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3150   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3151   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3152   if (info) PetscValidPointer(info, 5);
3153   PetscValidType(fact, 1);
3154   PetscValidType(mat, 2);
3155   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3156   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3157   MatCheckPreallocated(mat, 2);
3158   if (!info) {
3159     PetscCall(MatFactorInfoInitialize(&tinfo));
3160     info = &tinfo;
3161   }
3162 
3163   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3164   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3165   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3166   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3167   PetscFunctionReturn(PETSC_SUCCESS);
3168 }
3169 
3170 /*@C
3171    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3172    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3173 
3174    Collective
3175 
3176    Input Parameters:
3177 +  fact - the factor matrix obtained with `MatGetFactor()`
3178 .  mat - the matrix
3179 -  info - options for factorization
3180 
3181    Level: developer
3182 
3183    Notes:
3184    See `MatLUFactor()` for in-place factorization.  See
3185    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3186 
3187    Most users should employ the `KSP` interface for linear solvers
3188    instead of working directly with matrix algebra routines such as this.
3189    See, e.g., `KSPCreate()`.
3190 
3191     Developer Note:
3192     The Fortran interface is not autogenerated as the
3193     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3194 
3195 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3196 @*/
3197 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3198 {
3199   MatFactorInfo tinfo;
3200 
3201   PetscFunctionBegin;
3202   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3204   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3205   PetscValidType(fact, 1);
3206   PetscValidType(mat, 2);
3207   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3208   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3209              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3210 
3211   MatCheckPreallocated(mat, 2);
3212   if (!info) {
3213     PetscCall(MatFactorInfoInitialize(&tinfo));
3214     info = &tinfo;
3215   }
3216 
3217   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3218   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3219   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3220   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3221   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3222   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3223   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3224   PetscFunctionReturn(PETSC_SUCCESS);
3225 }
3226 
3227 /*@C
3228    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3229    symmetric matrix.
3230 
3231    Collective
3232 
3233    Input Parameters:
3234 +  mat - the matrix
3235 .  perm - row and column permutations
3236 -  f - expected fill as ratio of original fill
3237 
3238    Level: developer
3239 
3240    Notes:
3241    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3242    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3243 
3244    Most users should employ the `KSP` interface for linear solvers
3245    instead of working directly with matrix algebra routines such as this.
3246    See, e.g., `KSPCreate()`.
3247 
3248    Developer Note:
3249    The Fortran interface is not autogenerated as the
3250    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3251 
3252 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3253           `MatGetOrdering()`
3254 @*/
3255 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3256 {
3257   MatFactorInfo tinfo;
3258 
3259   PetscFunctionBegin;
3260   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3261   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3262   if (info) PetscValidPointer(info, 3);
3263   PetscValidType(mat, 1);
3264   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3265   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3266   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3267   MatCheckPreallocated(mat, 1);
3268   if (!info) {
3269     PetscCall(MatFactorInfoInitialize(&tinfo));
3270     info = &tinfo;
3271   }
3272 
3273   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3274   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3275   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3276   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3277   PetscFunctionReturn(PETSC_SUCCESS);
3278 }
3279 
3280 /*@C
3281    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3282    of a symmetric matrix.
3283 
3284    Collective
3285 
3286    Input Parameters:
3287 +  fact - the factor matrix obtained with `MatGetFactor()`
3288 .  mat - the matrix
3289 .  perm - row and column permutations
3290 -  info - options for factorization, includes
3291 .vb
3292           fill - expected fill as ratio of original fill.
3293           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3294                    Run with the option -info to determine an optimal value to use
3295 .ve
3296 
3297    Level: developer
3298 
3299    Notes:
3300    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3301    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3302 
3303    Most users should employ the `KSP` interface for linear solvers
3304    instead of working directly with matrix algebra routines such as this.
3305    See, e.g., `KSPCreate()`.
3306 
3307    Developer Note:
3308    The Fortran interface is not autogenerated as the
3309    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3310 
3311 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3312           `MatGetOrdering()`
3313 @*/
3314 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3315 {
3316   MatFactorInfo tinfo;
3317 
3318   PetscFunctionBegin;
3319   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3321   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3322   if (info) PetscValidPointer(info, 4);
3323   PetscValidType(fact, 1);
3324   PetscValidType(mat, 2);
3325   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3326   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3327   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3328   MatCheckPreallocated(mat, 2);
3329   if (!info) {
3330     PetscCall(MatFactorInfoInitialize(&tinfo));
3331     info = &tinfo;
3332   }
3333 
3334   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3335   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3336   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3337   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3338   PetscFunctionReturn(PETSC_SUCCESS);
3339 }
3340 
3341 /*@C
3342    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3343    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3344    `MatCholeskyFactorSymbolic()`.
3345 
3346    Collective
3347 
3348    Input Parameters:
3349 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3350 .  mat - the initial matrix that is to be factored
3351 -  info - options for factorization
3352 
3353    Level: developer
3354 
3355    Note:
3356    Most users should employ the `KSP` interface for linear solvers
3357    instead of working directly with matrix algebra routines such as this.
3358    See, e.g., `KSPCreate()`.
3359 
3360    Developer Note:
3361    The Fortran interface is not autogenerated as the
3362    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3363 
3364 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3365 @*/
3366 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3367 {
3368   MatFactorInfo tinfo;
3369 
3370   PetscFunctionBegin;
3371   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3372   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3373   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3374   PetscValidType(fact, 1);
3375   PetscValidType(mat, 2);
3376   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3377   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3378              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3379   MatCheckPreallocated(mat, 2);
3380   if (!info) {
3381     PetscCall(MatFactorInfoInitialize(&tinfo));
3382     info = &tinfo;
3383   }
3384 
3385   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3386   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3387   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3388   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3389   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3390   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3391   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3392   PetscFunctionReturn(PETSC_SUCCESS);
3393 }
3394 
3395 /*@
3396    MatQRFactor - Performs in-place QR factorization of matrix.
3397 
3398    Collective
3399 
3400    Input Parameters:
3401 +  mat - the matrix
3402 .  col - column permutation
3403 -  info - options for factorization, includes
3404 .vb
3405           fill - expected fill as ratio of original fill.
3406           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3407                    Run with the option -info to determine an optimal value to use
3408 .ve
3409 
3410    Level: developer
3411 
3412    Notes:
3413    Most users should employ the `KSP` interface for linear solvers
3414    instead of working directly with matrix algebra routines such as this.
3415    See, e.g., `KSPCreate()`.
3416 
3417    This changes the state of the matrix to a factored matrix; it cannot be used
3418    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3419 
3420    Developer Note:
3421    The Fortran interface is not autogenerated as the
3422    interface definition cannot be generated correctly [due to MatFactorInfo]
3423 
3424 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3425           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3426 @*/
3427 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3428 {
3429   PetscFunctionBegin;
3430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3431   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3432   if (info) PetscValidPointer(info, 3);
3433   PetscValidType(mat, 1);
3434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3436   MatCheckPreallocated(mat, 1);
3437   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3438   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3439   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3440   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3441   PetscFunctionReturn(PETSC_SUCCESS);
3442 }
3443 
3444 /*@
3445    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3446    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3447 
3448    Collective
3449 
3450    Input Parameters:
3451 +  fact - the factor matrix obtained with `MatGetFactor()`
3452 .  mat - the matrix
3453 .  col - column permutation
3454 -  info - options for factorization, includes
3455 .vb
3456           fill - expected fill as ratio of original fill.
3457           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3458                    Run with the option -info to determine an optimal value to use
3459 .ve
3460 
3461    Level: developer
3462 
3463    Note:
3464    Most users should employ the `KSP` interface for linear solvers
3465    instead of working directly with matrix algebra routines such as this.
3466    See, e.g., `KSPCreate()`.
3467 
3468    Developer Note:
3469    The Fortran interface is not autogenerated as the
3470    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3471 
3472 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3473 @*/
3474 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3475 {
3476   MatFactorInfo tinfo;
3477 
3478   PetscFunctionBegin;
3479   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3480   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3481   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3482   if (info) PetscValidPointer(info, 4);
3483   PetscValidType(fact, 1);
3484   PetscValidType(mat, 2);
3485   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3486   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3487   MatCheckPreallocated(mat, 2);
3488   if (!info) {
3489     PetscCall(MatFactorInfoInitialize(&tinfo));
3490     info = &tinfo;
3491   }
3492 
3493   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3494   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3495   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3496   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3497   PetscFunctionReturn(PETSC_SUCCESS);
3498 }
3499 
3500 /*@
3501    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3502    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3503 
3504    Collective
3505 
3506    Input Parameters:
3507 +  fact - the factor matrix obtained with `MatGetFactor()`
3508 .  mat - the matrix
3509 -  info - options for factorization
3510 
3511    Level: developer
3512 
3513    Notes:
3514    See `MatQRFactor()` for in-place factorization.
3515 
3516    Most users should employ the `KSP` interface for linear solvers
3517    instead of working directly with matrix algebra routines such as this.
3518    See, e.g., `KSPCreate()`.
3519 
3520    Developer Note:
3521    The Fortran interface is not autogenerated as the
3522    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3523 
3524 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3525 @*/
3526 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3527 {
3528   MatFactorInfo tinfo;
3529 
3530   PetscFunctionBegin;
3531   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3533   PetscValidType(fact, 1);
3534   PetscValidType(mat, 2);
3535   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3536   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3537              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3538 
3539   MatCheckPreallocated(mat, 2);
3540   if (!info) {
3541     PetscCall(MatFactorInfoInitialize(&tinfo));
3542     info = &tinfo;
3543   }
3544 
3545   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3546   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3547   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3548   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3549   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3550   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3551   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3552   PetscFunctionReturn(PETSC_SUCCESS);
3553 }
3554 
3555 /*@
3556    MatSolve - Solves A x = b, given a factored matrix.
3557 
3558    Neighbor-wise Collective
3559 
3560    Input Parameters:
3561 +  mat - the factored matrix
3562 -  b - the right-hand-side vector
3563 
3564    Output Parameter:
3565 .  x - the result vector
3566 
3567    Level: developer
3568 
3569    Notes:
3570    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3571    call `MatSolve`(A,x,x).
3572 
3573    Most users should employ the `KSP` interface for linear solvers
3574    instead of working directly with matrix algebra routines such as this.
3575    See, e.g., `KSPCreate()`.
3576 
3577 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3578 @*/
3579 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3580 {
3581   PetscFunctionBegin;
3582   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3583   PetscValidType(mat, 1);
3584   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3585   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3586   PetscCheckSameComm(mat, 1, b, 2);
3587   PetscCheckSameComm(mat, 1, x, 3);
3588   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3589   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3590   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3591   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3592   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3593   MatCheckPreallocated(mat, 1);
3594 
3595   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3596   if (mat->factorerrortype) {
3597     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3598     PetscCall(VecSetInf(x));
3599   } else PetscUseTypeMethod(mat, solve, b, x);
3600   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3601   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3602   PetscFunctionReturn(PETSC_SUCCESS);
3603 }
3604 
3605 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3606 {
3607   Vec      b, x;
3608   PetscInt N, i;
3609   PetscErrorCode (*f)(Mat, Vec, Vec);
3610   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3611 
3612   PetscFunctionBegin;
3613   if (A->factorerrortype) {
3614     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3615     PetscCall(MatSetInf(X));
3616     PetscFunctionReturn(PETSC_SUCCESS);
3617   }
3618   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3619   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3620   PetscCall(MatBoundToCPU(A, &Abound));
3621   if (!Abound) {
3622     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3623     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3624   }
3625 #if PetscDefined(HAVE_CUDA)
3626   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3627   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3628 #elif PetscDefined(HAVE_HIP)
3629   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3630   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3631 #endif
3632   PetscCall(MatGetSize(B, NULL, &N));
3633   for (i = 0; i < N; i++) {
3634     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3635     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3636     PetscCall((*f)(A, b, x));
3637     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3638     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3639   }
3640   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3641   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3642   PetscFunctionReturn(PETSC_SUCCESS);
3643 }
3644 
3645 /*@
3646    MatMatSolve - Solves A X = B, given a factored matrix.
3647 
3648    Neighbor-wise Collective
3649 
3650    Input Parameters:
3651 +  A - the factored matrix
3652 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3653 
3654    Output Parameter:
3655 .  X - the result matrix (dense matrix)
3656 
3657    Level: developer
3658 
3659    Note:
3660    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3661    otherwise, `B` and `X` cannot be the same.
3662 
3663 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3664 @*/
3665 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3666 {
3667   PetscFunctionBegin;
3668   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3669   PetscValidType(A, 1);
3670   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3671   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3672   PetscCheckSameComm(A, 1, B, 2);
3673   PetscCheckSameComm(A, 1, X, 3);
3674   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3675   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3676   PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3677   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3678   MatCheckPreallocated(A, 1);
3679 
3680   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3681   if (!A->ops->matsolve) {
3682     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3683     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3684   } else PetscUseTypeMethod(A, matsolve, B, X);
3685   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3686   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3687   PetscFunctionReturn(PETSC_SUCCESS);
3688 }
3689 
3690 /*@
3691    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3692 
3693    Neighbor-wise Collective
3694 
3695    Input Parameters:
3696 +  A - the factored matrix
3697 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3698 
3699    Output Parameter:
3700 .  X - the result matrix (dense matrix)
3701 
3702    Level: developer
3703 
3704    Note:
3705    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3706    call `MatMatSolveTranspose`(A,X,X).
3707 
3708 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3709 @*/
3710 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3711 {
3712   PetscFunctionBegin;
3713   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3714   PetscValidType(A, 1);
3715   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3716   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3717   PetscCheckSameComm(A, 1, B, 2);
3718   PetscCheckSameComm(A, 1, X, 3);
3719   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3720   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3721   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3722   PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n);
3723   PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3724   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3725   MatCheckPreallocated(A, 1);
3726 
3727   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3728   if (!A->ops->matsolvetranspose) {
3729     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3730     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3731   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3732   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3733   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3734   PetscFunctionReturn(PETSC_SUCCESS);
3735 }
3736 
3737 /*@
3738    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3739 
3740    Neighbor-wise Collective
3741 
3742    Input Parameters:
3743 +  A - the factored matrix
3744 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3745 
3746    Output Parameter:
3747 .  X - the result matrix (dense matrix)
3748 
3749    Level: developer
3750 
3751    Note:
3752    For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row
3753    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3754 
3755 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3756 @*/
3757 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3758 {
3759   PetscFunctionBegin;
3760   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3761   PetscValidType(A, 1);
3762   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3763   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3764   PetscCheckSameComm(A, 1, Bt, 2);
3765   PetscCheckSameComm(A, 1, X, 3);
3766 
3767   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3768   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3769   PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N);
3770   PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix");
3771   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3772   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3773   MatCheckPreallocated(A, 1);
3774 
3775   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3776   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3777   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3778   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3779   PetscFunctionReturn(PETSC_SUCCESS);
3780 }
3781 
3782 /*@
3783    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3784                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3785 
3786    Neighbor-wise Collective
3787 
3788    Input Parameters:
3789 +  mat - the factored matrix
3790 -  b - the right-hand-side vector
3791 
3792    Output Parameter:
3793 .  x - the result vector
3794 
3795    Level: developer
3796 
3797    Notes:
3798    `MatSolve()` should be used for most applications, as it performs
3799    a forward solve followed by a backward solve.
3800 
3801    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3802    call `MatForwardSolve`(A,x,x).
3803 
3804    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3805    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3806    `MatForwardSolve()` solves U^T*D y = b, and
3807    `MatBackwardSolve()` solves U x = y.
3808    Thus they do not provide a symmetric preconditioner.
3809 
3810 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3811 @*/
3812 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3813 {
3814   PetscFunctionBegin;
3815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3816   PetscValidType(mat, 1);
3817   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3818   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3819   PetscCheckSameComm(mat, 1, b, 2);
3820   PetscCheckSameComm(mat, 1, x, 3);
3821   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3822   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3823   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3824   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3825   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3826   MatCheckPreallocated(mat, 1);
3827 
3828   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3829   PetscUseTypeMethod(mat, forwardsolve, b, x);
3830   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3831   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3832   PetscFunctionReturn(PETSC_SUCCESS);
3833 }
3834 
3835 /*@
3836    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3837                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3838 
3839    Neighbor-wise Collective
3840 
3841    Input Parameters:
3842 +  mat - the factored matrix
3843 -  b - the right-hand-side vector
3844 
3845    Output Parameter:
3846 .  x - the result vector
3847 
3848    Level: developer
3849 
3850    Notes:
3851    `MatSolve()` should be used for most applications, as it performs
3852    a forward solve followed by a backward solve.
3853 
3854    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3855    call `MatBackwardSolve`(A,x,x).
3856 
3857    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3858    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3859    `MatForwardSolve()` solves U^T*D y = b, and
3860    `MatBackwardSolve()` solves U x = y.
3861    Thus they do not provide a symmetric preconditioner.
3862 
3863 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3864 @*/
3865 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3866 {
3867   PetscFunctionBegin;
3868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3869   PetscValidType(mat, 1);
3870   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3871   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3872   PetscCheckSameComm(mat, 1, b, 2);
3873   PetscCheckSameComm(mat, 1, x, 3);
3874   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3875   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3876   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3877   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3878   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3879   MatCheckPreallocated(mat, 1);
3880 
3881   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3882   PetscUseTypeMethod(mat, backwardsolve, b, x);
3883   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3884   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3885   PetscFunctionReturn(PETSC_SUCCESS);
3886 }
3887 
3888 /*@
3889    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3890 
3891    Neighbor-wise Collective
3892 
3893    Input Parameters:
3894 +  mat - the factored matrix
3895 .  b - the right-hand-side vector
3896 -  y - the vector to be added to
3897 
3898    Output Parameter:
3899 .  x - the result vector
3900 
3901    Level: developer
3902 
3903    Note:
3904    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3905    call `MatSolveAdd`(A,x,y,x).
3906 
3907 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3908 @*/
3909 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3910 {
3911   PetscScalar one = 1.0;
3912   Vec         tmp;
3913 
3914   PetscFunctionBegin;
3915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3916   PetscValidType(mat, 1);
3917   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3918   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3919   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3920   PetscCheckSameComm(mat, 1, b, 2);
3921   PetscCheckSameComm(mat, 1, y, 3);
3922   PetscCheckSameComm(mat, 1, x, 4);
3923   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3924   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3925   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3926   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
3927   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3928   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
3929   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3930   MatCheckPreallocated(mat, 1);
3931 
3932   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3933   if (mat->factorerrortype) {
3934     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3935     PetscCall(VecSetInf(x));
3936   } else if (mat->ops->solveadd) {
3937     PetscUseTypeMethod(mat, solveadd, b, y, x);
3938   } else {
3939     /* do the solve then the add manually */
3940     if (x != y) {
3941       PetscCall(MatSolve(mat, b, x));
3942       PetscCall(VecAXPY(x, one, y));
3943     } else {
3944       PetscCall(VecDuplicate(x, &tmp));
3945       PetscCall(VecCopy(x, tmp));
3946       PetscCall(MatSolve(mat, b, x));
3947       PetscCall(VecAXPY(x, one, tmp));
3948       PetscCall(VecDestroy(&tmp));
3949     }
3950   }
3951   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3952   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3953   PetscFunctionReturn(PETSC_SUCCESS);
3954 }
3955 
3956 /*@
3957    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3958 
3959    Neighbor-wise Collective
3960 
3961    Input Parameters:
3962 +  mat - the factored matrix
3963 -  b - the right-hand-side vector
3964 
3965    Output Parameter:
3966 .  x - the result vector
3967 
3968    Level: developer
3969 
3970    Notes:
3971    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3972    call `MatSolveTranspose`(A,x,x).
3973 
3974    Most users should employ the `KSP` interface for linear solvers
3975    instead of working directly with matrix algebra routines such as this.
3976    See, e.g., `KSPCreate()`.
3977 
3978 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3979 @*/
3980 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3981 {
3982   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3983 
3984   PetscFunctionBegin;
3985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3986   PetscValidType(mat, 1);
3987   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3988   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3989   PetscCheckSameComm(mat, 1, b, 2);
3990   PetscCheckSameComm(mat, 1, x, 3);
3991   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3992   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
3993   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
3994   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3995   MatCheckPreallocated(mat, 1);
3996   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3997   if (mat->factorerrortype) {
3998     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3999     PetscCall(VecSetInf(x));
4000   } else {
4001     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4002     PetscCall((*f)(mat, b, x));
4003   }
4004   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4005   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4006   PetscFunctionReturn(PETSC_SUCCESS);
4007 }
4008 
4009 /*@
4010    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4011                       factored matrix.
4012 
4013    Neighbor-wise Collective
4014 
4015    Input Parameters:
4016 +  mat - the factored matrix
4017 .  b - the right-hand-side vector
4018 -  y - the vector to be added to
4019 
4020    Output Parameter:
4021 .  x - the result vector
4022 
4023    Level: developer
4024 
4025    Note:
4026    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4027    call `MatSolveTransposeAdd`(A,x,y,x).
4028 
4029 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4030 @*/
4031 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4032 {
4033   PetscScalar one = 1.0;
4034   Vec         tmp;
4035   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4036 
4037   PetscFunctionBegin;
4038   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4039   PetscValidType(mat, 1);
4040   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4041   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4042   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4043   PetscCheckSameComm(mat, 1, b, 2);
4044   PetscCheckSameComm(mat, 1, y, 3);
4045   PetscCheckSameComm(mat, 1, x, 4);
4046   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4047   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4048   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4049   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
4050   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
4051   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4052   MatCheckPreallocated(mat, 1);
4053 
4054   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4055   if (mat->factorerrortype) {
4056     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4057     PetscCall(VecSetInf(x));
4058   } else if (f) {
4059     PetscCall((*f)(mat, b, y, x));
4060   } else {
4061     /* do the solve then the add manually */
4062     if (x != y) {
4063       PetscCall(MatSolveTranspose(mat, b, x));
4064       PetscCall(VecAXPY(x, one, y));
4065     } else {
4066       PetscCall(VecDuplicate(x, &tmp));
4067       PetscCall(VecCopy(x, tmp));
4068       PetscCall(MatSolveTranspose(mat, b, x));
4069       PetscCall(VecAXPY(x, one, tmp));
4070       PetscCall(VecDestroy(&tmp));
4071     }
4072   }
4073   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4074   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4075   PetscFunctionReturn(PETSC_SUCCESS);
4076 }
4077 
4078 /*@
4079    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4080 
4081    Neighbor-wise Collective
4082 
4083    Input Parameters:
4084 +  mat - the matrix
4085 .  b - the right hand side
4086 .  omega - the relaxation factor
4087 .  flag - flag indicating the type of SOR (see below)
4088 .  shift -  diagonal shift
4089 .  its - the number of iterations
4090 -  lits - the number of local iterations
4091 
4092    Output Parameter:
4093 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4094 
4095    SOR Flags:
4096 +     `SOR_FORWARD_SWEEP` - forward SOR
4097 .     `SOR_BACKWARD_SWEEP` - backward SOR
4098 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4099 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4100 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4101 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4102 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4103 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4104          upper/lower triangular part of matrix to
4105          vector (with omega)
4106 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4107 
4108    Level: developer
4109 
4110    Notes:
4111    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4112    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4113    on each processor.
4114 
4115    Application programmers will not generally use `MatSOR()` directly,
4116    but instead will employ the `KSP`/`PC` interface.
4117 
4118    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4119 
4120    Most users should employ the `KSP` interface for linear solvers
4121    instead of working directly with matrix algebra routines such as this.
4122    See, e.g., `KSPCreate()`.
4123 
4124    Vectors `x` and `b` CANNOT be the same
4125 
4126    The flags are implemented as bitwise inclusive or operations.
4127    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4128    to specify a zero initial guess for SSOR.
4129 
4130    Developer Note:
4131    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4132 
4133 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4134 @*/
4135 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4136 {
4137   PetscFunctionBegin;
4138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4139   PetscValidType(mat, 1);
4140   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4141   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4142   PetscCheckSameComm(mat, 1, b, 2);
4143   PetscCheckSameComm(mat, 1, x, 8);
4144   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4145   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4146   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
4147   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
4148   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
4149   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4150   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4151   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4152 
4153   MatCheckPreallocated(mat, 1);
4154   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4155   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4156   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4157   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4158   PetscFunctionReturn(PETSC_SUCCESS);
4159 }
4160 
4161 /*
4162       Default matrix copy routine.
4163 */
4164 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4165 {
4166   PetscInt           i, rstart = 0, rend = 0, nz;
4167   const PetscInt    *cwork;
4168   const PetscScalar *vwork;
4169 
4170   PetscFunctionBegin;
4171   if (B->assembled) PetscCall(MatZeroEntries(B));
4172   if (str == SAME_NONZERO_PATTERN) {
4173     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4174     for (i = rstart; i < rend; i++) {
4175       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4176       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4177       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4178     }
4179   } else {
4180     PetscCall(MatAYPX(B, 0.0, A, str));
4181   }
4182   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4183   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4184   PetscFunctionReturn(PETSC_SUCCESS);
4185 }
4186 
4187 /*@
4188    MatCopy - Copies a matrix to another matrix.
4189 
4190    Collective
4191 
4192    Input Parameters:
4193 +  A - the matrix
4194 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4195 
4196    Output Parameter:
4197 .  B - where the copy is put
4198 
4199    Level: intermediate
4200 
4201    Notes:
4202    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4203 
4204    `MatCopy()` copies the matrix entries of a matrix to another existing
4205    matrix (after first zeroing the second matrix).  A related routine is
4206    `MatConvert()`, which first creates a new matrix and then copies the data.
4207 
4208 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4209 @*/
4210 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4211 {
4212   PetscInt i;
4213 
4214   PetscFunctionBegin;
4215   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4216   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4217   PetscValidType(A, 1);
4218   PetscValidType(B, 2);
4219   PetscCheckSameComm(A, 1, B, 2);
4220   MatCheckPreallocated(B, 2);
4221   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4222   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4223   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N,
4224              A->cmap->N, B->cmap->N);
4225   MatCheckPreallocated(A, 1);
4226   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4227 
4228   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4229   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4230   else PetscCall(MatCopy_Basic(A, B, str));
4231 
4232   B->stencil.dim = A->stencil.dim;
4233   B->stencil.noc = A->stencil.noc;
4234   for (i = 0; i <= A->stencil.dim; i++) {
4235     B->stencil.dims[i]   = A->stencil.dims[i];
4236     B->stencil.starts[i] = A->stencil.starts[i];
4237   }
4238 
4239   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4240   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4241   PetscFunctionReturn(PETSC_SUCCESS);
4242 }
4243 
4244 /*@C
4245    MatConvert - Converts a matrix to another matrix, either of the same
4246    or different type.
4247 
4248    Collective
4249 
4250    Input Parameters:
4251 +  mat - the matrix
4252 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4253    same type as the original matrix.
4254 -  reuse - denotes if the destination matrix is to be created or reused.
4255    Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use
4256    `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused).
4257 
4258    Output Parameter:
4259 .  M - pointer to place new matrix
4260 
4261    Level: intermediate
4262 
4263    Notes:
4264    `MatConvert()` first creates a new matrix and then copies the data from
4265    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4266    entries of one matrix to another already existing matrix context.
4267 
4268    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4269    the MPI communicator of the generated matrix is always the same as the communicator
4270    of the input matrix.
4271 
4272 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4273 @*/
4274 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4275 {
4276   PetscBool  sametype, issame, flg;
4277   PetscBool3 issymmetric, ishermitian;
4278   char       convname[256], mtype[256];
4279   Mat        B;
4280 
4281   PetscFunctionBegin;
4282   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4283   PetscValidType(mat, 1);
4284   PetscValidPointer(M, 4);
4285   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4286   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4287   MatCheckPreallocated(mat, 1);
4288 
4289   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4290   if (flg) newtype = mtype;
4291 
4292   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4293   PetscCall(PetscStrcmp(newtype, "same", &issame));
4294   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4295   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4296 
4297   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4298     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4299     PetscFunctionReturn(PETSC_SUCCESS);
4300   }
4301 
4302   /* Cache Mat options because some converters use MatHeaderReplace  */
4303   issymmetric = mat->symmetric;
4304   ishermitian = mat->hermitian;
4305 
4306   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4307     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4308     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4309   } else {
4310     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4311     const char *prefix[3]                                 = {"seq", "mpi", ""};
4312     PetscInt    i;
4313     /*
4314        Order of precedence:
4315        0) See if newtype is a superclass of the current matrix.
4316        1) See if a specialized converter is known to the current matrix.
4317        2) See if a specialized converter is known to the desired matrix class.
4318        3) See if a good general converter is registered for the desired class
4319           (as of 6/27/03 only MATMPIADJ falls into this category).
4320        4) See if a good general converter is known for the current matrix.
4321        5) Use a really basic converter.
4322     */
4323 
4324     /* 0) See if newtype is a superclass of the current matrix.
4325           i.e mat is mpiaij and newtype is aij */
4326     for (i = 0; i < 2; i++) {
4327       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4328       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4329       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4330       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4331       if (flg) {
4332         if (reuse == MAT_INPLACE_MATRIX) {
4333           PetscCall(PetscInfo(mat, "Early return\n"));
4334           PetscFunctionReturn(PETSC_SUCCESS);
4335         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4336           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4337           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4338           PetscFunctionReturn(PETSC_SUCCESS);
4339         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4340           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4341           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4342           PetscFunctionReturn(PETSC_SUCCESS);
4343         }
4344       }
4345     }
4346     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4347     for (i = 0; i < 3; i++) {
4348       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4349       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4350       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4351       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4353       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4354       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4355       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4356       if (conv) goto foundconv;
4357     }
4358 
4359     /* 2)  See if a specialized converter is known to the desired matrix class. */
4360     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4361     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4362     PetscCall(MatSetType(B, newtype));
4363     for (i = 0; i < 3; i++) {
4364       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4367       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4368       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4369       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4370       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4371       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4372       if (conv) {
4373         PetscCall(MatDestroy(&B));
4374         goto foundconv;
4375       }
4376     }
4377 
4378     /* 3) See if a good general converter is registered for the desired class */
4379     conv = B->ops->convertfrom;
4380     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4381     PetscCall(MatDestroy(&B));
4382     if (conv) goto foundconv;
4383 
4384     /* 4) See if a good general converter is known for the current matrix */
4385     if (mat->ops->convert) conv = mat->ops->convert;
4386     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4387     if (conv) goto foundconv;
4388 
4389     /* 5) Use a really basic converter. */
4390     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4391     conv = MatConvert_Basic;
4392 
4393   foundconv:
4394     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4395     PetscCall((*conv)(mat, newtype, reuse, M));
4396     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4397       /* the block sizes must be same if the mappings are copied over */
4398       (*M)->rmap->bs = mat->rmap->bs;
4399       (*M)->cmap->bs = mat->cmap->bs;
4400       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4401       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4402       (*M)->rmap->mapping = mat->rmap->mapping;
4403       (*M)->cmap->mapping = mat->cmap->mapping;
4404     }
4405     (*M)->stencil.dim = mat->stencil.dim;
4406     (*M)->stencil.noc = mat->stencil.noc;
4407     for (i = 0; i <= mat->stencil.dim; i++) {
4408       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4409       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4410     }
4411     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4412   }
4413   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4414 
4415   /* Copy Mat options */
4416   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4417   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4418   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4419   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4420   PetscFunctionReturn(PETSC_SUCCESS);
4421 }
4422 
4423 /*@C
4424    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4425 
4426    Not Collective
4427 
4428    Input Parameter:
4429 .  mat - the matrix, must be a factored matrix
4430 
4431    Output Parameter:
4432 .   type - the string name of the package (do not free this string)
4433 
4434    Level: intermediate
4435 
4436    Fortran Note:
4437    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4438 
4439 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4440 @*/
4441 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4442 {
4443   PetscErrorCode (*conv)(Mat, MatSolverType *);
4444 
4445   PetscFunctionBegin;
4446   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4447   PetscValidType(mat, 1);
4448   PetscValidPointer(type, 2);
4449   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4450   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4451   if (conv) PetscCall((*conv)(mat, type));
4452   else *type = MATSOLVERPETSC;
4453   PetscFunctionReturn(PETSC_SUCCESS);
4454 }
4455 
4456 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4457 struct _MatSolverTypeForSpecifcType {
4458   MatType mtype;
4459   /* no entry for MAT_FACTOR_NONE */
4460   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4461   MatSolverTypeForSpecifcType next;
4462 };
4463 
4464 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4465 struct _MatSolverTypeHolder {
4466   char                       *name;
4467   MatSolverTypeForSpecifcType handlers;
4468   MatSolverTypeHolder         next;
4469 };
4470 
4471 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4472 
4473 /*@C
4474    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4475 
4476    Input Parameters:
4477 +    package - name of the package, for example petsc or superlu
4478 .    mtype - the matrix type that works with this package
4479 .    ftype - the type of factorization supported by the package
4480 -    createfactor - routine that will create the factored matrix ready to be used
4481 
4482     Level: developer
4483 
4484 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4485 @*/
4486 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4487 {
4488   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4489   PetscBool                   flg;
4490   MatSolverTypeForSpecifcType inext, iprev = NULL;
4491 
4492   PetscFunctionBegin;
4493   PetscCall(MatInitializePackage());
4494   if (!next) {
4495     PetscCall(PetscNew(&MatSolverTypeHolders));
4496     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4497     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4498     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4499     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4500     PetscFunctionReturn(PETSC_SUCCESS);
4501   }
4502   while (next) {
4503     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4504     if (flg) {
4505       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4506       inext = next->handlers;
4507       while (inext) {
4508         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4509         if (flg) {
4510           inext->createfactor[(int)ftype - 1] = createfactor;
4511           PetscFunctionReturn(PETSC_SUCCESS);
4512         }
4513         iprev = inext;
4514         inext = inext->next;
4515       }
4516       PetscCall(PetscNew(&iprev->next));
4517       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4518       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4519       PetscFunctionReturn(PETSC_SUCCESS);
4520     }
4521     prev = next;
4522     next = next->next;
4523   }
4524   PetscCall(PetscNew(&prev->next));
4525   PetscCall(PetscStrallocpy(package, &prev->next->name));
4526   PetscCall(PetscNew(&prev->next->handlers));
4527   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4528   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4529   PetscFunctionReturn(PETSC_SUCCESS);
4530 }
4531 
4532 /*@C
4533    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4534 
4535    Input Parameters:
4536 +    type - name of the package, for example petsc or superlu
4537 .    ftype - the type of factorization supported by the type
4538 -    mtype - the matrix type that works with this type
4539 
4540    Output Parameters:
4541 +   foundtype - `PETSC_TRUE` if the type was registered
4542 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4543 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4544 
4545     Level: developer
4546 
4547 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4548 @*/
4549 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4550 {
4551   MatSolverTypeHolder         next = MatSolverTypeHolders;
4552   PetscBool                   flg;
4553   MatSolverTypeForSpecifcType inext;
4554 
4555   PetscFunctionBegin;
4556   if (foundtype) *foundtype = PETSC_FALSE;
4557   if (foundmtype) *foundmtype = PETSC_FALSE;
4558   if (createfactor) *createfactor = NULL;
4559 
4560   if (type) {
4561     while (next) {
4562       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4563       if (flg) {
4564         if (foundtype) *foundtype = PETSC_TRUE;
4565         inext = next->handlers;
4566         while (inext) {
4567           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4568           if (flg) {
4569             if (foundmtype) *foundmtype = PETSC_TRUE;
4570             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4571             PetscFunctionReturn(PETSC_SUCCESS);
4572           }
4573           inext = inext->next;
4574         }
4575       }
4576       next = next->next;
4577     }
4578   } else {
4579     while (next) {
4580       inext = next->handlers;
4581       while (inext) {
4582         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4583         if (flg && inext->createfactor[(int)ftype - 1]) {
4584           if (foundtype) *foundtype = PETSC_TRUE;
4585           if (foundmtype) *foundmtype = PETSC_TRUE;
4586           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4587           PetscFunctionReturn(PETSC_SUCCESS);
4588         }
4589         inext = inext->next;
4590       }
4591       next = next->next;
4592     }
4593     /* try with base classes inext->mtype */
4594     next = MatSolverTypeHolders;
4595     while (next) {
4596       inext = next->handlers;
4597       while (inext) {
4598         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4599         if (flg && inext->createfactor[(int)ftype - 1]) {
4600           if (foundtype) *foundtype = PETSC_TRUE;
4601           if (foundmtype) *foundmtype = PETSC_TRUE;
4602           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4603           PetscFunctionReturn(PETSC_SUCCESS);
4604         }
4605         inext = inext->next;
4606       }
4607       next = next->next;
4608     }
4609   }
4610   PetscFunctionReturn(PETSC_SUCCESS);
4611 }
4612 
4613 PetscErrorCode MatSolverTypeDestroy(void)
4614 {
4615   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4616   MatSolverTypeForSpecifcType inext, iprev;
4617 
4618   PetscFunctionBegin;
4619   while (next) {
4620     PetscCall(PetscFree(next->name));
4621     inext = next->handlers;
4622     while (inext) {
4623       PetscCall(PetscFree(inext->mtype));
4624       iprev = inext;
4625       inext = inext->next;
4626       PetscCall(PetscFree(iprev));
4627     }
4628     prev = next;
4629     next = next->next;
4630     PetscCall(PetscFree(prev));
4631   }
4632   MatSolverTypeHolders = NULL;
4633   PetscFunctionReturn(PETSC_SUCCESS);
4634 }
4635 
4636 /*@C
4637    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4638 
4639    Logically Collective
4640 
4641    Input Parameter:
4642 .  mat - the matrix
4643 
4644    Output Parameter:
4645 .  flg - `PETSC_TRUE` if uses the ordering
4646 
4647    Level: developer
4648 
4649    Note:
4650    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4651    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4652 
4653 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4654 @*/
4655 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4656 {
4657   PetscFunctionBegin;
4658   *flg = mat->canuseordering;
4659   PetscFunctionReturn(PETSC_SUCCESS);
4660 }
4661 
4662 /*@C
4663    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4664 
4665    Logically Collective
4666 
4667    Input Parameters:
4668 +  mat - the matrix obtained with `MatGetFactor()`
4669 -  ftype - the factorization type to be used
4670 
4671    Output Parameter:
4672 .  otype - the preferred ordering type
4673 
4674    Level: developer
4675 
4676 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4677 @*/
4678 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4679 {
4680   PetscFunctionBegin;
4681   *otype = mat->preferredordering[ftype];
4682   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4683   PetscFunctionReturn(PETSC_SUCCESS);
4684 }
4685 
4686 /*@C
4687    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4688 
4689    Collective
4690 
4691    Input Parameters:
4692 +  mat - the matrix
4693 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4694 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4695 
4696    Output Parameter:
4697 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4698 
4699    Options Database Key:
4700 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4701                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4702 
4703    Level: intermediate
4704 
4705    Notes:
4706      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4707      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4708 
4709      Users usually access the factorization solvers via `KSP`
4710 
4711       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4712      such as pastix, superlu, mumps etc.
4713 
4714       PETSc must have been ./configure to use the external solver, using the option --download-package
4715 
4716       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4717       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4718       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4719 
4720    Developer Note:
4721       This should actually be called `MatCreateFactor()` since it creates a new factor object
4722 
4723 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4724           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4725 @*/
4726 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4727 {
4728   PetscBool foundtype, foundmtype;
4729   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4730 
4731   PetscFunctionBegin;
4732   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4733   PetscValidType(mat, 1);
4734 
4735   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4736   MatCheckPreallocated(mat, 1);
4737 
4738   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4739   if (!foundtype) {
4740     if (type) {
4741       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype],
4742               ((PetscObject)mat)->type_name, type);
4743     } else {
4744       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4745     }
4746   }
4747   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4748   PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4749 
4750   PetscCall((*conv)(mat, ftype, f));
4751   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4752   PetscFunctionReturn(PETSC_SUCCESS);
4753 }
4754 
4755 /*@C
4756    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4757 
4758    Not Collective
4759 
4760    Input Parameters:
4761 +  mat - the matrix
4762 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4763 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4764 
4765    Output Parameter:
4766 .    flg - PETSC_TRUE if the factorization is available
4767 
4768    Level: intermediate
4769 
4770    Notes:
4771       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4772      such as pastix, superlu, mumps etc.
4773 
4774       PETSc must have been ./configure to use the external solver, using the option --download-package
4775 
4776    Developer Note:
4777       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4778 
4779 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4780           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4781 @*/
4782 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4783 {
4784   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4785 
4786   PetscFunctionBegin;
4787   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4788   PetscValidType(mat, 1);
4789   PetscValidBoolPointer(flg, 4);
4790 
4791   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4792   MatCheckPreallocated(mat, 1);
4793 
4794   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4795   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4796   PetscFunctionReturn(PETSC_SUCCESS);
4797 }
4798 
4799 /*@
4800    MatDuplicate - Duplicates a matrix including the non-zero structure.
4801 
4802    Collective
4803 
4804    Input Parameters:
4805 +  mat - the matrix
4806 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4807         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4808 
4809    Output Parameter:
4810 .  M - pointer to place new matrix
4811 
4812    Level: intermediate
4813 
4814    Notes:
4815     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4816 
4817     May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well.
4818 
4819     When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat
4820     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4821     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4822 
4823 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4824 @*/
4825 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4826 {
4827   Mat         B;
4828   VecType     vtype;
4829   PetscInt    i;
4830   PetscObject dm, container_h, container_d;
4831   void (*viewf)(void);
4832 
4833   PetscFunctionBegin;
4834   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4835   PetscValidType(mat, 1);
4836   PetscValidPointer(M, 3);
4837   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4838   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4839   MatCheckPreallocated(mat, 1);
4840 
4841   *M = NULL;
4842   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4843   PetscUseTypeMethod(mat, duplicate, op, M);
4844   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4845   B = *M;
4846 
4847   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4848   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4849   PetscCall(MatGetVecType(mat, &vtype));
4850   PetscCall(MatSetVecType(B, vtype));
4851 
4852   B->stencil.dim = mat->stencil.dim;
4853   B->stencil.noc = mat->stencil.noc;
4854   for (i = 0; i <= mat->stencil.dim; i++) {
4855     B->stencil.dims[i]   = mat->stencil.dims[i];
4856     B->stencil.starts[i] = mat->stencil.starts[i];
4857   }
4858 
4859   B->nooffproczerorows = mat->nooffproczerorows;
4860   B->nooffprocentries  = mat->nooffprocentries;
4861 
4862   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4863   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4864   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4865   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4866   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4867   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4868   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4869   PetscFunctionReturn(PETSC_SUCCESS);
4870 }
4871 
4872 /*@
4873    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4874 
4875    Logically Collective
4876 
4877    Input Parameter:
4878 .  mat - the matrix
4879 
4880    Output Parameter:
4881 .  v - the diagonal of the matrix
4882 
4883    Level: intermediate
4884 
4885    Note:
4886    Currently only correct in parallel for square matrices.
4887 
4888 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4889 @*/
4890 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4891 {
4892   PetscFunctionBegin;
4893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4894   PetscValidType(mat, 1);
4895   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4896   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4897   MatCheckPreallocated(mat, 1);
4898 
4899   PetscUseTypeMethod(mat, getdiagonal, v);
4900   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4901   PetscFunctionReturn(PETSC_SUCCESS);
4902 }
4903 
4904 /*@C
4905    MatGetRowMin - Gets the minimum value (of the real part) of each
4906         row of the matrix
4907 
4908    Logically Collective
4909 
4910    Input Parameter:
4911 .  mat - the matrix
4912 
4913    Output Parameters:
4914 +  v - the vector for storing the maximums
4915 -  idx - the indices of the column found for each row (optional)
4916 
4917    Level: intermediate
4918 
4919    Note:
4920     The result of this call are the same as if one converted the matrix to dense format
4921       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4922 
4923     This code is only implemented for a couple of matrix formats.
4924 
4925 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4926           `MatGetRowMax()`
4927 @*/
4928 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4929 {
4930   PetscFunctionBegin;
4931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4932   PetscValidType(mat, 1);
4933   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4934   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4935 
4936   if (!mat->cmap->N) {
4937     PetscCall(VecSet(v, PETSC_MAX_REAL));
4938     if (idx) {
4939       PetscInt i, m = mat->rmap->n;
4940       for (i = 0; i < m; i++) idx[i] = -1;
4941     }
4942   } else {
4943     MatCheckPreallocated(mat, 1);
4944   }
4945   PetscUseTypeMethod(mat, getrowmin, v, idx);
4946   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4947   PetscFunctionReturn(PETSC_SUCCESS);
4948 }
4949 
4950 /*@C
4951    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4952         row of the matrix
4953 
4954    Logically Collective
4955 
4956    Input Parameter:
4957 .  mat - the matrix
4958 
4959    Output Parameters:
4960 +  v - the vector for storing the minimums
4961 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4962 
4963    Level: intermediate
4964 
4965    Notes:
4966     if a row is completely empty or has only 0.0 values then the idx[] value for that
4967     row is 0 (the first column).
4968 
4969     This code is only implemented for a couple of matrix formats.
4970 
4971 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4972 @*/
4973 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4974 {
4975   PetscFunctionBegin;
4976   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4977   PetscValidType(mat, 1);
4978   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4979   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4980   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4981 
4982   if (!mat->cmap->N) {
4983     PetscCall(VecSet(v, 0.0));
4984     if (idx) {
4985       PetscInt i, m = mat->rmap->n;
4986       for (i = 0; i < m; i++) idx[i] = -1;
4987     }
4988   } else {
4989     MatCheckPreallocated(mat, 1);
4990     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4991     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4992   }
4993   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4994   PetscFunctionReturn(PETSC_SUCCESS);
4995 }
4996 
4997 /*@C
4998    MatGetRowMax - Gets the maximum value (of the real part) of each
4999         row of the matrix
5000 
5001    Logically Collective
5002 
5003    Input Parameter:
5004 .  mat - the matrix
5005 
5006    Output Parameters:
5007 +  v - the vector for storing the maximums
5008 -  idx - the indices of the column found for each row (optional)
5009 
5010    Level: intermediate
5011 
5012    Notes:
5013     The result of this call are the same as if one converted the matrix to dense format
5014       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5015 
5016     This code is only implemented for a couple of matrix formats.
5017 
5018 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5019 @*/
5020 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5021 {
5022   PetscFunctionBegin;
5023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5024   PetscValidType(mat, 1);
5025   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5026   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5027 
5028   if (!mat->cmap->N) {
5029     PetscCall(VecSet(v, PETSC_MIN_REAL));
5030     if (idx) {
5031       PetscInt i, m = mat->rmap->n;
5032       for (i = 0; i < m; i++) idx[i] = -1;
5033     }
5034   } else {
5035     MatCheckPreallocated(mat, 1);
5036     PetscUseTypeMethod(mat, getrowmax, v, idx);
5037   }
5038   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5039   PetscFunctionReturn(PETSC_SUCCESS);
5040 }
5041 
5042 /*@C
5043    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5044         row of the matrix
5045 
5046    Logically Collective
5047 
5048    Input Parameter:
5049 .  mat - the matrix
5050 
5051    Output Parameters:
5052 +  v - the vector for storing the maximums
5053 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5054 
5055    Level: intermediate
5056 
5057    Notes:
5058     if a row is completely empty or has only 0.0 values then the idx[] value for that
5059     row is 0 (the first column).
5060 
5061     This code is only implemented for a couple of matrix formats.
5062 
5063 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5064 @*/
5065 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5066 {
5067   PetscFunctionBegin;
5068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5069   PetscValidType(mat, 1);
5070   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5071   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5072 
5073   if (!mat->cmap->N) {
5074     PetscCall(VecSet(v, 0.0));
5075     if (idx) {
5076       PetscInt i, m = mat->rmap->n;
5077       for (i = 0; i < m; i++) idx[i] = -1;
5078     }
5079   } else {
5080     MatCheckPreallocated(mat, 1);
5081     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5082     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5083   }
5084   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5085   PetscFunctionReturn(PETSC_SUCCESS);
5086 }
5087 
5088 /*@
5089    MatGetRowSum - Gets the sum of each row of the matrix
5090 
5091    Logically or Neighborhood Collective
5092 
5093    Input Parameter:
5094 .  mat - the matrix
5095 
5096    Output Parameter:
5097 .  v - the vector for storing the sum of rows
5098 
5099    Level: intermediate
5100 
5101    Notes:
5102     This code is slow since it is not currently specialized for different formats
5103 
5104 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5105 @*/
5106 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5107 {
5108   Vec ones;
5109 
5110   PetscFunctionBegin;
5111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5112   PetscValidType(mat, 1);
5113   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5114   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5115   MatCheckPreallocated(mat, 1);
5116   PetscCall(MatCreateVecs(mat, &ones, NULL));
5117   PetscCall(VecSet(ones, 1.));
5118   PetscCall(MatMult(mat, ones, v));
5119   PetscCall(VecDestroy(&ones));
5120   PetscFunctionReturn(PETSC_SUCCESS);
5121 }
5122 
5123 /*@
5124    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5125    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5126 
5127    Collective
5128 
5129    Input Parameter:
5130 .  mat - the matrix to provide the transpose
5131 
5132    Output Parameter:
5133 .  mat - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results
5134 
5135    Level: advanced
5136 
5137    Note:
5138    Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This
5139    routine allows bypassing that call.
5140 
5141 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5142 @*/
5143 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5144 {
5145   PetscContainer  rB = NULL;
5146   MatParentState *rb = NULL;
5147 
5148   PetscFunctionBegin;
5149   PetscCall(PetscNew(&rb));
5150   rb->id    = ((PetscObject)mat)->id;
5151   rb->state = 0;
5152   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5153   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5154   PetscCall(PetscContainerSetPointer(rB, rb));
5155   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5156   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5157   PetscCall(PetscObjectDereference((PetscObject)rB));
5158   PetscFunctionReturn(PETSC_SUCCESS);
5159 }
5160 
5161 /*@
5162    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5163 
5164    Collective
5165 
5166    Input Parameters:
5167 +  mat - the matrix to transpose
5168 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5169 
5170    Output Parameter:
5171 .  B - the transpose
5172 
5173    Level: intermediate
5174 
5175    Notes:
5176      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5177 
5178      `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5179      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5180 
5181      If the nonzero structure of mat changed from the previous call to this function with the same matrices an error will be generated for some matrix types.
5182 
5183      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5184 
5185      If mat is unchanged from the last call this function returns immediately without recomputing the result
5186 
5187      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5188 
5189 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5190           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5191 @*/
5192 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5193 {
5194   PetscContainer  rB = NULL;
5195   MatParentState *rb = NULL;
5196 
5197   PetscFunctionBegin;
5198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5199   PetscValidType(mat, 1);
5200   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5201   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5202   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5203   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5204   MatCheckPreallocated(mat, 1);
5205   if (reuse == MAT_REUSE_MATRIX) {
5206     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5207     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5208     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5209     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5210     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5211   }
5212 
5213   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5214   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5215     PetscUseTypeMethod(mat, transpose, reuse, B);
5216     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5217   }
5218   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5219 
5220   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5221   if (reuse != MAT_INPLACE_MATRIX) {
5222     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5223     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5224     rb->state        = ((PetscObject)mat)->state;
5225     rb->nonzerostate = mat->nonzerostate;
5226   }
5227   PetscFunctionReturn(PETSC_SUCCESS);
5228 }
5229 
5230 /*@
5231    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5232 
5233    Collective
5234 
5235    Input Parameter:
5236 .  A - the matrix to transpose
5237 
5238    Output Parameter:
5239 .  B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the
5240       numerical portion.
5241 
5242    Level: intermediate
5243 
5244    Note:
5245    This is not supported for many matrix types, use `MatTranspose()` in those cases
5246 
5247 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5248 @*/
5249 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5250 {
5251   PetscFunctionBegin;
5252   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5253   PetscValidType(A, 1);
5254   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5255   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5256   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5257   PetscUseTypeMethod(A, transposesymbolic, B);
5258   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5259 
5260   PetscCall(MatTransposeSetPrecursor(A, *B));
5261   PetscFunctionReturn(PETSC_SUCCESS);
5262 }
5263 
5264 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5265 {
5266   PetscContainer  rB;
5267   MatParentState *rb;
5268 
5269   PetscFunctionBegin;
5270   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5271   PetscValidType(A, 1);
5272   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5273   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5274   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5275   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5276   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5277   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5278   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5279   PetscFunctionReturn(PETSC_SUCCESS);
5280 }
5281 
5282 /*@
5283    MatIsTranspose - Test whether a matrix is another one's transpose,
5284         or its own, in which case it tests symmetry.
5285 
5286    Collective
5287 
5288    Input Parameters:
5289 +  A - the matrix to test
5290 .  B - the matrix to test against, this can equal the first parameter
5291 -  tol - tolerance, differences between entries smaller than this are counted as zero
5292 
5293    Output Parameter:
5294 .  flg - the result
5295 
5296    Level: intermediate
5297 
5298    Notes:
5299    Only available for `MATAIJ` matrices.
5300 
5301    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5302    test involves parallel copies of the block-offdiagonal parts of the matrix.
5303 
5304 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5305 @*/
5306 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5307 {
5308   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5309 
5310   PetscFunctionBegin;
5311   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5312   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5313   PetscValidBoolPointer(flg, 4);
5314   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5315   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5316   *flg = PETSC_FALSE;
5317   if (f && g) {
5318     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5319     PetscCall((*f)(A, B, tol, flg));
5320   } else {
5321     MatType mattype;
5322 
5323     PetscCall(MatGetType(f ? B : A, &mattype));
5324     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5325   }
5326   PetscFunctionReturn(PETSC_SUCCESS);
5327 }
5328 
5329 /*@
5330    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5331 
5332    Collective
5333 
5334    Input Parameters:
5335 +  mat - the matrix to transpose and complex conjugate
5336 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5337 
5338    Output Parameter:
5339 .  B - the Hermitian transpose
5340 
5341    Level: intermediate
5342 
5343 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5344 @*/
5345 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5346 {
5347   PetscFunctionBegin;
5348   PetscCall(MatTranspose(mat, reuse, B));
5349 #if defined(PETSC_USE_COMPLEX)
5350   PetscCall(MatConjugate(*B));
5351 #endif
5352   PetscFunctionReturn(PETSC_SUCCESS);
5353 }
5354 
5355 /*@
5356    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5357 
5358    Collective
5359 
5360    Input Parameters:
5361 +  A - the matrix to test
5362 .  B - the matrix to test against, this can equal the first parameter
5363 -  tol - tolerance, differences between entries smaller than this are counted as zero
5364 
5365    Output Parameter:
5366 .  flg - the result
5367 
5368    Level: intermediate
5369 
5370    Notes:
5371    Only available for `MATAIJ` matrices.
5372 
5373    The sequential algorithm
5374    has a running time of the order of the number of nonzeros; the parallel
5375    test involves parallel copies of the block-offdiagonal parts of the matrix.
5376 
5377 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5378 @*/
5379 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5380 {
5381   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5382 
5383   PetscFunctionBegin;
5384   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5385   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5386   PetscValidBoolPointer(flg, 4);
5387   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5388   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5389   if (f && g) {
5390     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5391     PetscCall((*f)(A, B, tol, flg));
5392   }
5393   PetscFunctionReturn(PETSC_SUCCESS);
5394 }
5395 
5396 /*@
5397    MatPermute - Creates a new matrix with rows and columns permuted from the
5398    original.
5399 
5400    Collective
5401 
5402    Input Parameters:
5403 +  mat - the matrix to permute
5404 .  row - row permutation, each processor supplies only the permutation for its rows
5405 -  col - column permutation, each processor supplies only the permutation for its columns
5406 
5407    Output Parameter:
5408 .  B - the permuted matrix
5409 
5410    Level: advanced
5411 
5412    Note:
5413    The index sets map from row/col of permuted matrix to row/col of original matrix.
5414    The index sets should be on the same communicator as mat and have the same local sizes.
5415 
5416    Developer Note:
5417      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5418      exploit the fact that row and col are permutations, consider implementing the
5419      more general `MatCreateSubMatrix()` instead.
5420 
5421 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5422 @*/
5423 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5424 {
5425   PetscFunctionBegin;
5426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5427   PetscValidType(mat, 1);
5428   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5429   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5430   PetscValidPointer(B, 4);
5431   PetscCheckSameComm(mat, 1, row, 2);
5432   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5433   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5434   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5435   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5436   MatCheckPreallocated(mat, 1);
5437 
5438   if (mat->ops->permute) {
5439     PetscUseTypeMethod(mat, permute, row, col, B);
5440     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5441   } else {
5442     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5443   }
5444   PetscFunctionReturn(PETSC_SUCCESS);
5445 }
5446 
5447 /*@
5448    MatEqual - Compares two matrices.
5449 
5450    Collective
5451 
5452    Input Parameters:
5453 +  A - the first matrix
5454 -  B - the second matrix
5455 
5456    Output Parameter:
5457 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5458 
5459    Level: intermediate
5460 
5461 .seealso: [](chapter_matrices), `Mat`
5462 @*/
5463 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5464 {
5465   PetscFunctionBegin;
5466   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5467   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5468   PetscValidType(A, 1);
5469   PetscValidType(B, 2);
5470   PetscValidBoolPointer(flg, 3);
5471   PetscCheckSameComm(A, 1, B, 2);
5472   MatCheckPreallocated(A, 1);
5473   MatCheckPreallocated(B, 2);
5474   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5475   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5476   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5477              B->cmap->N);
5478   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5479     PetscUseTypeMethod(A, equal, B, flg);
5480   } else {
5481     PetscCall(MatMultEqual(A, B, 10, flg));
5482   }
5483   PetscFunctionReturn(PETSC_SUCCESS);
5484 }
5485 
5486 /*@
5487    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5488    matrices that are stored as vectors.  Either of the two scaling
5489    matrices can be `NULL`.
5490 
5491    Collective
5492 
5493    Input Parameters:
5494 +  mat - the matrix to be scaled
5495 .  l - the left scaling vector (or `NULL`)
5496 -  r - the right scaling vector (or `NULL`)
5497 
5498    Level: intermediate
5499 
5500    Note:
5501    `MatDiagonalScale()` computes A = LAR, where
5502    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5503    The L scales the rows of the matrix, the R scales the columns of the matrix.
5504 
5505 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5506 @*/
5507 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5508 {
5509   PetscFunctionBegin;
5510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5511   PetscValidType(mat, 1);
5512   if (l) {
5513     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5514     PetscCheckSameComm(mat, 1, l, 2);
5515   }
5516   if (r) {
5517     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5518     PetscCheckSameComm(mat, 1, r, 3);
5519   }
5520   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5521   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5522   MatCheckPreallocated(mat, 1);
5523   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5524 
5525   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5526   PetscUseTypeMethod(mat, diagonalscale, l, r);
5527   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5528   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5529   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5530   PetscFunctionReturn(PETSC_SUCCESS);
5531 }
5532 
5533 /*@
5534     MatScale - Scales all elements of a matrix by a given number.
5535 
5536     Logically Collective
5537 
5538     Input Parameters:
5539 +   mat - the matrix to be scaled
5540 -   a  - the scaling value
5541 
5542     Level: intermediate
5543 
5544 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5545 @*/
5546 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5547 {
5548   PetscFunctionBegin;
5549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5550   PetscValidType(mat, 1);
5551   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5552   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5553   PetscValidLogicalCollectiveScalar(mat, a, 2);
5554   MatCheckPreallocated(mat, 1);
5555 
5556   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5557   if (a != (PetscScalar)1.0) {
5558     PetscUseTypeMethod(mat, scale, a);
5559     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5560   }
5561   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5562   PetscFunctionReturn(PETSC_SUCCESS);
5563 }
5564 
5565 /*@
5566    MatNorm - Calculates various norms of a matrix.
5567 
5568    Collective
5569 
5570    Input Parameters:
5571 +  mat - the matrix
5572 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5573 
5574    Output Parameter:
5575 .  nrm - the resulting norm
5576 
5577    Level: intermediate
5578 
5579 .seealso: [](chapter_matrices), `Mat`
5580 @*/
5581 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5582 {
5583   PetscFunctionBegin;
5584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5585   PetscValidType(mat, 1);
5586   PetscValidRealPointer(nrm, 3);
5587 
5588   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5589   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5590   MatCheckPreallocated(mat, 1);
5591 
5592   PetscUseTypeMethod(mat, norm, type, nrm);
5593   PetscFunctionReturn(PETSC_SUCCESS);
5594 }
5595 
5596 /*
5597      This variable is used to prevent counting of MatAssemblyBegin() that
5598    are called from within a MatAssemblyEnd().
5599 */
5600 static PetscInt MatAssemblyEnd_InUse = 0;
5601 /*@
5602    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5603    be called after completing all calls to `MatSetValues()`.
5604 
5605    Collective
5606 
5607    Input Parameters:
5608 +  mat - the matrix
5609 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5610 
5611    Level: beginner
5612 
5613    Notes:
5614    `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5615    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5616 
5617    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5618    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5619    using the matrix.
5620 
5621    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5622    same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is
5623    a global collective operation requiring all processes that share the matrix.
5624 
5625    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5626    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5627    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5628 
5629 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5630 @*/
5631 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5632 {
5633   PetscFunctionBegin;
5634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5635   PetscValidType(mat, 1);
5636   MatCheckPreallocated(mat, 1);
5637   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5638   if (mat->assembled) {
5639     mat->was_assembled = PETSC_TRUE;
5640     mat->assembled     = PETSC_FALSE;
5641   }
5642 
5643   if (!MatAssemblyEnd_InUse) {
5644     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5645     PetscTryTypeMethod(mat, assemblybegin, type);
5646     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5647   } else PetscTryTypeMethod(mat, assemblybegin, type);
5648   PetscFunctionReturn(PETSC_SUCCESS);
5649 }
5650 
5651 /*@
5652    MatAssembled - Indicates if a matrix has been assembled and is ready for
5653      use; for example, in matrix-vector product.
5654 
5655    Not Collective
5656 
5657    Input Parameter:
5658 .  mat - the matrix
5659 
5660    Output Parameter:
5661 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5662 
5663    Level: advanced
5664 
5665 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5666 @*/
5667 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5668 {
5669   PetscFunctionBegin;
5670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5671   PetscValidBoolPointer(assembled, 2);
5672   *assembled = mat->assembled;
5673   PetscFunctionReturn(PETSC_SUCCESS);
5674 }
5675 
5676 /*@
5677    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5678    be called after `MatAssemblyBegin()`.
5679 
5680    Collective
5681 
5682    Input Parameters:
5683 +  mat - the matrix
5684 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5685 
5686    Options Database Keys:
5687 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5688 .  -mat_view ::ascii_info_detail - Prints more detailed info
5689 .  -mat_view - Prints matrix in ASCII format
5690 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5691 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5692 .  -display <name> - Sets display name (default is host)
5693 .  -draw_pause <sec> - Sets number of seconds to pause after display
5694 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5695 .  -viewer_socket_machine <machine> - Machine to use for socket
5696 .  -viewer_socket_port <port> - Port number to use for socket
5697 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5698 
5699    Level: beginner
5700 
5701 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5702 @*/
5703 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5704 {
5705   static PetscInt inassm = 0;
5706   PetscBool       flg    = PETSC_FALSE;
5707 
5708   PetscFunctionBegin;
5709   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5710   PetscValidType(mat, 1);
5711 
5712   inassm++;
5713   MatAssemblyEnd_InUse++;
5714   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5715     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5716     PetscTryTypeMethod(mat, assemblyend, type);
5717     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5718   } else PetscTryTypeMethod(mat, assemblyend, type);
5719 
5720   /* Flush assembly is not a true assembly */
5721   if (type != MAT_FLUSH_ASSEMBLY) {
5722     if (mat->num_ass) {
5723       if (!mat->symmetry_eternal) {
5724         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5725         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5726       }
5727       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5728       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5729     }
5730     mat->num_ass++;
5731     mat->assembled        = PETSC_TRUE;
5732     mat->ass_nonzerostate = mat->nonzerostate;
5733   }
5734 
5735   mat->insertmode = NOT_SET_VALUES;
5736   MatAssemblyEnd_InUse--;
5737   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5738   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5739     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5740 
5741     if (mat->checksymmetryonassembly) {
5742       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5743       if (flg) {
5744         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5745       } else {
5746         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5747       }
5748     }
5749     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5750   }
5751   inassm--;
5752   PetscFunctionReturn(PETSC_SUCCESS);
5753 }
5754 
5755 /*@
5756    MatSetOption - Sets a parameter option for a matrix. Some options
5757    may be specific to certain storage formats.  Some options
5758    determine how values will be inserted (or added). Sorted,
5759    row-oriented input will generally assemble the fastest. The default
5760    is row-oriented.
5761 
5762    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5763 
5764    Input Parameters:
5765 +  mat - the matrix
5766 .  option - the option, one of those listed below (and possibly others),
5767 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5768 
5769   Options Describing Matrix Structure:
5770 +    `MAT_SPD` - symmetric positive definite
5771 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5772 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5773 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5774 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5775 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5776 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5777 
5778    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5779    do not need to be computed (usually at a high cost)
5780 
5781    Options For Use with `MatSetValues()`:
5782    Insert a logically dense subblock, which can be
5783 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5784 
5785    These options reflect the data you pass in with `MatSetValues()`; it has
5786    nothing to do with how the data is stored internally in the matrix
5787    data structure.
5788 
5789    When (re)assembling a matrix, we can restrict the input for
5790    efficiency/debugging purposes.  These options include
5791 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5792 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5793 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5794 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5795 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5796 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5797         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5798         performance for very large process counts.
5799 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5800         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5801         functions, instead sending only neighbor messages.
5802 
5803    Level: intermediate
5804 
5805    Notes:
5806    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5807 
5808    Some options are relevant only for particular matrix types and
5809    are thus ignored by others.  Other options are not supported by
5810    certain matrix types and will generate an error message if set.
5811 
5812    If using Fortran to compute a matrix, one may need to
5813    use the column-oriented option (or convert to the row-oriented
5814    format).
5815 
5816    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5817    that would generate a new entry in the nonzero structure is instead
5818    ignored.  Thus, if memory has not already been allocated for this particular
5819    data, then the insertion is ignored. For dense matrices, in which
5820    the entire array is allocated, no entries are ever ignored.
5821    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5822 
5823    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5824    that would generate a new entry in the nonzero structure instead produces
5825    an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5826 
5827    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5828    that would generate a new entry that has not been preallocated will
5829    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5830    only.) This is a useful flag when debugging matrix memory preallocation.
5831    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5832 
5833    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5834    other processors should be dropped, rather than stashed.
5835    This is useful if you know that the "owning" processor is also
5836    always generating the correct matrix entries, so that PETSc need
5837    not transfer duplicate entries generated on another processor.
5838 
5839    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5840    searches during matrix assembly. When this flag is set, the hash table
5841    is created during the first matrix assembly. This hash table is
5842    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5843    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5844    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5845    supported by `MATMPIBAIJ` format only.
5846 
5847    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5848    are kept in the nonzero structure
5849 
5850    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5851    a zero location in the matrix
5852 
5853    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5854 
5855    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5856         zero row routines and thus improves performance for very large process counts.
5857 
5858    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5859         part of the matrix (since they should match the upper triangular part).
5860 
5861    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5862                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5863                      with finite difference schemes with non-periodic boundary conditions.
5864 
5865    Developer Note:
5866    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5867    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5868    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5869    not changed.
5870 
5871 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5872 @*/
5873 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5874 {
5875   PetscFunctionBegin;
5876   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5877   if (op > 0) {
5878     PetscValidLogicalCollectiveEnum(mat, op, 2);
5879     PetscValidLogicalCollectiveBool(mat, flg, 3);
5880   }
5881 
5882   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
5883 
5884   switch (op) {
5885   case MAT_FORCE_DIAGONAL_ENTRIES:
5886     mat->force_diagonals = flg;
5887     PetscFunctionReturn(PETSC_SUCCESS);
5888   case MAT_NO_OFF_PROC_ENTRIES:
5889     mat->nooffprocentries = flg;
5890     PetscFunctionReturn(PETSC_SUCCESS);
5891   case MAT_SUBSET_OFF_PROC_ENTRIES:
5892     mat->assembly_subset = flg;
5893     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5894 #if !defined(PETSC_HAVE_MPIUNI)
5895       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5896 #endif
5897       mat->stash.first_assembly_done = PETSC_FALSE;
5898     }
5899     PetscFunctionReturn(PETSC_SUCCESS);
5900   case MAT_NO_OFF_PROC_ZERO_ROWS:
5901     mat->nooffproczerorows = flg;
5902     PetscFunctionReturn(PETSC_SUCCESS);
5903   case MAT_SPD:
5904     if (flg) {
5905       mat->spd                    = PETSC_BOOL3_TRUE;
5906       mat->symmetric              = PETSC_BOOL3_TRUE;
5907       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5908     } else {
5909       mat->spd = PETSC_BOOL3_FALSE;
5910     }
5911     break;
5912   case MAT_SYMMETRIC:
5913     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5914     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5915 #if !defined(PETSC_USE_COMPLEX)
5916     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5917 #endif
5918     break;
5919   case MAT_HERMITIAN:
5920     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5921     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5922 #if !defined(PETSC_USE_COMPLEX)
5923     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5924 #endif
5925     break;
5926   case MAT_STRUCTURALLY_SYMMETRIC:
5927     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5928     break;
5929   case MAT_SYMMETRY_ETERNAL:
5930     PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false");
5931     mat->symmetry_eternal = flg;
5932     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5933     break;
5934   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5935     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false");
5936     mat->structural_symmetry_eternal = flg;
5937     break;
5938   case MAT_SPD_ETERNAL:
5939     PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false");
5940     mat->spd_eternal = flg;
5941     if (flg) {
5942       mat->structural_symmetry_eternal = PETSC_TRUE;
5943       mat->symmetry_eternal            = PETSC_TRUE;
5944     }
5945     break;
5946   case MAT_STRUCTURE_ONLY:
5947     mat->structure_only = flg;
5948     break;
5949   case MAT_SORTED_FULL:
5950     mat->sortedfull = flg;
5951     break;
5952   default:
5953     break;
5954   }
5955   PetscTryTypeMethod(mat, setoption, op, flg);
5956   PetscFunctionReturn(PETSC_SUCCESS);
5957 }
5958 
5959 /*@
5960    MatGetOption - Gets a parameter option that has been set for a matrix.
5961 
5962    Logically Collective
5963 
5964    Input Parameters:
5965 +  mat - the matrix
5966 -  option - the option, this only responds to certain options, check the code for which ones
5967 
5968    Output Parameter:
5969 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5970 
5971    Level: intermediate
5972 
5973     Notes:
5974     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5975 
5976     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5977     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5978 
5979 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5980     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5981 @*/
5982 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5983 {
5984   PetscFunctionBegin;
5985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5986   PetscValidType(mat, 1);
5987 
5988   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
5989   PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");
5990 
5991   switch (op) {
5992   case MAT_NO_OFF_PROC_ENTRIES:
5993     *flg = mat->nooffprocentries;
5994     break;
5995   case MAT_NO_OFF_PROC_ZERO_ROWS:
5996     *flg = mat->nooffproczerorows;
5997     break;
5998   case MAT_SYMMETRIC:
5999     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6000     break;
6001   case MAT_HERMITIAN:
6002     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6003     break;
6004   case MAT_STRUCTURALLY_SYMMETRIC:
6005     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6006     break;
6007   case MAT_SPD:
6008     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6009     break;
6010   case MAT_SYMMETRY_ETERNAL:
6011     *flg = mat->symmetry_eternal;
6012     break;
6013   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6014     *flg = mat->symmetry_eternal;
6015     break;
6016   default:
6017     break;
6018   }
6019   PetscFunctionReturn(PETSC_SUCCESS);
6020 }
6021 
6022 /*@
6023    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6024    this routine retains the old nonzero structure.
6025 
6026    Logically Collective
6027 
6028    Input Parameter:
6029 .  mat - the matrix
6030 
6031    Level: intermediate
6032 
6033    Note:
6034     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
6035    See the Performance chapter of the users manual for information on preallocating matrices.
6036 
6037 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6038 @*/
6039 PetscErrorCode MatZeroEntries(Mat mat)
6040 {
6041   PetscFunctionBegin;
6042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6043   PetscValidType(mat, 1);
6044   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6045   PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled");
6046   MatCheckPreallocated(mat, 1);
6047 
6048   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6049   PetscUseTypeMethod(mat, zeroentries);
6050   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6051   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6052   PetscFunctionReturn(PETSC_SUCCESS);
6053 }
6054 
6055 /*@
6056    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6057    of a set of rows and columns of a matrix.
6058 
6059    Collective
6060 
6061    Input Parameters:
6062 +  mat - the matrix
6063 .  numRows - the number of rows/columns to zero
6064 .  rows - the global row indices
6065 .  diag - value put in the diagonal of the eliminated rows
6066 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6067 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6068 
6069    Level: intermediate
6070 
6071    Notes:
6072    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6073 
6074    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6075    The other entries of `b` will be adjusted by the known values of `x` times the corresponding matrix entries in the columns that are being eliminated
6076 
6077    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6078    Krylov method to take advantage of the known solution on the zeroed rows.
6079 
6080    For the parallel case, all processes that share the matrix (i.e.,
6081    those in the communicator used for matrix creation) MUST call this
6082    routine, regardless of whether any rows being zeroed are owned by
6083    them.
6084 
6085    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6086 
6087    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6088    list only rows local to itself).
6089 
6090    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6091 
6092 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6093           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6094 @*/
6095 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6096 {
6097   PetscFunctionBegin;
6098   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6099   PetscValidType(mat, 1);
6100   if (numRows) PetscValidIntPointer(rows, 3);
6101   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6102   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6103   MatCheckPreallocated(mat, 1);
6104 
6105   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6106   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6107   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6108   PetscFunctionReturn(PETSC_SUCCESS);
6109 }
6110 
6111 /*@
6112    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6113    of a set of rows and columns of a matrix.
6114 
6115    Collective
6116 
6117    Input Parameters:
6118 +  mat - the matrix
6119 .  is - the rows to zero
6120 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6121 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6122 -  b - optional vector of right hand side, that will be adjusted by provided solution
6123 
6124    Level: intermediate
6125 
6126    Note:
6127    See `MatZeroRowsColumns()` for details on how this routine operates.
6128 
6129 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6130           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6131 @*/
6132 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6133 {
6134   PetscInt        numRows;
6135   const PetscInt *rows;
6136 
6137   PetscFunctionBegin;
6138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6139   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6140   PetscValidType(mat, 1);
6141   PetscValidType(is, 2);
6142   PetscCall(ISGetLocalSize(is, &numRows));
6143   PetscCall(ISGetIndices(is, &rows));
6144   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6145   PetscCall(ISRestoreIndices(is, &rows));
6146   PetscFunctionReturn(PETSC_SUCCESS);
6147 }
6148 
6149 /*@
6150    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6151    of a set of rows of a matrix.
6152 
6153    Collective
6154 
6155    Input Parameters:
6156 +  mat - the matrix
6157 .  numRows - the number of rows to zero
6158 .  rows - the global row indices
6159 .  diag - value put in the diagonal of the zeroed rows
6160 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6161 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6162 
6163    Level: intermediate
6164 
6165    Notes:
6166    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6167 
6168    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6169 
6170    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6171    Krylov method to take advantage of the known solution on the zeroed rows.
6172 
6173    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6174    from the matrix.
6175 
6176    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6177    but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6178    formats this does not alter the nonzero structure.
6179 
6180    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6181    of the matrix is not changed the values are
6182    merely zeroed.
6183 
6184    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6185    formats can optionally remove the main diagonal entry from the
6186    nonzero structure as well, by passing 0.0 as the final argument).
6187 
6188    For the parallel case, all processes that share the matrix (i.e.,
6189    those in the communicator used for matrix creation) MUST call this
6190    routine, regardless of whether any rows being zeroed are owned by
6191    them.
6192 
6193    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6194    list only rows local to itself).
6195 
6196    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6197    owns that are to be zeroed. This saves a global synchronization in the implementation.
6198 
6199 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6200           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6201 @*/
6202 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6203 {
6204   PetscFunctionBegin;
6205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6206   PetscValidType(mat, 1);
6207   if (numRows) PetscValidIntPointer(rows, 3);
6208   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6209   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6210   MatCheckPreallocated(mat, 1);
6211 
6212   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6213   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6214   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6215   PetscFunctionReturn(PETSC_SUCCESS);
6216 }
6217 
6218 /*@
6219    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6220    of a set of rows of a matrix.
6221 
6222    Collective
6223 
6224    Input Parameters:
6225 +  mat - the matrix
6226 .  is - index set of rows to remove (if `NULL` then no row is removed)
6227 .  diag - value put in all diagonals of eliminated rows
6228 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6229 -  b - optional vector of right hand side, that will be adjusted by provided solution
6230 
6231    Level: intermediate
6232 
6233    Note:
6234    See `MatZeroRows()` for details on how this routine operates.
6235 
6236 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6237           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6238 @*/
6239 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6240 {
6241   PetscInt        numRows = 0;
6242   const PetscInt *rows    = NULL;
6243 
6244   PetscFunctionBegin;
6245   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6246   PetscValidType(mat, 1);
6247   if (is) {
6248     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6249     PetscCall(ISGetLocalSize(is, &numRows));
6250     PetscCall(ISGetIndices(is, &rows));
6251   }
6252   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6253   if (is) PetscCall(ISRestoreIndices(is, &rows));
6254   PetscFunctionReturn(PETSC_SUCCESS);
6255 }
6256 
6257 /*@
6258    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6259    of a set of rows of a matrix. These rows must be local to the process.
6260 
6261    Collective
6262 
6263    Input Parameters:
6264 +  mat - the matrix
6265 .  numRows - the number of rows to remove
6266 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6267 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6268 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6269 -  b - optional vector of right hand side, that will be adjusted by provided solution
6270 
6271    Level: intermediate
6272 
6273    Notes:
6274    See `MatZeroRows()` for details on how this routine operates.
6275 
6276    The grid coordinates are across the entire grid, not just the local portion
6277 
6278    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6279    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6280    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6281    `DM_BOUNDARY_PERIODIC` boundary type.
6282 
6283    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6284    a single value per point) you can skip filling those indices.
6285 
6286    Fortran Note:
6287    `idxm` and `idxn` should be declared as
6288 $     MatStencil idxm(4, m)
6289    and the values inserted using
6290 .vb
6291     idxm(MatStencil_i, 1) = i
6292     idxm(MatStencil_j, 1) = j
6293     idxm(MatStencil_k, 1) = k
6294     idxm(MatStencil_c, 1) = c
6295    etc
6296 .ve
6297 
6298 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6299           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6300 @*/
6301 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6302 {
6303   PetscInt  dim    = mat->stencil.dim;
6304   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6305   PetscInt *dims   = mat->stencil.dims + 1;
6306   PetscInt *starts = mat->stencil.starts;
6307   PetscInt *dxm    = (PetscInt *)rows;
6308   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6309 
6310   PetscFunctionBegin;
6311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6312   PetscValidType(mat, 1);
6313   if (numRows) PetscValidPointer(rows, 3);
6314 
6315   PetscCall(PetscMalloc1(numRows, &jdxm));
6316   for (i = 0; i < numRows; ++i) {
6317     /* Skip unused dimensions (they are ordered k, j, i, c) */
6318     for (j = 0; j < 3 - sdim; ++j) dxm++;
6319     /* Local index in X dir */
6320     tmp = *dxm++ - starts[0];
6321     /* Loop over remaining dimensions */
6322     for (j = 0; j < dim - 1; ++j) {
6323       /* If nonlocal, set index to be negative */
6324       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6325       /* Update local index */
6326       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6327     }
6328     /* Skip component slot if necessary */
6329     if (mat->stencil.noc) dxm++;
6330     /* Local row number */
6331     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6332   }
6333   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6334   PetscCall(PetscFree(jdxm));
6335   PetscFunctionReturn(PETSC_SUCCESS);
6336 }
6337 
6338 /*@
6339    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6340    of a set of rows and columns of a matrix.
6341 
6342    Collective
6343 
6344    Input Parameters:
6345 +  mat - the matrix
6346 .  numRows - the number of rows/columns to remove
6347 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6348 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6349 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6350 -  b - optional vector of right hand side, that will be adjusted by provided solution
6351 
6352    Level: intermediate
6353 
6354    Notes:
6355    See `MatZeroRowsColumns()` for details on how this routine operates.
6356 
6357    The grid coordinates are across the entire grid, not just the local portion
6358 
6359    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6360    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6361    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6362    `DM_BOUNDARY_PERIODIC` boundary type.
6363 
6364    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6365    a single value per point) you can skip filling those indices.
6366 
6367    Fortran Note:
6368    `idxm` and `idxn` should be declared as
6369 $     MatStencil idxm(4, m)
6370    and the values inserted using
6371 .vb
6372     idxm(MatStencil_i, 1) = i
6373     idxm(MatStencil_j, 1) = j
6374     idxm(MatStencil_k, 1) = k
6375     idxm(MatStencil_c, 1) = c
6376     etc
6377 .ve
6378 
6379 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6380           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6381 @*/
6382 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6383 {
6384   PetscInt  dim    = mat->stencil.dim;
6385   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6386   PetscInt *dims   = mat->stencil.dims + 1;
6387   PetscInt *starts = mat->stencil.starts;
6388   PetscInt *dxm    = (PetscInt *)rows;
6389   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6390 
6391   PetscFunctionBegin;
6392   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6393   PetscValidType(mat, 1);
6394   if (numRows) PetscValidPointer(rows, 3);
6395 
6396   PetscCall(PetscMalloc1(numRows, &jdxm));
6397   for (i = 0; i < numRows; ++i) {
6398     /* Skip unused dimensions (they are ordered k, j, i, c) */
6399     for (j = 0; j < 3 - sdim; ++j) dxm++;
6400     /* Local index in X dir */
6401     tmp = *dxm++ - starts[0];
6402     /* Loop over remaining dimensions */
6403     for (j = 0; j < dim - 1; ++j) {
6404       /* If nonlocal, set index to be negative */
6405       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6406       /* Update local index */
6407       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6408     }
6409     /* Skip component slot if necessary */
6410     if (mat->stencil.noc) dxm++;
6411     /* Local row number */
6412     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6413   }
6414   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6415   PetscCall(PetscFree(jdxm));
6416   PetscFunctionReturn(PETSC_SUCCESS);
6417 }
6418 
6419 /*@C
6420    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6421    of a set of rows of a matrix; using local numbering of rows.
6422 
6423    Collective
6424 
6425    Input Parameters:
6426 +  mat - the matrix
6427 .  numRows - the number of rows to remove
6428 .  rows - the local row indices
6429 .  diag - value put in all diagonals of eliminated rows
6430 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6431 -  b - optional vector of right hand side, that will be adjusted by provided solution
6432 
6433    Level: intermediate
6434 
6435    Notes:
6436    Before calling `MatZeroRowsLocal()`, the user must first set the
6437    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6438 
6439    See `MatZeroRows()` for details on how this routine operates.
6440 
6441 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6442           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6443 @*/
6444 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6445 {
6446   PetscFunctionBegin;
6447   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6448   PetscValidType(mat, 1);
6449   if (numRows) PetscValidIntPointer(rows, 3);
6450   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6451   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6452   MatCheckPreallocated(mat, 1);
6453 
6454   if (mat->ops->zerorowslocal) {
6455     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6456   } else {
6457     IS              is, newis;
6458     const PetscInt *newRows;
6459 
6460     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6461     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6462     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6463     PetscCall(ISGetIndices(newis, &newRows));
6464     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6465     PetscCall(ISRestoreIndices(newis, &newRows));
6466     PetscCall(ISDestroy(&newis));
6467     PetscCall(ISDestroy(&is));
6468   }
6469   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6470   PetscFunctionReturn(PETSC_SUCCESS);
6471 }
6472 
6473 /*@
6474    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6475    of a set of rows of a matrix; using local numbering of rows.
6476 
6477    Collective
6478 
6479    Input Parameters:
6480 +  mat - the matrix
6481 .  is - index set of rows to remove
6482 .  diag - value put in all diagonals of eliminated rows
6483 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6484 -  b - optional vector of right hand side, that will be adjusted by provided solution
6485 
6486    Level: intermediate
6487 
6488    Notes:
6489    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6490    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6491 
6492    See `MatZeroRows()` for details on how this routine operates.
6493 
6494 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6495           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6496 @*/
6497 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6498 {
6499   PetscInt        numRows;
6500   const PetscInt *rows;
6501 
6502   PetscFunctionBegin;
6503   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6504   PetscValidType(mat, 1);
6505   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6506   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6507   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6508   MatCheckPreallocated(mat, 1);
6509 
6510   PetscCall(ISGetLocalSize(is, &numRows));
6511   PetscCall(ISGetIndices(is, &rows));
6512   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6513   PetscCall(ISRestoreIndices(is, &rows));
6514   PetscFunctionReturn(PETSC_SUCCESS);
6515 }
6516 
6517 /*@
6518    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6519    of a set of rows and columns of a matrix; using local numbering of rows.
6520 
6521    Collective
6522 
6523    Input Parameters:
6524 +  mat - the matrix
6525 .  numRows - the number of rows to remove
6526 .  rows - the global row indices
6527 .  diag - value put in all diagonals of eliminated rows
6528 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6529 -  b - optional vector of right hand side, that will be adjusted by provided solution
6530 
6531    Level: intermediate
6532 
6533    Notes:
6534    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6535    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6536 
6537    See `MatZeroRowsColumns()` for details on how this routine operates.
6538 
6539 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6540           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6541 @*/
6542 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6543 {
6544   IS              is, newis;
6545   const PetscInt *newRows;
6546 
6547   PetscFunctionBegin;
6548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6549   PetscValidType(mat, 1);
6550   if (numRows) PetscValidIntPointer(rows, 3);
6551   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6552   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6553   MatCheckPreallocated(mat, 1);
6554 
6555   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6556   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6557   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6558   PetscCall(ISGetIndices(newis, &newRows));
6559   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6560   PetscCall(ISRestoreIndices(newis, &newRows));
6561   PetscCall(ISDestroy(&newis));
6562   PetscCall(ISDestroy(&is));
6563   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6564   PetscFunctionReturn(PETSC_SUCCESS);
6565 }
6566 
6567 /*@
6568    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6569    of a set of rows and columns of a matrix; using local numbering of rows.
6570 
6571    Collective
6572 
6573    Input Parameters:
6574 +  mat - the matrix
6575 .  is - index set of rows to remove
6576 .  diag - value put in all diagonals of eliminated rows
6577 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6578 -  b - optional vector of right hand side, that will be adjusted by provided solution
6579 
6580    Level: intermediate
6581 
6582    Notes:
6583    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6584    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6585 
6586    See `MatZeroRowsColumns()` for details on how this routine operates.
6587 
6588 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6589           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6590 @*/
6591 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6592 {
6593   PetscInt        numRows;
6594   const PetscInt *rows;
6595 
6596   PetscFunctionBegin;
6597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6598   PetscValidType(mat, 1);
6599   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6600   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6601   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6602   MatCheckPreallocated(mat, 1);
6603 
6604   PetscCall(ISGetLocalSize(is, &numRows));
6605   PetscCall(ISGetIndices(is, &rows));
6606   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6607   PetscCall(ISRestoreIndices(is, &rows));
6608   PetscFunctionReturn(PETSC_SUCCESS);
6609 }
6610 
6611 /*@C
6612    MatGetSize - Returns the numbers of rows and columns in a matrix.
6613 
6614    Not Collective
6615 
6616    Input Parameter:
6617 .  mat - the matrix
6618 
6619    Output Parameters:
6620 +  m - the number of global rows
6621 -  n - the number of global columns
6622 
6623    Level: beginner
6624 
6625    Note:
6626    Both output parameters can be `NULL` on input.
6627 
6628 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6629 @*/
6630 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6631 {
6632   PetscFunctionBegin;
6633   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6634   if (m) *m = mat->rmap->N;
6635   if (n) *n = mat->cmap->N;
6636   PetscFunctionReturn(PETSC_SUCCESS);
6637 }
6638 
6639 /*@C
6640    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6641    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6642 
6643    Not Collective
6644 
6645    Input Parameter:
6646 .  mat - the matrix
6647 
6648    Output Parameters:
6649 +  m - the number of local rows, use `NULL` to not obtain this value
6650 -  n - the number of local columns, use `NULL` to not obtain this value
6651 
6652    Level: beginner
6653 
6654 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6655 @*/
6656 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6657 {
6658   PetscFunctionBegin;
6659   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6660   if (m) PetscValidIntPointer(m, 2);
6661   if (n) PetscValidIntPointer(n, 3);
6662   if (m) *m = mat->rmap->n;
6663   if (n) *n = mat->cmap->n;
6664   PetscFunctionReturn(PETSC_SUCCESS);
6665 }
6666 
6667 /*@C
6668    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6669    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6670 
6671    Not Collective, unless matrix has not been allocated, then collective
6672 
6673    Input Parameter:
6674 .  mat - the matrix
6675 
6676    Output Parameters:
6677 +  m - the global index of the first local column, use `NULL` to not obtain this value
6678 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6679 
6680    Level: developer
6681 
6682 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6683 @*/
6684 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6685 {
6686   PetscFunctionBegin;
6687   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6688   PetscValidType(mat, 1);
6689   if (m) PetscValidIntPointer(m, 2);
6690   if (n) PetscValidIntPointer(n, 3);
6691   MatCheckPreallocated(mat, 1);
6692   if (m) *m = mat->cmap->rstart;
6693   if (n) *n = mat->cmap->rend;
6694   PetscFunctionReturn(PETSC_SUCCESS);
6695 }
6696 
6697 /*@C
6698    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6699    this MPI process. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6700    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6701 
6702    Not Collective
6703 
6704    Input Parameter:
6705 .  mat - the matrix
6706 
6707    Output Parameters:
6708 +  m - the global index of the first local row, use `NULL` to not obtain this value
6709 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6710 
6711    Level: beginner
6712 
6713    Note:
6714   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6715   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6716   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6717 
6718 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6719           `PetscLayout`
6720 @*/
6721 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6722 {
6723   PetscFunctionBegin;
6724   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6725   PetscValidType(mat, 1);
6726   if (m) PetscValidIntPointer(m, 2);
6727   if (n) PetscValidIntPointer(n, 3);
6728   MatCheckPreallocated(mat, 1);
6729   if (m) *m = mat->rmap->rstart;
6730   if (n) *n = mat->rmap->rend;
6731   PetscFunctionReturn(PETSC_SUCCESS);
6732 }
6733 
6734 /*@C
6735    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6736    each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6737    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6738 
6739    Not Collective, unless matrix has not been allocated
6740 
6741    Input Parameter:
6742 .  mat - the matrix
6743 
6744    Output Parameter:
6745 .  ranges - start of each processors portion plus one more than the total length at the end
6746 
6747    Level: beginner
6748 
6749 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6750 @*/
6751 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6752 {
6753   PetscFunctionBegin;
6754   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6755   PetscValidType(mat, 1);
6756   MatCheckPreallocated(mat, 1);
6757   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6758   PetscFunctionReturn(PETSC_SUCCESS);
6759 }
6760 
6761 /*@C
6762    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6763    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6764 
6765    Not Collective, unless matrix has not been allocated
6766 
6767    Input Parameter:
6768 .  mat - the matrix
6769 
6770    Output Parameter:
6771 .  ranges - start of each processors portion plus one more then the total length at the end
6772 
6773    Level: beginner
6774 
6775 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6776 @*/
6777 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6778 {
6779   PetscFunctionBegin;
6780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6781   PetscValidType(mat, 1);
6782   MatCheckPreallocated(mat, 1);
6783   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6784   PetscFunctionReturn(PETSC_SUCCESS);
6785 }
6786 
6787 /*@C
6788    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6789    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6790    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6791 
6792    Not Collective
6793 
6794    Input Parameter:
6795 .  A - matrix
6796 
6797    Output Parameters:
6798 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6799 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6800 
6801    Level: intermediate
6802 
6803 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6804 @*/
6805 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6806 {
6807   PetscErrorCode (*f)(Mat, IS *, IS *);
6808 
6809   PetscFunctionBegin;
6810   MatCheckPreallocated(A, 1);
6811   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6812   if (f) {
6813     PetscCall((*f)(A, rows, cols));
6814   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6815     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6816     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6817   }
6818   PetscFunctionReturn(PETSC_SUCCESS);
6819 }
6820 
6821 /*@C
6822    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6823    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6824    to complete the factorization.
6825 
6826    Collective
6827 
6828    Input Parameters:
6829 +  fact - the factorized matrix obtained with `MatGetFactor()`
6830 .  mat - the matrix
6831 .  row - row permutation
6832 .  col - column permutation
6833 -  info - structure containing
6834 .vb
6835       levels - number of levels of fill.
6836       expected fill - as ratio of original fill.
6837       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6838                 missing diagonal entries)
6839 .ve
6840 
6841    Level: developer
6842 
6843    Notes:
6844    See [Matrix Factorization](sec_matfactor) for additional information.
6845 
6846    Most users should employ the `KSP` interface for linear solvers
6847    instead of working directly with matrix algebra routines such as this.
6848    See, e.g., `KSPCreate()`.
6849 
6850    Uses the definition of level of fill as in Y. Saad, 2003
6851 
6852    Developer Note:
6853    The Fortran interface is not autogenerated as the
6854    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6855 
6856    References:
6857 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6858 
6859 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6860           `MatGetOrdering()`, `MatFactorInfo`
6861 @*/
6862 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6863 {
6864   PetscFunctionBegin;
6865   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6866   PetscValidType(mat, 2);
6867   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6868   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6869   PetscValidPointer(info, 5);
6870   PetscValidPointer(fact, 1);
6871   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6872   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6873   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6874   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6875   MatCheckPreallocated(mat, 2);
6876 
6877   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6878   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6879   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6880   PetscFunctionReturn(PETSC_SUCCESS);
6881 }
6882 
6883 /*@C
6884    MatICCFactorSymbolic - Performs symbolic incomplete
6885    Cholesky factorization for a symmetric matrix.  Use
6886    `MatCholeskyFactorNumeric()` to complete the factorization.
6887 
6888    Collective
6889 
6890    Input Parameters:
6891 +  fact - the factorized matrix obtained with `MatGetFactor()`
6892 .  mat - the matrix to be factored
6893 .  perm - row and column permutation
6894 -  info - structure containing
6895 .vb
6896       levels - number of levels of fill.
6897       expected fill - as ratio of original fill.
6898 .ve
6899 
6900    Level: developer
6901 
6902    Notes:
6903    Most users should employ the `KSP` interface for linear solvers
6904    instead of working directly with matrix algebra routines such as this.
6905    See, e.g., `KSPCreate()`.
6906 
6907    This uses the definition of level of fill as in Y. Saad, 2003
6908 
6909    Developer Note:
6910    The Fortran interface is not autogenerated as the
6911    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6912 
6913    References:
6914 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6915 
6916 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6917 @*/
6918 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6919 {
6920   PetscFunctionBegin;
6921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6922   PetscValidType(mat, 2);
6923   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6924   PetscValidPointer(info, 4);
6925   PetscValidPointer(fact, 1);
6926   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6927   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6928   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6929   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6930   MatCheckPreallocated(mat, 2);
6931 
6932   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6933   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6934   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6935   PetscFunctionReturn(PETSC_SUCCESS);
6936 }
6937 
6938 /*@C
6939    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6940    points to an array of valid matrices, they may be reused to store the new
6941    submatrices.
6942 
6943    Collective
6944 
6945    Input Parameters:
6946 +  mat - the matrix
6947 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6948 .  irow - index set of rows to extract
6949 .  icol - index set of columns to extract
6950 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6951 
6952    Output Parameter:
6953 .  submat - the array of submatrices
6954 
6955    Level: advanced
6956 
6957    Notes:
6958    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6959    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6960    to extract a parallel submatrix.
6961 
6962    Some matrix types place restrictions on the row and column
6963    indices, such as that they be sorted or that they be equal to each other.
6964 
6965    The index sets may not have duplicate entries.
6966 
6967    When extracting submatrices from a parallel matrix, each processor can
6968    form a different submatrix by setting the rows and columns of its
6969    individual index sets according to the local submatrix desired.
6970 
6971    When finished using the submatrices, the user should destroy
6972    them with `MatDestroySubMatrices()`.
6973 
6974    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6975    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6976 
6977    This routine creates the matrices in submat; you should NOT create them before
6978    calling it. It also allocates the array of matrix pointers submat.
6979 
6980    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6981    request one row/column in a block, they must request all rows/columns that are in
6982    that block. For example, if the block size is 2 you cannot request just row 0 and
6983    column 0.
6984 
6985    Fortran Note:
6986    The Fortran interface is slightly different from that given below; it
6987    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
6988 
6989 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6990 @*/
6991 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6992 {
6993   PetscInt  i;
6994   PetscBool eq;
6995 
6996   PetscFunctionBegin;
6997   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6998   PetscValidType(mat, 1);
6999   if (n) {
7000     PetscValidPointer(irow, 3);
7001     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7002     PetscValidPointer(icol, 4);
7003     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7004   }
7005   PetscValidPointer(submat, 6);
7006   if (n && scall == MAT_REUSE_MATRIX) {
7007     PetscValidPointer(*submat, 6);
7008     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7009   }
7010   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7011   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7012   MatCheckPreallocated(mat, 1);
7013   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7014   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7015   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7016   for (i = 0; i < n; i++) {
7017     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7018     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7019     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7020 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7021     if (mat->boundtocpu && mat->bindingpropagates) {
7022       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7023       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7024     }
7025 #endif
7026   }
7027   PetscFunctionReturn(PETSC_SUCCESS);
7028 }
7029 
7030 /*@C
7031    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7032 
7033    Collective
7034 
7035    Input Parameters:
7036 +  mat - the matrix
7037 .  n   - the number of submatrixes to be extracted
7038 .  irow - index set of rows to extract
7039 .  icol - index set of columns to extract
7040 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7041 
7042    Output Parameter:
7043 .  submat - the array of submatrices
7044 
7045    Level: advanced
7046 
7047    Note:
7048    This is used by `PCGASM`
7049 
7050 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7051 @*/
7052 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7053 {
7054   PetscInt  i;
7055   PetscBool eq;
7056 
7057   PetscFunctionBegin;
7058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7059   PetscValidType(mat, 1);
7060   if (n) {
7061     PetscValidPointer(irow, 3);
7062     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7063     PetscValidPointer(icol, 4);
7064     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7065   }
7066   PetscValidPointer(submat, 6);
7067   if (n && scall == MAT_REUSE_MATRIX) {
7068     PetscValidPointer(*submat, 6);
7069     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7070   }
7071   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7072   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7073   MatCheckPreallocated(mat, 1);
7074 
7075   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7076   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7077   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7078   for (i = 0; i < n; i++) {
7079     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7080     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7081   }
7082   PetscFunctionReturn(PETSC_SUCCESS);
7083 }
7084 
7085 /*@C
7086    MatDestroyMatrices - Destroys an array of matrices.
7087 
7088    Collective
7089 
7090    Input Parameters:
7091 +  n - the number of local matrices
7092 -  mat - the matrices (this is a pointer to the array of matrices)
7093 
7094    Level: advanced
7095 
7096     Note:
7097     Frees not only the matrices, but also the array that contains the matrices
7098 
7099     Fortran Note:
7100     This does not free the array.
7101 
7102 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7103 @*/
7104 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7105 {
7106   PetscInt i;
7107 
7108   PetscFunctionBegin;
7109   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7110   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7111   PetscValidPointer(mat, 2);
7112 
7113   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7114 
7115   /* memory is allocated even if n = 0 */
7116   PetscCall(PetscFree(*mat));
7117   PetscFunctionReturn(PETSC_SUCCESS);
7118 }
7119 
7120 /*@C
7121    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7122 
7123    Collective
7124 
7125    Input Parameters:
7126 +  n - the number of local matrices
7127 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7128                        sequence of `MatCreateSubMatrices()`)
7129 
7130    Level: advanced
7131 
7132     Note:
7133     Frees not only the matrices, but also the array that contains the matrices
7134 
7135     Fortran Note:
7136     This does not free the array.
7137 
7138 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7139 @*/
7140 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7141 {
7142   Mat mat0;
7143 
7144   PetscFunctionBegin;
7145   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7146   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7147   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7148   PetscValidPointer(mat, 2);
7149 
7150   mat0 = (*mat)[0];
7151   if (mat0 && mat0->ops->destroysubmatrices) {
7152     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7153   } else {
7154     PetscCall(MatDestroyMatrices(n, mat));
7155   }
7156   PetscFunctionReturn(PETSC_SUCCESS);
7157 }
7158 
7159 /*@C
7160    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7161 
7162    Collective
7163 
7164    Input Parameter:
7165 .  mat - the matrix
7166 
7167    Output Parameter:
7168 .  matstruct - the sequential matrix with the nonzero structure of mat
7169 
7170   Level: developer
7171 
7172 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7173 @*/
7174 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7175 {
7176   PetscFunctionBegin;
7177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7178   PetscValidPointer(matstruct, 2);
7179 
7180   PetscValidType(mat, 1);
7181   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7182   MatCheckPreallocated(mat, 1);
7183 
7184   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7185   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7186   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7187   PetscFunctionReturn(PETSC_SUCCESS);
7188 }
7189 
7190 /*@C
7191    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7192 
7193    Collective
7194 
7195    Input Parameter:
7196 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7197                        sequence of `MatGetSeqNonzeroStructure()`)
7198 
7199    Level: advanced
7200 
7201     Note:
7202     Frees not only the matrices, but also the array that contains the matrices
7203 
7204 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7205 @*/
7206 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7207 {
7208   PetscFunctionBegin;
7209   PetscValidPointer(mat, 1);
7210   PetscCall(MatDestroy(mat));
7211   PetscFunctionReturn(PETSC_SUCCESS);
7212 }
7213 
7214 /*@
7215    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7216    replaces the index sets by larger ones that represent submatrices with
7217    additional overlap.
7218 
7219    Collective
7220 
7221    Input Parameters:
7222 +  mat - the matrix
7223 .  n   - the number of index sets
7224 .  is  - the array of index sets (these index sets will changed during the call)
7225 -  ov  - the additional overlap requested
7226 
7227    Options Database Key:
7228 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7229 
7230    Level: developer
7231 
7232    Note:
7233    The computed overlap preserves the matrix block sizes when the blocks are square.
7234    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7235    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7236 
7237 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7238 @*/
7239 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7240 {
7241   PetscInt i, bs, cbs;
7242 
7243   PetscFunctionBegin;
7244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7245   PetscValidType(mat, 1);
7246   PetscValidLogicalCollectiveInt(mat, n, 2);
7247   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7248   if (n) {
7249     PetscValidPointer(is, 3);
7250     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7251   }
7252   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7253   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7254   MatCheckPreallocated(mat, 1);
7255 
7256   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7257   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7258   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7259   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7260   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7261   if (bs == cbs) {
7262     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7263   }
7264   PetscFunctionReturn(PETSC_SUCCESS);
7265 }
7266 
7267 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7268 
7269 /*@
7270    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7271    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7272    additional overlap.
7273 
7274    Collective
7275 
7276    Input Parameters:
7277 +  mat - the matrix
7278 .  n   - the number of index sets
7279 .  is  - the array of index sets (these index sets will changed during the call)
7280 -  ov  - the additional overlap requested
7281 
7282 `   Options Database Key:
7283 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7284 
7285    Level: developer
7286 
7287 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7288 @*/
7289 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7290 {
7291   PetscInt i;
7292 
7293   PetscFunctionBegin;
7294   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7295   PetscValidType(mat, 1);
7296   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7297   if (n) {
7298     PetscValidPointer(is, 3);
7299     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7300   }
7301   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7302   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7303   MatCheckPreallocated(mat, 1);
7304   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7305   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7306   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7307   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7308   PetscFunctionReturn(PETSC_SUCCESS);
7309 }
7310 
7311 /*@
7312    MatGetBlockSize - Returns the matrix block size.
7313 
7314    Not Collective
7315 
7316    Input Parameter:
7317 .  mat - the matrix
7318 
7319    Output Parameter:
7320 .  bs - block size
7321 
7322    Level: intermediate
7323 
7324    Notes:
7325     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7326 
7327    If the block size has not been set yet this routine returns 1.
7328 
7329 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7330 @*/
7331 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7332 {
7333   PetscFunctionBegin;
7334   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7335   PetscValidIntPointer(bs, 2);
7336   *bs = PetscAbs(mat->rmap->bs);
7337   PetscFunctionReturn(PETSC_SUCCESS);
7338 }
7339 
7340 /*@
7341    MatGetBlockSizes - Returns the matrix block row and column sizes.
7342 
7343    Not Collective
7344 
7345    Input Parameter:
7346 .  mat - the matrix
7347 
7348    Output Parameters:
7349 +  rbs - row block size
7350 -  cbs - column block size
7351 
7352    Level: intermediate
7353 
7354    Notes:
7355     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7356     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7357 
7358    If a block size has not been set yet this routine returns 1.
7359 
7360 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7361 @*/
7362 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7363 {
7364   PetscFunctionBegin;
7365   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7366   if (rbs) PetscValidIntPointer(rbs, 2);
7367   if (cbs) PetscValidIntPointer(cbs, 3);
7368   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7369   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7370   PetscFunctionReturn(PETSC_SUCCESS);
7371 }
7372 
7373 /*@
7374    MatSetBlockSize - Sets the matrix block size.
7375 
7376    Logically Collective
7377 
7378    Input Parameters:
7379 +  mat - the matrix
7380 -  bs - block size
7381 
7382    Level: intermediate
7383 
7384    Notes:
7385     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7386     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7387 
7388     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7389     is compatible with the matrix local sizes.
7390 
7391 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7392 @*/
7393 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7394 {
7395   PetscFunctionBegin;
7396   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7397   PetscValidLogicalCollectiveInt(mat, bs, 2);
7398   PetscCall(MatSetBlockSizes(mat, bs, bs));
7399   PetscFunctionReturn(PETSC_SUCCESS);
7400 }
7401 
7402 typedef struct {
7403   PetscInt         n;
7404   IS              *is;
7405   Mat             *mat;
7406   PetscObjectState nonzerostate;
7407   Mat              C;
7408 } EnvelopeData;
7409 
7410 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7411 {
7412   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7413   PetscCall(PetscFree(edata->is));
7414   PetscCall(PetscFree(edata));
7415   return PETSC_SUCCESS;
7416 }
7417 
7418 /*
7419    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7420          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7421 
7422    Collective
7423 
7424    Input Parameter:
7425 .  mat - the matrix
7426 
7427    Notes:
7428      There can be zeros within the blocks
7429 
7430      The blocks can overlap between processes, including laying on more than two processes
7431 
7432 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7433 */
7434 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7435 {
7436   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7437   PetscInt          *diag, *odiag, sc;
7438   VecScatter         scatter;
7439   PetscScalar       *seqv;
7440   const PetscScalar *parv;
7441   const PetscInt    *ia, *ja;
7442   PetscBool          set, flag, done;
7443   Mat                AA = mat, A;
7444   MPI_Comm           comm;
7445   PetscMPIInt        rank, size, tag;
7446   MPI_Status         status;
7447   PetscContainer     container;
7448   EnvelopeData      *edata;
7449   Vec                seq, par;
7450   IS                 isglobal;
7451 
7452   PetscFunctionBegin;
7453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7454   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7455   if (!set || !flag) {
7456     /* TOO: only needs nonzero structure of transpose */
7457     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7458     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7459   }
7460   PetscCall(MatAIJGetLocalMat(AA, &A));
7461   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7462   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7463 
7464   PetscCall(MatGetLocalSize(mat, &n, NULL));
7465   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7466   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7467   PetscCallMPI(MPI_Comm_size(comm, &size));
7468   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7469 
7470   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7471 
7472   if (rank > 0) {
7473     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7474     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7475   }
7476   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7477   for (i = 0; i < n; i++) {
7478     env = PetscMax(env, ja[ia[i + 1] - 1]);
7479     II  = rstart + i;
7480     if (env == II) {
7481       starts[lblocks]  = tbs;
7482       sizes[lblocks++] = 1 + II - tbs;
7483       tbs              = 1 + II;
7484     }
7485   }
7486   if (rank < size - 1) {
7487     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7488     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7489   }
7490 
7491   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7492   if (!set || !flag) PetscCall(MatDestroy(&AA));
7493   PetscCall(MatDestroy(&A));
7494 
7495   PetscCall(PetscNew(&edata));
7496   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7497   edata->n = lblocks;
7498   /* create IS needed for extracting blocks from the original matrix */
7499   PetscCall(PetscMalloc1(lblocks, &edata->is));
7500   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7501 
7502   /* Create the resulting inverse matrix structure with preallocation information */
7503   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7504   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7505   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7506   PetscCall(MatSetType(edata->C, MATAIJ));
7507 
7508   /* Communicate the start and end of each row, from each block to the correct rank */
7509   /* TODO: Use PetscSF instead of VecScatter */
7510   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7511   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7512   PetscCall(VecGetArrayWrite(seq, &seqv));
7513   for (PetscInt i = 0; i < lblocks; i++) {
7514     for (PetscInt j = 0; j < sizes[i]; j++) {
7515       seqv[cnt]     = starts[i];
7516       seqv[cnt + 1] = starts[i] + sizes[i];
7517       cnt += 2;
7518     }
7519   }
7520   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7521   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7522   sc -= cnt;
7523   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7524   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7525   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7526   PetscCall(ISDestroy(&isglobal));
7527   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7528   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7529   PetscCall(VecScatterDestroy(&scatter));
7530   PetscCall(VecDestroy(&seq));
7531   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7532   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7533   PetscCall(VecGetArrayRead(par, &parv));
7534   cnt = 0;
7535   PetscCall(MatGetSize(mat, NULL, &n));
7536   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7537     PetscInt start, end, d = 0, od = 0;
7538 
7539     start = (PetscInt)PetscRealPart(parv[cnt]);
7540     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7541     cnt += 2;
7542 
7543     if (start < cstart) {
7544       od += cstart - start + n - cend;
7545       d += cend - cstart;
7546     } else if (start < cend) {
7547       od += n - cend;
7548       d += cend - start;
7549     } else od += n - start;
7550     if (end <= cstart) {
7551       od -= cstart - end + n - cend;
7552       d -= cend - cstart;
7553     } else if (end < cend) {
7554       od -= n - cend;
7555       d -= cend - end;
7556     } else od -= n - end;
7557 
7558     odiag[i] = od;
7559     diag[i]  = d;
7560   }
7561   PetscCall(VecRestoreArrayRead(par, &parv));
7562   PetscCall(VecDestroy(&par));
7563   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7564   PetscCall(PetscFree2(diag, odiag));
7565   PetscCall(PetscFree2(sizes, starts));
7566 
7567   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7568   PetscCall(PetscContainerSetPointer(container, edata));
7569   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7570   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7571   PetscCall(PetscObjectDereference((PetscObject)container));
7572   PetscFunctionReturn(PETSC_SUCCESS);
7573 }
7574 
7575 /*@
7576   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7577 
7578   Collective
7579 
7580   Input Parameters:
7581 + A - the matrix
7582 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7583 
7584   Output Parameter:
7585 . C - matrix with inverted block diagonal of `A`
7586 
7587   Level: advanced
7588 
7589   Note:
7590      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7591 
7592 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7593 @*/
7594 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7595 {
7596   PetscContainer   container;
7597   EnvelopeData    *edata;
7598   PetscObjectState nonzerostate;
7599 
7600   PetscFunctionBegin;
7601   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7602   if (!container) {
7603     PetscCall(MatComputeVariableBlockEnvelope(A));
7604     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7605   }
7606   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7607   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7608   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7609   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7610 
7611   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7612   *C = edata->C;
7613 
7614   for (PetscInt i = 0; i < edata->n; i++) {
7615     Mat          D;
7616     PetscScalar *dvalues;
7617 
7618     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7619     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7620     PetscCall(MatSeqDenseInvert(D));
7621     PetscCall(MatDenseGetArray(D, &dvalues));
7622     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7623     PetscCall(MatDestroy(&D));
7624   }
7625   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7626   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7627   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7628   PetscFunctionReturn(PETSC_SUCCESS);
7629 }
7630 
7631 /*@
7632    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7633 
7634    Logically Collective
7635 
7636    Input Parameters:
7637 +  mat - the matrix
7638 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7639 -  bsizes - the block sizes
7640 
7641    Level: intermediate
7642 
7643    Notes:
7644     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7645 
7646     Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes.
7647 
7648 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7649           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7650 @*/
7651 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7652 {
7653   PetscInt i, ncnt = 0, nlocal;
7654 
7655   PetscFunctionBegin;
7656   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7657   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7658   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7659   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7660   PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal);
7661   PetscCall(PetscFree(mat->bsizes));
7662   mat->nblocks = nblocks;
7663   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7664   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7665   PetscFunctionReturn(PETSC_SUCCESS);
7666 }
7667 
7668 /*@C
7669    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7670 
7671    Logically Collective; No Fortran Support
7672 
7673    Input Parameter:
7674 .  mat - the matrix
7675 
7676    Output Parameters:
7677 +  nblocks - the number of blocks on this process
7678 -  bsizes - the block sizes
7679 
7680    Level: intermediate
7681 
7682 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7683 @*/
7684 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7685 {
7686   PetscFunctionBegin;
7687   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7688   *nblocks = mat->nblocks;
7689   *bsizes  = mat->bsizes;
7690   PetscFunctionReturn(PETSC_SUCCESS);
7691 }
7692 
7693 /*@
7694    MatSetBlockSizes - Sets the matrix block row and column sizes.
7695 
7696    Logically Collective
7697 
7698    Input Parameters:
7699 +  mat - the matrix
7700 .  rbs - row block size
7701 -  cbs - column block size
7702 
7703    Level: intermediate
7704 
7705    Notes:
7706     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7707     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7708     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7709 
7710     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7711     are compatible with the matrix local sizes.
7712 
7713     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7714 
7715 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7716 @*/
7717 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7718 {
7719   PetscFunctionBegin;
7720   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7721   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7722   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7723   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7724   if (mat->rmap->refcnt) {
7725     ISLocalToGlobalMapping l2g  = NULL;
7726     PetscLayout            nmap = NULL;
7727 
7728     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7729     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7730     PetscCall(PetscLayoutDestroy(&mat->rmap));
7731     mat->rmap          = nmap;
7732     mat->rmap->mapping = l2g;
7733   }
7734   if (mat->cmap->refcnt) {
7735     ISLocalToGlobalMapping l2g  = NULL;
7736     PetscLayout            nmap = NULL;
7737 
7738     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7739     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7740     PetscCall(PetscLayoutDestroy(&mat->cmap));
7741     mat->cmap          = nmap;
7742     mat->cmap->mapping = l2g;
7743   }
7744   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7745   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7746   PetscFunctionReturn(PETSC_SUCCESS);
7747 }
7748 
7749 /*@
7750    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7751 
7752    Logically Collective
7753 
7754    Input Parameters:
7755 +  mat - the matrix
7756 .  fromRow - matrix from which to copy row block size
7757 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7758 
7759    Level: developer
7760 
7761 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7762 @*/
7763 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7764 {
7765   PetscFunctionBegin;
7766   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7767   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7768   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7769   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7770   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7771   PetscFunctionReturn(PETSC_SUCCESS);
7772 }
7773 
7774 /*@
7775    MatResidual - Default routine to calculate the residual r = b - Ax
7776 
7777    Collective
7778 
7779    Input Parameters:
7780 +  mat - the matrix
7781 .  b   - the right-hand-side
7782 -  x   - the approximate solution
7783 
7784    Output Parameter:
7785 .  r - location to store the residual
7786 
7787    Level: developer
7788 
7789 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7790 @*/
7791 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7792 {
7793   PetscFunctionBegin;
7794   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7795   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7796   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7797   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7798   PetscValidType(mat, 1);
7799   MatCheckPreallocated(mat, 1);
7800   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7801   if (!mat->ops->residual) {
7802     PetscCall(MatMult(mat, x, r));
7803     PetscCall(VecAYPX(r, -1.0, b));
7804   } else {
7805     PetscUseTypeMethod(mat, residual, b, x, r);
7806   }
7807   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7808   PetscFunctionReturn(PETSC_SUCCESS);
7809 }
7810 
7811 /*MC
7812     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7813 
7814     Synopsis:
7815     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7816 
7817     Not Collective
7818 
7819     Input Parameters:
7820 +   A - the matrix
7821 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7822 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7823 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7824                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7825                  always used.
7826 
7827     Output Parameters:
7828 +   n - number of local rows in the (possibly compressed) matrix
7829 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7830 .   ja - the column indices
7831 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7832            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7833 
7834     Level: developer
7835 
7836     Note:
7837     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7838 
7839 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7840 M*/
7841 
7842 /*MC
7843     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7844 
7845     Synopsis:
7846     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7847 
7848     Not Collective
7849 
7850     Input Parameters:
7851 +   A - the  matrix
7852 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7853 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7854     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7855                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7856                  always used.
7857 .   n - number of local rows in the (possibly compressed) matrix
7858 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7859 .   ja - the column indices
7860 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7861            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7862 
7863     Level: developer
7864 
7865 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7866 M*/
7867 
7868 /*@C
7869     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7870 
7871    Collective
7872 
7873     Input Parameters:
7874 +   mat - the matrix
7875 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7876 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7877 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7878                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7879                  always used.
7880 
7881     Output Parameters:
7882 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7883 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use `NULL` if not needed
7884 .   ja - the column indices, use `NULL` if not needed
7885 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7886            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7887 
7888     Level: developer
7889 
7890     Notes:
7891     You CANNOT change any of the ia[] or ja[] values.
7892 
7893     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7894 
7895     Fortran Notes:
7896     Use
7897 .vb
7898     PetscInt, pointer :: ia(:),ja(:)
7899     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7900     ! Access the ith and jth entries via ia(i) and ja(j)
7901 .ve
7902    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7903 
7904 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7905 @*/
7906 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7907 {
7908   PetscFunctionBegin;
7909   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7910   PetscValidType(mat, 1);
7911   if (n) PetscValidIntPointer(n, 5);
7912   if (ia) PetscValidPointer(ia, 6);
7913   if (ja) PetscValidPointer(ja, 7);
7914   if (done) PetscValidBoolPointer(done, 8);
7915   MatCheckPreallocated(mat, 1);
7916   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7917   else {
7918     if (done) *done = PETSC_TRUE;
7919     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7920     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7921     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7922   }
7923   PetscFunctionReturn(PETSC_SUCCESS);
7924 }
7925 
7926 /*@C
7927     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7928 
7929     Collective
7930 
7931     Input Parameters:
7932 +   mat - the matrix
7933 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7934 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7935                 symmetrized
7936 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7937                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7938                  always used.
7939 .   n - number of columns in the (possibly compressed) matrix
7940 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7941 -   ja - the row indices
7942 
7943     Output Parameter:
7944 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7945 
7946     Level: developer
7947 
7948 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7949 @*/
7950 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7951 {
7952   PetscFunctionBegin;
7953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7954   PetscValidType(mat, 1);
7955   PetscValidIntPointer(n, 5);
7956   if (ia) PetscValidPointer(ia, 6);
7957   if (ja) PetscValidPointer(ja, 7);
7958   PetscValidBoolPointer(done, 8);
7959   MatCheckPreallocated(mat, 1);
7960   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7961   else {
7962     *done = PETSC_TRUE;
7963     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7964   }
7965   PetscFunctionReturn(PETSC_SUCCESS);
7966 }
7967 
7968 /*@C
7969     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7970 
7971     Collective
7972 
7973     Input Parameters:
7974 +   mat - the matrix
7975 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7976 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7977 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7978                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7979                  always used.
7980 .   n - size of (possibly compressed) matrix
7981 .   ia - the row pointers
7982 -   ja - the column indices
7983 
7984     Output Parameter:
7985 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7986 
7987     Level: developer
7988 
7989     Note:
7990     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7991     us of the array after it has been restored. If you pass `NULL`, it will
7992     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7993 
7994     Fortran Note:
7995    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
7996 
7997 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
7998 @*/
7999 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8000 {
8001   PetscFunctionBegin;
8002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8003   PetscValidType(mat, 1);
8004   if (ia) PetscValidPointer(ia, 6);
8005   if (ja) PetscValidPointer(ja, 7);
8006   if (done) PetscValidBoolPointer(done, 8);
8007   MatCheckPreallocated(mat, 1);
8008 
8009   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8010   else {
8011     if (done) *done = PETSC_TRUE;
8012     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8013     if (n) *n = 0;
8014     if (ia) *ia = NULL;
8015     if (ja) *ja = NULL;
8016   }
8017   PetscFunctionReturn(PETSC_SUCCESS);
8018 }
8019 
8020 /*@C
8021     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8022 
8023     Collective
8024 
8025     Input Parameters:
8026 +   mat - the matrix
8027 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8028 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8029 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8030                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8031                  always used.
8032 
8033     Output Parameters:
8034 +   n - size of (possibly compressed) matrix
8035 .   ia - the column pointers
8036 .   ja - the row indices
8037 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8038 
8039     Level: developer
8040 
8041 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8042 @*/
8043 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8044 {
8045   PetscFunctionBegin;
8046   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8047   PetscValidType(mat, 1);
8048   if (ia) PetscValidPointer(ia, 6);
8049   if (ja) PetscValidPointer(ja, 7);
8050   PetscValidBoolPointer(done, 8);
8051   MatCheckPreallocated(mat, 1);
8052 
8053   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8054   else {
8055     *done = PETSC_TRUE;
8056     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8057     if (n) *n = 0;
8058     if (ia) *ia = NULL;
8059     if (ja) *ja = NULL;
8060   }
8061   PetscFunctionReturn(PETSC_SUCCESS);
8062 }
8063 
8064 /*@C
8065     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8066 
8067     Collective
8068 
8069     Input Parameters:
8070 +   mat - the matrix
8071 .   ncolors - maximum color value
8072 .   n   - number of entries in colorarray
8073 -   colorarray - array indicating color for each column
8074 
8075     Output Parameter:
8076 .   iscoloring - coloring generated using colorarray information
8077 
8078     Level: developer
8079 
8080 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8081 @*/
8082 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8083 {
8084   PetscFunctionBegin;
8085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8086   PetscValidType(mat, 1);
8087   PetscValidIntPointer(colorarray, 4);
8088   PetscValidPointer(iscoloring, 5);
8089   MatCheckPreallocated(mat, 1);
8090 
8091   if (!mat->ops->coloringpatch) {
8092     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8093   } else {
8094     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8095   }
8096   PetscFunctionReturn(PETSC_SUCCESS);
8097 }
8098 
8099 /*@
8100    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8101 
8102    Logically Collective
8103 
8104    Input Parameter:
8105 .  mat - the factored matrix to be reset
8106 
8107    Level: developer
8108 
8109    Notes:
8110    This routine should be used only with factored matrices formed by in-place
8111    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8112    format).  This option can save memory, for example, when solving nonlinear
8113    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8114    ILU(0) preconditioner.
8115 
8116    One can specify in-place ILU(0) factorization by calling
8117 .vb
8118      PCType(pc,PCILU);
8119      PCFactorSeUseInPlace(pc);
8120 .ve
8121    or by using the options -pc_type ilu -pc_factor_in_place
8122 
8123    In-place factorization ILU(0) can also be used as a local
8124    solver for the blocks within the block Jacobi or additive Schwarz
8125    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8126    for details on setting local solver options.
8127 
8128    Most users should employ the `KSP` interface for linear solvers
8129    instead of working directly with matrix algebra routines such as this.
8130    See, e.g., `KSPCreate()`.
8131 
8132 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8133 @*/
8134 PetscErrorCode MatSetUnfactored(Mat mat)
8135 {
8136   PetscFunctionBegin;
8137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8138   PetscValidType(mat, 1);
8139   MatCheckPreallocated(mat, 1);
8140   mat->factortype = MAT_FACTOR_NONE;
8141   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8142   PetscUseTypeMethod(mat, setunfactored);
8143   PetscFunctionReturn(PETSC_SUCCESS);
8144 }
8145 
8146 /*MC
8147     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8148 
8149     Synopsis:
8150     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8151 
8152     Not Collective
8153 
8154     Input Parameter:
8155 .   x - matrix
8156 
8157     Output Parameters:
8158 +   xx_v - the Fortran pointer to the array
8159 -   ierr - error code
8160 
8161     Example of Usage:
8162 .vb
8163       PetscScalar, pointer xx_v(:,:)
8164       ....
8165       call MatDenseGetArrayF90(x,xx_v,ierr)
8166       a = xx_v(3)
8167       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8168 .ve
8169 
8170     Level: advanced
8171 
8172 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8173 M*/
8174 
8175 /*MC
8176     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8177     accessed with `MatDenseGetArrayF90()`.
8178 
8179     Synopsis:
8180     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8181 
8182     Not Collective
8183 
8184     Input Parameters:
8185 +   x - matrix
8186 -   xx_v - the Fortran90 pointer to the array
8187 
8188     Output Parameter:
8189 .   ierr - error code
8190 
8191     Example of Usage:
8192 .vb
8193        PetscScalar, pointer xx_v(:,:)
8194        ....
8195        call MatDenseGetArrayF90(x,xx_v,ierr)
8196        a = xx_v(3)
8197        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8198 .ve
8199 
8200     Level: advanced
8201 
8202 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8203 M*/
8204 
8205 /*MC
8206     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8207 
8208     Synopsis:
8209     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8210 
8211     Not Collective
8212 
8213     Input Parameter:
8214 .   x - matrix
8215 
8216     Output Parameters:
8217 +   xx_v - the Fortran pointer to the array
8218 -   ierr - error code
8219 
8220     Example of Usage:
8221 .vb
8222       PetscScalar, pointer xx_v(:)
8223       ....
8224       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8225       a = xx_v(3)
8226       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8227 .ve
8228 
8229     Level: advanced
8230 
8231 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8232 M*/
8233 
8234 /*MC
8235     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8236     accessed with `MatSeqAIJGetArrayF90()`.
8237 
8238     Synopsis:
8239     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8240 
8241     Not Collective
8242 
8243     Input Parameters:
8244 +   x - matrix
8245 -   xx_v - the Fortran90 pointer to the array
8246 
8247     Output Parameter:
8248 .   ierr - error code
8249 
8250     Example of Usage:
8251 .vb
8252        PetscScalar, pointer xx_v(:)
8253        ....
8254        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8255        a = xx_v(3)
8256        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8257 .ve
8258 
8259     Level: advanced
8260 
8261 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8262 M*/
8263 
8264 /*@
8265     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8266                       as the original matrix.
8267 
8268     Collective
8269 
8270     Input Parameters:
8271 +   mat - the original matrix
8272 .   isrow - parallel `IS` containing the rows this processor should obtain
8273 .   iscol - parallel `IS` containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix.
8274 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8275 
8276     Output Parameter:
8277 .   newmat - the new submatrix, of the same type as the original matrix
8278 
8279     Level: advanced
8280 
8281     Notes:
8282     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8283 
8284     Some matrix types place restrictions on the row and column indices, such
8285     as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8286     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8287 
8288     The index sets may not have duplicate entries.
8289 
8290       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8291    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8292    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8293    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8294    you are finished using it.
8295 
8296     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8297     the input matrix.
8298 
8299     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8300 
8301    Example usage:
8302    Consider the following 8x8 matrix with 34 non-zero values, that is
8303    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8304    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8305    as follows
8306 .vb
8307             1  2  0  |  0  3  0  |  0  4
8308     Proc0   0  5  6  |  7  0  0  |  8  0
8309             9  0 10  | 11  0  0  | 12  0
8310     -------------------------------------
8311            13  0 14  | 15 16 17  |  0  0
8312     Proc1   0 18  0  | 19 20 21  |  0  0
8313             0  0  0  | 22 23  0  | 24  0
8314     -------------------------------------
8315     Proc2  25 26 27  |  0  0 28  | 29  0
8316            30  0  0  | 31 32 33  |  0 34
8317 .ve
8318 
8319     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8320 
8321 .vb
8322             2  0  |  0  3  0  |  0
8323     Proc0   5  6  |  7  0  0  |  8
8324     -------------------------------
8325     Proc1  18  0  | 19 20 21  |  0
8326     -------------------------------
8327     Proc2  26 27  |  0  0 28  | 29
8328             0  0  | 31 32 33  |  0
8329 .ve
8330 
8331 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8332 @*/
8333 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8334 {
8335   PetscMPIInt size;
8336   Mat        *local;
8337   IS          iscoltmp;
8338   PetscBool   flg;
8339 
8340   PetscFunctionBegin;
8341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8342   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8343   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8344   PetscValidPointer(newmat, 5);
8345   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8346   PetscValidType(mat, 1);
8347   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8348   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8349 
8350   MatCheckPreallocated(mat, 1);
8351   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8352 
8353   if (!iscol || isrow == iscol) {
8354     PetscBool   stride;
8355     PetscMPIInt grabentirematrix = 0, grab;
8356     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8357     if (stride) {
8358       PetscInt first, step, n, rstart, rend;
8359       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8360       if (step == 1) {
8361         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8362         if (rstart == first) {
8363           PetscCall(ISGetLocalSize(isrow, &n));
8364           if (n == rend - rstart) grabentirematrix = 1;
8365         }
8366       }
8367     }
8368     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8369     if (grab) {
8370       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8371       if (cll == MAT_INITIAL_MATRIX) {
8372         *newmat = mat;
8373         PetscCall(PetscObjectReference((PetscObject)mat));
8374       }
8375       PetscFunctionReturn(PETSC_SUCCESS);
8376     }
8377   }
8378 
8379   if (!iscol) {
8380     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8381   } else {
8382     iscoltmp = iscol;
8383   }
8384 
8385   /* if original matrix is on just one processor then use submatrix generated */
8386   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8387     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8388     goto setproperties;
8389   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8390     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8391     *newmat = *local;
8392     PetscCall(PetscFree(local));
8393     goto setproperties;
8394   } else if (!mat->ops->createsubmatrix) {
8395     /* Create a new matrix type that implements the operation using the full matrix */
8396     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8397     switch (cll) {
8398     case MAT_INITIAL_MATRIX:
8399       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8400       break;
8401     case MAT_REUSE_MATRIX:
8402       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8403       break;
8404     default:
8405       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8406     }
8407     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8408     goto setproperties;
8409   }
8410 
8411   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8412   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8413   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8414 
8415 setproperties:
8416   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8417   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8418   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8419   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8420   PetscFunctionReturn(PETSC_SUCCESS);
8421 }
8422 
8423 /*@
8424    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8425 
8426    Not Collective
8427 
8428    Input Parameters:
8429 +  A - the matrix we wish to propagate options from
8430 -  B - the matrix we wish to propagate options to
8431 
8432    Level: beginner
8433 
8434    Note:
8435    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8436 
8437 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8438 @*/
8439 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8440 {
8441   PetscFunctionBegin;
8442   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8443   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8444   B->symmetry_eternal            = A->symmetry_eternal;
8445   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8446   B->symmetric                   = A->symmetric;
8447   B->structurally_symmetric      = A->structurally_symmetric;
8448   B->spd                         = A->spd;
8449   B->hermitian                   = A->hermitian;
8450   PetscFunctionReturn(PETSC_SUCCESS);
8451 }
8452 
8453 /*@
8454    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8455    used during the assembly process to store values that belong to
8456    other processors.
8457 
8458    Not Collective
8459 
8460    Input Parameters:
8461 +  mat   - the matrix
8462 .  size  - the initial size of the stash.
8463 -  bsize - the initial size of the block-stash(if used).
8464 
8465    Options Database Keys:
8466 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8467 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8468 
8469    Level: intermediate
8470 
8471    Notes:
8472      The block-stash is used for values set with `MatSetValuesBlocked()` while
8473      the stash is used for values set with `MatSetValues()`
8474 
8475      Run with the option -info and look for output of the form
8476      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8477      to determine the appropriate value, MM, to use for size and
8478      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8479      to determine the value, BMM to use for bsize
8480 
8481 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8482 @*/
8483 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8484 {
8485   PetscFunctionBegin;
8486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8487   PetscValidType(mat, 1);
8488   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8489   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8490   PetscFunctionReturn(PETSC_SUCCESS);
8491 }
8492 
8493 /*@
8494    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8495      the matrix
8496 
8497    Neighbor-wise Collective
8498 
8499    Input Parameters:
8500 +  mat   - the matrix
8501 .  x - the vector to be multiplied by the interpolation operator
8502 -  y - the vector to be added to the result
8503 
8504    Output Parameter:
8505 .  w - the resulting vector
8506 
8507    Level: intermediate
8508 
8509    Notes:
8510     `w` may be the same vector as `y`.
8511 
8512     This allows one to use either the restriction or interpolation (its transpose)
8513     matrix to do the interpolation
8514 
8515 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8516 @*/
8517 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8518 {
8519   PetscInt M, N, Ny;
8520 
8521   PetscFunctionBegin;
8522   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8523   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8524   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8525   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8526   PetscCall(MatGetSize(A, &M, &N));
8527   PetscCall(VecGetSize(y, &Ny));
8528   if (M == Ny) {
8529     PetscCall(MatMultAdd(A, x, y, w));
8530   } else {
8531     PetscCall(MatMultTransposeAdd(A, x, y, w));
8532   }
8533   PetscFunctionReturn(PETSC_SUCCESS);
8534 }
8535 
8536 /*@
8537    MatInterpolate - y = A*x or A'*x depending on the shape of
8538      the matrix
8539 
8540    Neighbor-wise Collective
8541 
8542    Input Parameters:
8543 +  mat   - the matrix
8544 -  x - the vector to be interpolated
8545 
8546    Output Parameter:
8547 .  y - the resulting vector
8548 
8549    Level: intermediate
8550 
8551    Note:
8552     This allows one to use either the restriction or interpolation (its transpose)
8553     matrix to do the interpolation
8554 
8555 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8556 @*/
8557 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8558 {
8559   PetscInt M, N, Ny;
8560 
8561   PetscFunctionBegin;
8562   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8563   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8564   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8565   PetscCall(MatGetSize(A, &M, &N));
8566   PetscCall(VecGetSize(y, &Ny));
8567   if (M == Ny) {
8568     PetscCall(MatMult(A, x, y));
8569   } else {
8570     PetscCall(MatMultTranspose(A, x, y));
8571   }
8572   PetscFunctionReturn(PETSC_SUCCESS);
8573 }
8574 
8575 /*@
8576    MatRestrict - y = A*x or A'*x
8577 
8578    Neighbor-wise Collective
8579 
8580    Input Parameters:
8581 +  mat   - the matrix
8582 -  x - the vector to be restricted
8583 
8584    Output Parameter:
8585 .  y - the resulting vector
8586 
8587    Level: intermediate
8588 
8589    Note:
8590     This allows one to use either the restriction or interpolation (its transpose)
8591     matrix to do the restriction
8592 
8593 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8594 @*/
8595 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8596 {
8597   PetscInt M, N, Ny;
8598 
8599   PetscFunctionBegin;
8600   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8601   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8602   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8603   PetscCall(MatGetSize(A, &M, &N));
8604   PetscCall(VecGetSize(y, &Ny));
8605   if (M == Ny) {
8606     PetscCall(MatMult(A, x, y));
8607   } else {
8608     PetscCall(MatMultTranspose(A, x, y));
8609   }
8610   PetscFunctionReturn(PETSC_SUCCESS);
8611 }
8612 
8613 /*@
8614    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8615 
8616    Neighbor-wise Collective
8617 
8618    Input Parameters:
8619 +  mat   - the matrix
8620 .  x - the input dense matrix to be multiplied
8621 -  w - the input dense matrix to be added to the result
8622 
8623    Output Parameter:
8624 .  y - the output dense matrix
8625 
8626    Level: intermediate
8627 
8628    Note:
8629     This allows one to use either the restriction or interpolation (its transpose)
8630     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8631     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8632 
8633 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8634 @*/
8635 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8636 {
8637   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8638   PetscBool trans = PETSC_TRUE;
8639   MatReuse  reuse = MAT_INITIAL_MATRIX;
8640 
8641   PetscFunctionBegin;
8642   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8643   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8644   PetscValidType(x, 2);
8645   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8646   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8647   PetscCall(MatGetSize(A, &M, &N));
8648   PetscCall(MatGetSize(x, &Mx, &Nx));
8649   if (N == Mx) trans = PETSC_FALSE;
8650   else PetscCheck(M == Mx, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx);
8651   Mo = trans ? N : M;
8652   if (*y) {
8653     PetscCall(MatGetSize(*y, &My, &Ny));
8654     if (Mo == My && Nx == Ny) {
8655       reuse = MAT_REUSE_MATRIX;
8656     } else {
8657       PetscCheck(w || *y != w, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot reuse y and w, size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT ", Y %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx, My, Ny);
8658       PetscCall(MatDestroy(y));
8659     }
8660   }
8661 
8662   if (w && *y == w) { /* this is to minimize changes in PCMG */
8663     PetscBool flg;
8664 
8665     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8666     if (w) {
8667       PetscInt My, Ny, Mw, Nw;
8668 
8669       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8670       PetscCall(MatGetSize(*y, &My, &Ny));
8671       PetscCall(MatGetSize(w, &Mw, &Nw));
8672       if (!flg || My != Mw || Ny != Nw) w = NULL;
8673     }
8674     if (!w) {
8675       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8676       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8677       PetscCall(PetscObjectDereference((PetscObject)w));
8678     } else {
8679       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8680     }
8681   }
8682   if (!trans) {
8683     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8684   } else {
8685     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8686   }
8687   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8688   PetscFunctionReturn(PETSC_SUCCESS);
8689 }
8690 
8691 /*@
8692    MatMatInterpolate - Y = A*X or A'*X
8693 
8694    Neighbor-wise Collective
8695 
8696    Input Parameters:
8697 +  mat   - the matrix
8698 -  x - the input dense matrix
8699 
8700    Output Parameter:
8701 .  y - the output dense matrix
8702 
8703    Level: intermediate
8704 
8705    Note:
8706     This allows one to use either the restriction or interpolation (its transpose)
8707     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8708     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8709 
8710 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8711 @*/
8712 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8713 {
8714   PetscFunctionBegin;
8715   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8716   PetscFunctionReturn(PETSC_SUCCESS);
8717 }
8718 
8719 /*@
8720    MatMatRestrict - Y = A*X or A'*X
8721 
8722    Neighbor-wise Collective
8723 
8724    Input Parameters:
8725 +  mat   - the matrix
8726 -  x - the input dense matrix
8727 
8728    Output Parameter:
8729 .  y - the output dense matrix
8730 
8731    Level: intermediate
8732 
8733    Note:
8734     This allows one to use either the restriction or interpolation (its transpose)
8735     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8736     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8737 
8738 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8739 @*/
8740 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8741 {
8742   PetscFunctionBegin;
8743   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8744   PetscFunctionReturn(PETSC_SUCCESS);
8745 }
8746 
8747 /*@
8748    MatGetNullSpace - retrieves the null space of a matrix.
8749 
8750    Logically Collective
8751 
8752    Input Parameters:
8753 +  mat - the matrix
8754 -  nullsp - the null space object
8755 
8756    Level: developer
8757 
8758 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8759 @*/
8760 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8761 {
8762   PetscFunctionBegin;
8763   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8764   PetscValidPointer(nullsp, 2);
8765   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8766   PetscFunctionReturn(PETSC_SUCCESS);
8767 }
8768 
8769 /*@
8770    MatSetNullSpace - attaches a null space to a matrix.
8771 
8772    Logically Collective
8773 
8774    Input Parameters:
8775 +  mat - the matrix
8776 -  nullsp - the null space object
8777 
8778    Level: advanced
8779 
8780    Notes:
8781       This null space is used by the `KSP` linear solvers to solve singular systems.
8782 
8783       Overwrites any previous null space that may have been attached. You can remove the null space from the matrix object by calling this routine with an nullsp of `NULL`
8784 
8785       For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) the `KSP` residuals will not converge to
8786       to zero but the linear system will still be solved in a least squares sense.
8787 
8788       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8789    the domain of a matrix A (from R^n to R^m (m rows, n columns) R^n = the direct sum of the null space of A, n(A), + the range of A^T, R(A^T).
8790    Similarly R^m = direct sum n(A^T) + R(A).  Hence the linear system A x = b has a solution only if b in R(A) (or correspondingly b is orthogonal to
8791    n(A^T)) and if x is a solution then x + alpha n(A) is a solution for any alpha. The minimum norm solution is orthogonal to n(A). For problems without a solution
8792    the solution that minimizes the norm of the residual (the least squares solution) can be obtained by solving A x = \hat{b} where \hat{b} is b orthogonalized to the n(A^T).
8793    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8794 
8795     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8796     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8797     routine also automatically calls `MatSetTransposeNullSpace()`.
8798 
8799     The user should call `MatNullSpaceDestroy()`.
8800 
8801 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8802           `KSPSetPCSide()`
8803 @*/
8804 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8805 {
8806   PetscFunctionBegin;
8807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8808   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8809   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8810   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8811   mat->nullsp = nullsp;
8812   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8813   PetscFunctionReturn(PETSC_SUCCESS);
8814 }
8815 
8816 /*@
8817    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8818 
8819    Logically Collective
8820 
8821    Input Parameters:
8822 +  mat - the matrix
8823 -  nullsp - the null space object
8824 
8825    Level: developer
8826 
8827 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8828 @*/
8829 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8830 {
8831   PetscFunctionBegin;
8832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8833   PetscValidType(mat, 1);
8834   PetscValidPointer(nullsp, 2);
8835   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8836   PetscFunctionReturn(PETSC_SUCCESS);
8837 }
8838 
8839 /*@
8840    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8841 
8842    Logically Collective
8843 
8844    Input Parameters:
8845 +  mat - the matrix
8846 -  nullsp - the null space object
8847 
8848    Level: advanced
8849 
8850    Notes:
8851    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8852 
8853    See `MatSetNullSpace()`
8854 
8855 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8856 @*/
8857 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8858 {
8859   PetscFunctionBegin;
8860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8861   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8862   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8863   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8864   mat->transnullsp = nullsp;
8865   PetscFunctionReturn(PETSC_SUCCESS);
8866 }
8867 
8868 /*@
8869    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8870         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8871 
8872    Logically Collective
8873 
8874    Input Parameters:
8875 +  mat - the matrix
8876 -  nullsp - the null space object
8877 
8878    Level: advanced
8879 
8880    Notes:
8881    Overwrites any previous near null space that may have been attached
8882 
8883    You can remove the null space by calling this routine with an nullsp of `NULL`
8884 
8885 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8886 @*/
8887 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8888 {
8889   PetscFunctionBegin;
8890   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8891   PetscValidType(mat, 1);
8892   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8893   MatCheckPreallocated(mat, 1);
8894   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8895   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8896   mat->nearnullsp = nullsp;
8897   PetscFunctionReturn(PETSC_SUCCESS);
8898 }
8899 
8900 /*@
8901    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8902 
8903    Not Collective
8904 
8905    Input Parameter:
8906 .  mat - the matrix
8907 
8908    Output Parameter:
8909 .  nullsp - the null space object, `NULL` if not set
8910 
8911    Level: advanced
8912 
8913 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8914 @*/
8915 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8916 {
8917   PetscFunctionBegin;
8918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8919   PetscValidType(mat, 1);
8920   PetscValidPointer(nullsp, 2);
8921   MatCheckPreallocated(mat, 1);
8922   *nullsp = mat->nearnullsp;
8923   PetscFunctionReturn(PETSC_SUCCESS);
8924 }
8925 
8926 /*@C
8927    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8928 
8929    Collective
8930 
8931    Input Parameters:
8932 +  mat - the matrix
8933 .  row - row/column permutation
8934 -  info - information on desired factorization process
8935 
8936    Level: developer
8937 
8938    Notes:
8939    Probably really in-place only when level of fill is zero, otherwise allocates
8940    new space to store factored matrix and deletes previous memory.
8941 
8942    Most users should employ the `KSP` interface for linear solvers
8943    instead of working directly with matrix algebra routines such as this.
8944    See, e.g., `KSPCreate()`.
8945 
8946    Developer Note:
8947    The Fortran interface is not autogenerated as the
8948    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8949 
8950 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8951 @*/
8952 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8953 {
8954   PetscFunctionBegin;
8955   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8956   PetscValidType(mat, 1);
8957   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8958   PetscValidPointer(info, 3);
8959   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8960   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8961   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8962   MatCheckPreallocated(mat, 1);
8963   PetscUseTypeMethod(mat, iccfactor, row, info);
8964   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8965   PetscFunctionReturn(PETSC_SUCCESS);
8966 }
8967 
8968 /*@
8969    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8970          ghosted ones.
8971 
8972    Not Collective
8973 
8974    Input Parameters:
8975 +  mat - the matrix
8976 -  diag - the diagonal values, including ghost ones
8977 
8978    Level: developer
8979 
8980    Notes:
8981     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8982 
8983     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8984 
8985 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8986 @*/
8987 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8988 {
8989   PetscMPIInt size;
8990 
8991   PetscFunctionBegin;
8992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8993   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8994   PetscValidType(mat, 1);
8995 
8996   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8997   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8998   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8999   if (size == 1) {
9000     PetscInt n, m;
9001     PetscCall(VecGetSize(diag, &n));
9002     PetscCall(MatGetSize(mat, NULL, &m));
9003     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9004     PetscCall(MatDiagonalScale(mat, NULL, diag));
9005   } else {
9006     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9007   }
9008   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9009   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9010   PetscFunctionReturn(PETSC_SUCCESS);
9011 }
9012 
9013 /*@
9014    MatGetInertia - Gets the inertia from a factored matrix
9015 
9016    Collective
9017 
9018    Input Parameter:
9019 .  mat - the matrix
9020 
9021    Output Parameters:
9022 +   nneg - number of negative eigenvalues
9023 .   nzero - number of zero eigenvalues
9024 -   npos - number of positive eigenvalues
9025 
9026    Level: advanced
9027 
9028    Note:
9029     Matrix must have been factored by `MatCholeskyFactor()`
9030 
9031 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9032 @*/
9033 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9034 {
9035   PetscFunctionBegin;
9036   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9037   PetscValidType(mat, 1);
9038   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9040   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9041   PetscFunctionReturn(PETSC_SUCCESS);
9042 }
9043 
9044 /*@C
9045    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9046 
9047    Neighbor-wise Collective
9048 
9049    Input Parameters:
9050 +  mat - the factored matrix obtained with `MatGetFactor()`
9051 -  b - the right-hand-side vectors
9052 
9053    Output Parameter:
9054 .  x - the result vectors
9055 
9056    Level: developer
9057 
9058    Note:
9059    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9060    call `MatSolves`(A,x,x).
9061 
9062 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9063 @*/
9064 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9065 {
9066   PetscFunctionBegin;
9067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9068   PetscValidType(mat, 1);
9069   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9070   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9071   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9072 
9073   MatCheckPreallocated(mat, 1);
9074   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9075   PetscUseTypeMethod(mat, solves, b, x);
9076   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9077   PetscFunctionReturn(PETSC_SUCCESS);
9078 }
9079 
9080 /*@
9081    MatIsSymmetric - Test whether a matrix is symmetric
9082 
9083    Collective
9084 
9085    Input Parameters:
9086 +  A - the matrix to test
9087 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9088 
9089    Output Parameter:
9090 .  flg - the result
9091 
9092    Level: intermediate
9093 
9094    Notes:
9095     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9096 
9097     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9098 
9099     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9100     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9101 
9102 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9103           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9104 @*/
9105 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9106 {
9107   PetscFunctionBegin;
9108   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9109   PetscValidBoolPointer(flg, 3);
9110 
9111   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9112   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9113   else {
9114     PetscUseTypeMethod(A, issymmetric, tol, flg);
9115     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9116   }
9117   PetscFunctionReturn(PETSC_SUCCESS);
9118 }
9119 
9120 /*@
9121    MatIsHermitian - Test whether a matrix is Hermitian
9122 
9123    Collective
9124 
9125    Input Parameters:
9126 +  A - the matrix to test
9127 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9128 
9129    Output Parameter:
9130 .  flg - the result
9131 
9132    Level: intermediate
9133 
9134    Notes:
9135     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9136 
9137     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9138 
9139     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9140     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9141 
9142 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9143           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9144 @*/
9145 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9146 {
9147   PetscFunctionBegin;
9148   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9149   PetscValidBoolPointer(flg, 3);
9150 
9151   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9152   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9153   else {
9154     PetscUseTypeMethod(A, ishermitian, tol, flg);
9155     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9156   }
9157   PetscFunctionReturn(PETSC_SUCCESS);
9158 }
9159 
9160 /*@
9161    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9162 
9163    Not Collective
9164 
9165    Input Parameter:
9166 .  A - the matrix to check
9167 
9168    Output Parameters:
9169 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9170 -  flg - the result (only valid if set is `PETSC_TRUE`)
9171 
9172    Level: advanced
9173 
9174    Notes:
9175    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9176    if you want it explicitly checked
9177 
9178     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9179     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9180 
9181 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9182 @*/
9183 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9184 {
9185   PetscFunctionBegin;
9186   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9187   PetscValidBoolPointer(set, 2);
9188   PetscValidBoolPointer(flg, 3);
9189   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9190     *set = PETSC_TRUE;
9191     *flg = PetscBool3ToBool(A->symmetric);
9192   } else {
9193     *set = PETSC_FALSE;
9194   }
9195   PetscFunctionReturn(PETSC_SUCCESS);
9196 }
9197 
9198 /*@
9199    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9200 
9201    Not Collective
9202 
9203    Input Parameter:
9204 .  A - the matrix to check
9205 
9206    Output Parameters:
9207 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9208 -  flg - the result (only valid if set is `PETSC_TRUE`)
9209 
9210    Level: advanced
9211 
9212    Notes:
9213    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9214 
9215    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9216    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9217 
9218 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9219 @*/
9220 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9221 {
9222   PetscFunctionBegin;
9223   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9224   PetscValidBoolPointer(set, 2);
9225   PetscValidBoolPointer(flg, 3);
9226   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9227     *set = PETSC_TRUE;
9228     *flg = PetscBool3ToBool(A->spd);
9229   } else {
9230     *set = PETSC_FALSE;
9231   }
9232   PetscFunctionReturn(PETSC_SUCCESS);
9233 }
9234 
9235 /*@
9236    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9237 
9238    Not Collective
9239 
9240    Input Parameter:
9241 .  A - the matrix to check
9242 
9243    Output Parameters:
9244 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9245 -  flg - the result (only valid if set is `PETSC_TRUE`)
9246 
9247    Level: advanced
9248 
9249    Notes:
9250    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9251    if you want it explicitly checked
9252 
9253    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9254    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9255 
9256 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9257 @*/
9258 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9259 {
9260   PetscFunctionBegin;
9261   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9262   PetscValidBoolPointer(set, 2);
9263   PetscValidBoolPointer(flg, 3);
9264   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9265     *set = PETSC_TRUE;
9266     *flg = PetscBool3ToBool(A->hermitian);
9267   } else {
9268     *set = PETSC_FALSE;
9269   }
9270   PetscFunctionReturn(PETSC_SUCCESS);
9271 }
9272 
9273 /*@
9274    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9275 
9276    Collective
9277 
9278    Input Parameter:
9279 .  A - the matrix to test
9280 
9281    Output Parameter:
9282 .  flg - the result
9283 
9284    Level: intermediate
9285 
9286    Notes:
9287    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9288 
9289    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9290    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9291 
9292 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9293 @*/
9294 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9295 {
9296   PetscFunctionBegin;
9297   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9298   PetscValidBoolPointer(flg, 2);
9299   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9300     *flg = PetscBool3ToBool(A->structurally_symmetric);
9301   } else {
9302     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9303     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9304   }
9305   PetscFunctionReturn(PETSC_SUCCESS);
9306 }
9307 
9308 /*@
9309    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9310 
9311    Not Collective
9312 
9313    Input Parameter:
9314 .  A - the matrix to check
9315 
9316    Output Parameters:
9317 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9318 -  flg - the result (only valid if set is PETSC_TRUE)
9319 
9320    Level: advanced
9321 
9322    Notes:
9323    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9324    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9325 
9326    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9327 
9328 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9329 @*/
9330 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9331 {
9332   PetscFunctionBegin;
9333   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9334   PetscValidBoolPointer(set, 2);
9335   PetscValidBoolPointer(flg, 3);
9336   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9337     *set = PETSC_TRUE;
9338     *flg = PetscBool3ToBool(A->structurally_symmetric);
9339   } else {
9340     *set = PETSC_FALSE;
9341   }
9342   PetscFunctionReturn(PETSC_SUCCESS);
9343 }
9344 
9345 /*@
9346    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9347        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9348 
9349     Not Collective
9350 
9351    Input Parameter:
9352 .   mat - the matrix
9353 
9354    Output Parameters:
9355 +   nstash   - the size of the stash
9356 .   reallocs - the number of additional mallocs incurred.
9357 .   bnstash   - the size of the block stash
9358 -   breallocs - the number of additional mallocs incurred.in the block stash
9359 
9360    Level: advanced
9361 
9362 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9363 @*/
9364 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9365 {
9366   PetscFunctionBegin;
9367   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9368   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9369   PetscFunctionReturn(PETSC_SUCCESS);
9370 }
9371 
9372 /*@C
9373    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9374    parallel layout, `PetscLayout` for rows and columns
9375 
9376    Collective
9377 
9378    Input Parameter:
9379 .  mat - the matrix
9380 
9381    Output Parameters:
9382 +   right - (optional) vector that the matrix can be multiplied against
9383 -   left - (optional) vector that the matrix vector product can be stored in
9384 
9385   Level: advanced
9386 
9387    Notes:
9388     The blocksize of the returned vectors is determined by the row and column block sizes set with `MatSetBlockSizes()` or the single blocksize (same for both) set by `MatSetBlockSize()`.
9389 
9390     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9391 
9392 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9393 @*/
9394 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9395 {
9396   PetscFunctionBegin;
9397   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9398   PetscValidType(mat, 1);
9399   if (mat->ops->getvecs) {
9400     PetscUseTypeMethod(mat, getvecs, right, left);
9401   } else {
9402     PetscInt rbs, cbs;
9403     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9404     if (right) {
9405       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9406       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9407       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9408       PetscCall(VecSetBlockSize(*right, cbs));
9409       PetscCall(VecSetType(*right, mat->defaultvectype));
9410 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9411       if (mat->boundtocpu && mat->bindingpropagates) {
9412         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9413         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9414       }
9415 #endif
9416       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9417     }
9418     if (left) {
9419       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9420       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9421       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9422       PetscCall(VecSetBlockSize(*left, rbs));
9423       PetscCall(VecSetType(*left, mat->defaultvectype));
9424 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9425       if (mat->boundtocpu && mat->bindingpropagates) {
9426         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9427         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9428       }
9429 #endif
9430       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9431     }
9432   }
9433   PetscFunctionReturn(PETSC_SUCCESS);
9434 }
9435 
9436 /*@C
9437    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9438      with default values.
9439 
9440    Not Collective
9441 
9442    Input Parameter:
9443 .    info - the `MatFactorInfo` data structure
9444 
9445    Level: developer
9446 
9447    Notes:
9448     The solvers are generally used through the `KSP` and `PC` objects, for example
9449           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9450 
9451     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9452 
9453    Developer Note:
9454    The Fortran interface is not autogenerated as the
9455    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9456 
9457 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9458 @*/
9459 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9460 {
9461   PetscFunctionBegin;
9462   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9463   PetscFunctionReturn(PETSC_SUCCESS);
9464 }
9465 
9466 /*@
9467    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9468 
9469    Collective
9470 
9471    Input Parameters:
9472 +  mat - the factored matrix
9473 -  is - the index set defining the Schur indices (0-based)
9474 
9475    Level: advanced
9476 
9477    Notes:
9478     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9479 
9480    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9481 
9482    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9483 
9484 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9485           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9486 @*/
9487 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9488 {
9489   PetscErrorCode (*f)(Mat, IS);
9490 
9491   PetscFunctionBegin;
9492   PetscValidType(mat, 1);
9493   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9494   PetscValidType(is, 2);
9495   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9496   PetscCheckSameComm(mat, 1, is, 2);
9497   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9498   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9499   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9500   PetscCall(MatDestroy(&mat->schur));
9501   PetscCall((*f)(mat, is));
9502   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9503   PetscFunctionReturn(PETSC_SUCCESS);
9504 }
9505 
9506 /*@
9507   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9508 
9509    Logically Collective
9510 
9511    Input Parameters:
9512 +  F - the factored matrix obtained by calling `MatGetFactor()`
9513 .  S - location where to return the Schur complement, can be `NULL`
9514 -  status - the status of the Schur complement matrix, can be `NULL`
9515 
9516    Level: advanced
9517 
9518    Notes:
9519    You must call `MatFactorSetSchurIS()` before calling this routine.
9520 
9521    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9522 
9523    The routine provides a copy of the Schur matrix stored within the solver data structures.
9524    The caller must destroy the object when it is no longer needed.
9525    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9526 
9527    Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does)
9528 
9529    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9530 
9531    Developer Note:
9532     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9533    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9534 
9535 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9536 @*/
9537 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9538 {
9539   PetscFunctionBegin;
9540   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9541   if (S) PetscValidPointer(S, 2);
9542   if (status) PetscValidPointer(status, 3);
9543   if (S) {
9544     PetscErrorCode (*f)(Mat, Mat *);
9545 
9546     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9547     if (f) {
9548       PetscCall((*f)(F, S));
9549     } else {
9550       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9551     }
9552   }
9553   if (status) *status = F->schur_status;
9554   PetscFunctionReturn(PETSC_SUCCESS);
9555 }
9556 
9557 /*@
9558   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9559 
9560    Logically Collective
9561 
9562    Input Parameters:
9563 +  F - the factored matrix obtained by calling `MatGetFactor()`
9564 .  *S - location where to return the Schur complement, can be `NULL`
9565 -  status - the status of the Schur complement matrix, can be `NULL`
9566 
9567    Level: advanced
9568 
9569    Notes:
9570    You must call `MatFactorSetSchurIS()` before calling this routine.
9571 
9572    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9573 
9574    The routine returns a the Schur Complement stored within the data structures of the solver.
9575 
9576    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9577 
9578    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9579 
9580    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9581 
9582    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9583 
9584 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9585 @*/
9586 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9587 {
9588   PetscFunctionBegin;
9589   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9590   if (S) PetscValidPointer(S, 2);
9591   if (status) PetscValidPointer(status, 3);
9592   if (S) *S = F->schur;
9593   if (status) *status = F->schur_status;
9594   PetscFunctionReturn(PETSC_SUCCESS);
9595 }
9596 
9597 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9598 {
9599   Mat S = F->schur;
9600 
9601   PetscFunctionBegin;
9602   switch (F->schur_status) {
9603   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9604   case MAT_FACTOR_SCHUR_INVERTED:
9605     if (S) {
9606       S->ops->solve             = NULL;
9607       S->ops->matsolve          = NULL;
9608       S->ops->solvetranspose    = NULL;
9609       S->ops->matsolvetranspose = NULL;
9610       S->ops->solveadd          = NULL;
9611       S->ops->solvetransposeadd = NULL;
9612       S->factortype             = MAT_FACTOR_NONE;
9613       PetscCall(PetscFree(S->solvertype));
9614     }
9615   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9616     break;
9617   default:
9618     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9619   }
9620   PetscFunctionReturn(PETSC_SUCCESS);
9621 }
9622 
9623 /*@
9624   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9625 
9626    Logically Collective
9627 
9628    Input Parameters:
9629 +  F - the factored matrix obtained by calling `MatGetFactor()`
9630 .  *S - location where the Schur complement is stored
9631 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9632 
9633    Level: advanced
9634 
9635 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9636 @*/
9637 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9638 {
9639   PetscFunctionBegin;
9640   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9641   if (S) {
9642     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9643     *S = NULL;
9644   }
9645   F->schur_status = status;
9646   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9647   PetscFunctionReturn(PETSC_SUCCESS);
9648 }
9649 
9650 /*@
9651   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9652 
9653    Logically Collective
9654 
9655    Input Parameters:
9656 +  F - the factored matrix obtained by calling `MatGetFactor()`
9657 .  rhs - location where the right hand side of the Schur complement system is stored
9658 -  sol - location where the solution of the Schur complement system has to be returned
9659 
9660    Level: advanced
9661 
9662    Notes:
9663    The sizes of the vectors should match the size of the Schur complement
9664 
9665    Must be called after `MatFactorSetSchurIS()`
9666 
9667 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9668 @*/
9669 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9670 {
9671   PetscFunctionBegin;
9672   PetscValidType(F, 1);
9673   PetscValidType(rhs, 2);
9674   PetscValidType(sol, 3);
9675   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9676   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9677   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9678   PetscCheckSameComm(F, 1, rhs, 2);
9679   PetscCheckSameComm(F, 1, sol, 3);
9680   PetscCall(MatFactorFactorizeSchurComplement(F));
9681   switch (F->schur_status) {
9682   case MAT_FACTOR_SCHUR_FACTORED:
9683     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9684     break;
9685   case MAT_FACTOR_SCHUR_INVERTED:
9686     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9687     break;
9688   default:
9689     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9690   }
9691   PetscFunctionReturn(PETSC_SUCCESS);
9692 }
9693 
9694 /*@
9695   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9696 
9697    Logically Collective
9698 
9699    Input Parameters:
9700 +  F - the factored matrix obtained by calling `MatGetFactor()`
9701 .  rhs - location where the right hand side of the Schur complement system is stored
9702 -  sol - location where the solution of the Schur complement system has to be returned
9703 
9704    Level: advanced
9705 
9706    Notes:
9707    The sizes of the vectors should match the size of the Schur complement
9708 
9709    Must be called after `MatFactorSetSchurIS()`
9710 
9711 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9712 @*/
9713 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9714 {
9715   PetscFunctionBegin;
9716   PetscValidType(F, 1);
9717   PetscValidType(rhs, 2);
9718   PetscValidType(sol, 3);
9719   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9720   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9721   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9722   PetscCheckSameComm(F, 1, rhs, 2);
9723   PetscCheckSameComm(F, 1, sol, 3);
9724   PetscCall(MatFactorFactorizeSchurComplement(F));
9725   switch (F->schur_status) {
9726   case MAT_FACTOR_SCHUR_FACTORED:
9727     PetscCall(MatSolve(F->schur, rhs, sol));
9728     break;
9729   case MAT_FACTOR_SCHUR_INVERTED:
9730     PetscCall(MatMult(F->schur, rhs, sol));
9731     break;
9732   default:
9733     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9734   }
9735   PetscFunctionReturn(PETSC_SUCCESS);
9736 }
9737 
9738 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9739 #if PetscDefined(HAVE_CUDA)
9740 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9741 #endif
9742 
9743 /* Schur status updated in the interface */
9744 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9745 {
9746   Mat S = F->schur;
9747 
9748   PetscFunctionBegin;
9749   if (S) {
9750     PetscMPIInt size;
9751     PetscBool   isdense, isdensecuda;
9752 
9753     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9754     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9755     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9756     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9757     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9758     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9759     if (isdense) {
9760       PetscCall(MatSeqDenseInvertFactors_Private(S));
9761     } else if (isdensecuda) {
9762 #if defined(PETSC_HAVE_CUDA)
9763       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9764 #endif
9765     }
9766     // HIP??????????????
9767     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9768   }
9769   PetscFunctionReturn(PETSC_SUCCESS);
9770 }
9771 
9772 /*@
9773   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9774 
9775    Logically Collective
9776 
9777    Input Parameter:
9778 .  F - the factored matrix obtained by calling `MatGetFactor()`
9779 
9780    Level: advanced
9781 
9782    Notes:
9783     Must be called after `MatFactorSetSchurIS()`.
9784 
9785    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9786 
9787 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9788 @*/
9789 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9790 {
9791   PetscFunctionBegin;
9792   PetscValidType(F, 1);
9793   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9794   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9795   PetscCall(MatFactorFactorizeSchurComplement(F));
9796   PetscCall(MatFactorInvertSchurComplement_Private(F));
9797   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9798   PetscFunctionReturn(PETSC_SUCCESS);
9799 }
9800 
9801 /*@
9802   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9803 
9804    Logically Collective
9805 
9806    Input Parameter:
9807 .  F - the factored matrix obtained by calling `MatGetFactor()`
9808 
9809    Level: advanced
9810 
9811    Note:
9812     Must be called after `MatFactorSetSchurIS()`
9813 
9814 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9815 @*/
9816 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9817 {
9818   MatFactorInfo info;
9819 
9820   PetscFunctionBegin;
9821   PetscValidType(F, 1);
9822   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9823   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9824   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9825   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9826   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9827     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9828   } else {
9829     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9830   }
9831   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9832   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9833   PetscFunctionReturn(PETSC_SUCCESS);
9834 }
9835 
9836 /*@
9837    MatPtAP - Creates the matrix product C = P^T * A * P
9838 
9839    Neighbor-wise Collective
9840 
9841    Input Parameters:
9842 +  A - the matrix
9843 .  P - the projection matrix
9844 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9845 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9846           if the result is a dense matrix this is irrelevant
9847 
9848    Output Parameter:
9849 .  C - the product matrix
9850 
9851    Level: intermediate
9852 
9853    Notes:
9854    C will be created and must be destroyed by the user with `MatDestroy()`.
9855 
9856    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9857 
9858    Developer Note:
9859    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9860 
9861 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9862 @*/
9863 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9864 {
9865   PetscFunctionBegin;
9866   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9867   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9868 
9869   if (scall == MAT_INITIAL_MATRIX) {
9870     PetscCall(MatProductCreate(A, P, NULL, C));
9871     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9872     PetscCall(MatProductSetAlgorithm(*C, "default"));
9873     PetscCall(MatProductSetFill(*C, fill));
9874 
9875     (*C)->product->api_user = PETSC_TRUE;
9876     PetscCall(MatProductSetFromOptions(*C));
9877     PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and P %s", MatProductTypes[MATPRODUCT_PtAP], ((PetscObject)A)->type_name, ((PetscObject)P)->type_name);
9878     PetscCall(MatProductSymbolic(*C));
9879   } else { /* scall == MAT_REUSE_MATRIX */
9880     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9881   }
9882 
9883   PetscCall(MatProductNumeric(*C));
9884   (*C)->symmetric = A->symmetric;
9885   (*C)->spd       = A->spd;
9886   PetscFunctionReturn(PETSC_SUCCESS);
9887 }
9888 
9889 /*@
9890    MatRARt - Creates the matrix product C = R * A * R^T
9891 
9892    Neighbor-wise Collective
9893 
9894    Input Parameters:
9895 +  A - the matrix
9896 .  R - the projection matrix
9897 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9898 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9899           if the result is a dense matrix this is irrelevant
9900 
9901    Output Parameter:
9902 .  C - the product matrix
9903 
9904    Level: intermediate
9905 
9906    Notes:
9907    C will be created and must be destroyed by the user with `MatDestroy()`.
9908 
9909    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9910 
9911    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9912    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9913    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9914    We recommend using MatPtAP().
9915 
9916 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9917 @*/
9918 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9919 {
9920   PetscFunctionBegin;
9921   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9922   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9923 
9924   if (scall == MAT_INITIAL_MATRIX) {
9925     PetscCall(MatProductCreate(A, R, NULL, C));
9926     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9927     PetscCall(MatProductSetAlgorithm(*C, "default"));
9928     PetscCall(MatProductSetFill(*C, fill));
9929 
9930     (*C)->product->api_user = PETSC_TRUE;
9931     PetscCall(MatProductSetFromOptions(*C));
9932     PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and R %s", MatProductTypes[MATPRODUCT_RARt], ((PetscObject)A)->type_name, ((PetscObject)R)->type_name);
9933     PetscCall(MatProductSymbolic(*C));
9934   } else { /* scall == MAT_REUSE_MATRIX */
9935     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9936   }
9937 
9938   PetscCall(MatProductNumeric(*C));
9939   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9940   PetscFunctionReturn(PETSC_SUCCESS);
9941 }
9942 
9943 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9944 {
9945   PetscFunctionBegin;
9946   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9947 
9948   if (scall == MAT_INITIAL_MATRIX) {
9949     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9950     PetscCall(MatProductCreate(A, B, NULL, C));
9951     PetscCall(MatProductSetType(*C, ptype));
9952     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9953     PetscCall(MatProductSetFill(*C, fill));
9954 
9955     (*C)->product->api_user = PETSC_TRUE;
9956     PetscCall(MatProductSetFromOptions(*C));
9957     PetscCall(MatProductSymbolic(*C));
9958   } else { /* scall == MAT_REUSE_MATRIX */
9959     Mat_Product *product = (*C)->product;
9960     PetscBool    isdense;
9961 
9962     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9963     if (isdense && product && product->type != ptype) {
9964       PetscCall(MatProductClear(*C));
9965       product = NULL;
9966     }
9967     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9968     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9969       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9970       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9971       product           = (*C)->product;
9972       product->fill     = fill;
9973       product->api_user = PETSC_TRUE;
9974       product->clear    = PETSC_TRUE;
9975 
9976       PetscCall(MatProductSetType(*C, ptype));
9977       PetscCall(MatProductSetFromOptions(*C));
9978       PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for %s and %s", MatProductTypes[ptype], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name);
9979       PetscCall(MatProductSymbolic(*C));
9980     } else { /* user may change input matrices A or B when REUSE */
9981       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9982     }
9983   }
9984   PetscCall(MatProductNumeric(*C));
9985   PetscFunctionReturn(PETSC_SUCCESS);
9986 }
9987 
9988 /*@
9989    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9990 
9991    Neighbor-wise Collective
9992 
9993    Input Parameters:
9994 +  A - the left matrix
9995 .  B - the right matrix
9996 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9997 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9998           if the result is a dense matrix this is irrelevant
9999 
10000    Output Parameter:
10001 .  C - the product matrix
10002 
10003    Notes:
10004    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10005 
10006    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
10007    call to this function with `MAT_INITIAL_MATRIX`.
10008 
10009    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10010 
10011    In the special case where matrix B (and hence C) are dense you can create the correctly sized matrix C yourself and then call this routine with `MAT_REUSE_MATRIX`,
10012    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10013 
10014    Example of Usage:
10015 .vb
10016      MatProductCreate(A,B,NULL,&C);
10017      MatProductSetType(C,MATPRODUCT_AB);
10018      MatProductSymbolic(C);
10019      MatProductNumeric(C); // compute C=A * B
10020      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10021      MatProductNumeric(C);
10022      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10023      MatProductNumeric(C);
10024 .ve
10025 
10026    Level: intermediate
10027 
10028 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10029 @*/
10030 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10031 {
10032   PetscFunctionBegin;
10033   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10034   PetscFunctionReturn(PETSC_SUCCESS);
10035 }
10036 
10037 /*@
10038    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10039 
10040    Neighbor-wise Collective
10041 
10042    Input Parameters:
10043 +  A - the left matrix
10044 .  B - the right matrix
10045 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10046 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10047 
10048    Output Parameter:
10049 .  C - the product matrix
10050 
10051    Level: intermediate
10052 
10053    Notes:
10054    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10055 
10056    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10057 
10058    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10059    actually needed.
10060 
10061    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10062    and for pairs of `MATMPIDENSE` matrices.
10063 
10064    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10065 
10066    Options Database Keys:
10067 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10068               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10069               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10070 
10071 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10072 @*/
10073 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10074 {
10075   PetscFunctionBegin;
10076   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10077   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10078   PetscFunctionReturn(PETSC_SUCCESS);
10079 }
10080 
10081 /*@
10082    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10083 
10084    Neighbor-wise Collective
10085 
10086    Input Parameters:
10087 +  A - the left matrix
10088 .  B - the right matrix
10089 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10090 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10091 
10092    Output Parameter:
10093 .  C - the product matrix
10094 
10095    Level: intermediate
10096 
10097    Notes:
10098    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10099 
10100    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10101 
10102    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10103 
10104    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10105    actually needed.
10106 
10107    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10108    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10109 
10110 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10111 @*/
10112 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10113 {
10114   PetscFunctionBegin;
10115   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10116   PetscFunctionReturn(PETSC_SUCCESS);
10117 }
10118 
10119 /*@
10120    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10121 
10122    Neighbor-wise Collective
10123 
10124    Input Parameters:
10125 +  A - the left matrix
10126 .  B - the middle matrix
10127 .  C - the right matrix
10128 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10129 -  fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
10130           if the result is a dense matrix this is irrelevant
10131 
10132    Output Parameter:
10133 .  D - the product matrix
10134 
10135    Level: intermediate
10136 
10137    Notes:
10138    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10139 
10140    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10141 
10142    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10143 
10144    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10145    actually needed.
10146 
10147    If you have many matrices with the same non-zero structure to multiply, you
10148    should use `MAT_REUSE_MATRIX` in all calls but the first
10149 
10150 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10151 @*/
10152 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10153 {
10154   PetscFunctionBegin;
10155   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10156   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10157 
10158   if (scall == MAT_INITIAL_MATRIX) {
10159     PetscCall(MatProductCreate(A, B, C, D));
10160     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10161     PetscCall(MatProductSetAlgorithm(*D, "default"));
10162     PetscCall(MatProductSetFill(*D, fill));
10163 
10164     (*D)->product->api_user = PETSC_TRUE;
10165     PetscCall(MatProductSetFromOptions(*D));
10166     PetscCheck((*D)->ops->productsymbolic, PetscObjectComm((PetscObject)(*D)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s, B %s and C %s", MatProductTypes[MATPRODUCT_ABC], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name,
10167                ((PetscObject)C)->type_name);
10168     PetscCall(MatProductSymbolic(*D));
10169   } else { /* user may change input matrices when REUSE */
10170     PetscCall(MatProductReplaceMats(A, B, C, *D));
10171   }
10172   PetscCall(MatProductNumeric(*D));
10173   PetscFunctionReturn(PETSC_SUCCESS);
10174 }
10175 
10176 /*@
10177    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10178 
10179    Collective
10180 
10181    Input Parameters:
10182 +  mat - the matrix
10183 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10184 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10185 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10186 
10187    Output Parameter:
10188 .  matredundant - redundant matrix
10189 
10190    Level: advanced
10191 
10192    Notes:
10193    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10194    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10195 
10196    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10197    calling it.
10198 
10199    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10200 
10201 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10202 @*/
10203 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10204 {
10205   MPI_Comm       comm;
10206   PetscMPIInt    size;
10207   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10208   Mat_Redundant *redund     = NULL;
10209   PetscSubcomm   psubcomm   = NULL;
10210   MPI_Comm       subcomm_in = subcomm;
10211   Mat           *matseq;
10212   IS             isrow, iscol;
10213   PetscBool      newsubcomm = PETSC_FALSE;
10214 
10215   PetscFunctionBegin;
10216   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10217   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10218     PetscValidPointer(*matredundant, 5);
10219     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10220   }
10221 
10222   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10223   if (size == 1 || nsubcomm == 1) {
10224     if (reuse == MAT_INITIAL_MATRIX) {
10225       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10226     } else {
10227       PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10228       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10229     }
10230     PetscFunctionReturn(PETSC_SUCCESS);
10231   }
10232 
10233   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10234   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10235   MatCheckPreallocated(mat, 1);
10236 
10237   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10238   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10239     /* create psubcomm, then get subcomm */
10240     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10241     PetscCallMPI(MPI_Comm_size(comm, &size));
10242     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10243 
10244     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10245     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10246     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10247     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10248     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10249     newsubcomm = PETSC_TRUE;
10250     PetscCall(PetscSubcommDestroy(&psubcomm));
10251   }
10252 
10253   /* get isrow, iscol and a local sequential matrix matseq[0] */
10254   if (reuse == MAT_INITIAL_MATRIX) {
10255     mloc_sub = PETSC_DECIDE;
10256     nloc_sub = PETSC_DECIDE;
10257     if (bs < 1) {
10258       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10259       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10260     } else {
10261       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10262       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10263     }
10264     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10265     rstart = rend - mloc_sub;
10266     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10267     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10268   } else { /* reuse == MAT_REUSE_MATRIX */
10269     PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10270     /* retrieve subcomm */
10271     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10272     redund = (*matredundant)->redundant;
10273     isrow  = redund->isrow;
10274     iscol  = redund->iscol;
10275     matseq = redund->matseq;
10276   }
10277   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10278 
10279   /* get matredundant over subcomm */
10280   if (reuse == MAT_INITIAL_MATRIX) {
10281     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10282 
10283     /* create a supporting struct and attach it to C for reuse */
10284     PetscCall(PetscNew(&redund));
10285     (*matredundant)->redundant = redund;
10286     redund->isrow              = isrow;
10287     redund->iscol              = iscol;
10288     redund->matseq             = matseq;
10289     if (newsubcomm) {
10290       redund->subcomm = subcomm;
10291     } else {
10292       redund->subcomm = MPI_COMM_NULL;
10293     }
10294   } else {
10295     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10296   }
10297 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10298   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10299     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10300     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10301   }
10302 #endif
10303   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10304   PetscFunctionReturn(PETSC_SUCCESS);
10305 }
10306 
10307 /*@C
10308    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10309    a given `Mat`. Each submatrix can span multiple procs.
10310 
10311    Collective
10312 
10313    Input Parameters:
10314 +  mat - the matrix
10315 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10316 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10317 
10318    Output Parameter:
10319 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10320 
10321   Level: advanced
10322 
10323   Notes:
10324   The submatrix partition across processors is dictated by `subComm` a
10325   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10326   is not restricted to be grouped with consecutive original ranks.
10327 
10328   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10329   map directly to the layout of the original matrix [wrt the local
10330   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10331   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10332   the `subMat`. However the offDiagMat looses some columns - and this is
10333   reconstructed with `MatSetValues()`
10334 
10335   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10336 
10337 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10338 @*/
10339 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10340 {
10341   PetscMPIInt commsize, subCommSize;
10342 
10343   PetscFunctionBegin;
10344   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10345   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10346   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10347 
10348   PetscCheck(scall != MAT_REUSE_MATRIX || *subMat != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10349   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10350   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10351   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10352   PetscFunctionReturn(PETSC_SUCCESS);
10353 }
10354 
10355 /*@
10356    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10357 
10358    Not Collective
10359 
10360    Input Parameters:
10361 +  mat - matrix to extract local submatrix from
10362 .  isrow - local row indices for submatrix
10363 -  iscol - local column indices for submatrix
10364 
10365    Output Parameter:
10366 .  submat - the submatrix
10367 
10368    Level: intermediate
10369 
10370    Notes:
10371    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10372 
10373    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10374    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10375 
10376    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10377    `MatSetValuesBlockedLocal()` will also be implemented.
10378 
10379    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10380    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10381 
10382 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10383 @*/
10384 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10385 {
10386   PetscFunctionBegin;
10387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10388   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10389   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10390   PetscCheckSameComm(isrow, 2, iscol, 3);
10391   PetscValidPointer(submat, 4);
10392   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10393 
10394   if (mat->ops->getlocalsubmatrix) {
10395     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10396   } else {
10397     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10398   }
10399   PetscFunctionReturn(PETSC_SUCCESS);
10400 }
10401 
10402 /*@
10403    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10404 
10405    Not Collective
10406 
10407    Input Parameters:
10408 +  mat - matrix to extract local submatrix from
10409 .  isrow - local row indices for submatrix
10410 .  iscol - local column indices for submatrix
10411 -  submat - the submatrix
10412 
10413    Level: intermediate
10414 
10415 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10416 @*/
10417 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10418 {
10419   PetscFunctionBegin;
10420   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10421   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10422   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10423   PetscCheckSameComm(isrow, 2, iscol, 3);
10424   PetscValidPointer(submat, 4);
10425   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10426 
10427   if (mat->ops->restorelocalsubmatrix) {
10428     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10429   } else {
10430     PetscCall(MatDestroy(submat));
10431   }
10432   *submat = NULL;
10433   PetscFunctionReturn(PETSC_SUCCESS);
10434 }
10435 
10436 /*@
10437    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10438 
10439    Collective
10440 
10441    Input Parameter:
10442 .  mat - the matrix
10443 
10444    Output Parameter:
10445 .  is - if any rows have zero diagonals this contains the list of them
10446 
10447    Level: developer
10448 
10449 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10450 @*/
10451 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10452 {
10453   PetscFunctionBegin;
10454   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10455   PetscValidType(mat, 1);
10456   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10457   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10458 
10459   if (!mat->ops->findzerodiagonals) {
10460     Vec                diag;
10461     const PetscScalar *a;
10462     PetscInt          *rows;
10463     PetscInt           rStart, rEnd, r, nrow = 0;
10464 
10465     PetscCall(MatCreateVecs(mat, &diag, NULL));
10466     PetscCall(MatGetDiagonal(mat, diag));
10467     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10468     PetscCall(VecGetArrayRead(diag, &a));
10469     for (r = 0; r < rEnd - rStart; ++r)
10470       if (a[r] == 0.0) ++nrow;
10471     PetscCall(PetscMalloc1(nrow, &rows));
10472     nrow = 0;
10473     for (r = 0; r < rEnd - rStart; ++r)
10474       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10475     PetscCall(VecRestoreArrayRead(diag, &a));
10476     PetscCall(VecDestroy(&diag));
10477     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10478   } else {
10479     PetscUseTypeMethod(mat, findzerodiagonals, is);
10480   }
10481   PetscFunctionReturn(PETSC_SUCCESS);
10482 }
10483 
10484 /*@
10485    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10486 
10487    Collective
10488 
10489    Input Parameter:
10490 .  mat - the matrix
10491 
10492    Output Parameter:
10493 .  is - contains the list of rows with off block diagonal entries
10494 
10495    Level: developer
10496 
10497 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10498 @*/
10499 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10500 {
10501   PetscFunctionBegin;
10502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10503   PetscValidType(mat, 1);
10504   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10505   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10506 
10507   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10508   PetscFunctionReturn(PETSC_SUCCESS);
10509 }
10510 
10511 /*@C
10512   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10513 
10514   Collective; No Fortran Support
10515 
10516   Input Parameter:
10517 . mat - the matrix
10518 
10519   Output Parameter:
10520 . values - the block inverses in column major order (FORTRAN-like)
10521 
10522   Level: advanced
10523 
10524    Notes:
10525    The size of the blocks is determined by the block size of the matrix.
10526 
10527    The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10528 
10529    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10530 
10531 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10532 @*/
10533 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10534 {
10535   PetscFunctionBegin;
10536   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10537   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10538   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10539   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10540   PetscFunctionReturn(PETSC_SUCCESS);
10541 }
10542 
10543 /*@C
10544   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10545 
10546   Collective; No Fortran Support
10547 
10548   Input Parameters:
10549 + mat - the matrix
10550 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10551 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10552 
10553   Output Parameter:
10554 . values - the block inverses in column major order (FORTRAN-like)
10555 
10556   Level: advanced
10557 
10558   Notes:
10559   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10560 
10561   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10562 
10563 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10564 @*/
10565 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10566 {
10567   PetscFunctionBegin;
10568   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10569   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10570   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10571   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10572   PetscFunctionReturn(PETSC_SUCCESS);
10573 }
10574 
10575 /*@
10576   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10577 
10578   Collective
10579 
10580   Input Parameters:
10581 + A - the matrix
10582 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10583 
10584   Level: advanced
10585 
10586   Note:
10587   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10588 
10589 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10590 @*/
10591 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10592 {
10593   const PetscScalar *vals;
10594   PetscInt          *dnnz;
10595   PetscInt           m, rstart, rend, bs, i, j;
10596 
10597   PetscFunctionBegin;
10598   PetscCall(MatInvertBlockDiagonal(A, &vals));
10599   PetscCall(MatGetBlockSize(A, &bs));
10600   PetscCall(MatGetLocalSize(A, &m, NULL));
10601   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10602   PetscCall(PetscMalloc1(m / bs, &dnnz));
10603   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10604   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10605   PetscCall(PetscFree(dnnz));
10606   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10607   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10608   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10609   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10610   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10611   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10612   PetscFunctionReturn(PETSC_SUCCESS);
10613 }
10614 
10615 /*@C
10616     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10617     via `MatTransposeColoringCreate()`.
10618 
10619     Collective
10620 
10621     Input Parameter:
10622 .   c - coloring context
10623 
10624     Level: intermediate
10625 
10626 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10627 @*/
10628 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10629 {
10630   MatTransposeColoring matcolor = *c;
10631 
10632   PetscFunctionBegin;
10633   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10634   if (--((PetscObject)matcolor)->refct > 0) {
10635     matcolor = NULL;
10636     PetscFunctionReturn(PETSC_SUCCESS);
10637   }
10638 
10639   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10640   PetscCall(PetscFree(matcolor->rows));
10641   PetscCall(PetscFree(matcolor->den2sp));
10642   PetscCall(PetscFree(matcolor->colorforcol));
10643   PetscCall(PetscFree(matcolor->columns));
10644   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10645   PetscCall(PetscHeaderDestroy(c));
10646   PetscFunctionReturn(PETSC_SUCCESS);
10647 }
10648 
10649 /*@C
10650     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10651     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10652     `MatTransposeColoring` to sparse B.
10653 
10654     Collective
10655 
10656     Input Parameters:
10657 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10658 -   B - sparse matrix
10659 
10660     Output Parameter:
10661 .   Btdense - dense matrix B^T
10662 
10663     Level: developer
10664 
10665     Note:
10666     These are used internally for some implementations of `MatRARt()`
10667 
10668 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10669 @*/
10670 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10671 {
10672   PetscFunctionBegin;
10673   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10674   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10675   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10676 
10677   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10678   PetscFunctionReturn(PETSC_SUCCESS);
10679 }
10680 
10681 /*@C
10682     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10683     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10684     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10685     `Csp` from `Cden`.
10686 
10687     Collective
10688 
10689     Input Parameters:
10690 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10691 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10692 
10693     Output Parameter:
10694 .   Csp - sparse matrix
10695 
10696     Level: developer
10697 
10698     Note:
10699     These are used internally for some implementations of `MatRARt()`
10700 
10701 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10702 @*/
10703 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10704 {
10705   PetscFunctionBegin;
10706   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10707   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10708   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10709 
10710   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10711   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10712   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10713   PetscFunctionReturn(PETSC_SUCCESS);
10714 }
10715 
10716 /*@C
10717    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10718 
10719    Collective
10720 
10721    Input Parameters:
10722 +  mat - the matrix product C
10723 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10724 
10725     Output Parameter:
10726 .   color - the new coloring context
10727 
10728     Level: intermediate
10729 
10730 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10731           `MatTransColoringApplyDenToSp()`
10732 @*/
10733 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10734 {
10735   MatTransposeColoring c;
10736   MPI_Comm             comm;
10737 
10738   PetscFunctionBegin;
10739   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10740   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10741   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10742 
10743   c->ctype = iscoloring->ctype;
10744   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10745 
10746   *color = c;
10747   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10748   PetscFunctionReturn(PETSC_SUCCESS);
10749 }
10750 
10751 /*@
10752       MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10753         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10754         same, otherwise it will be larger
10755 
10756      Not Collective
10757 
10758   Input Parameter:
10759 .    A  - the matrix
10760 
10761   Output Parameter:
10762 .    state - the current state
10763 
10764   Level: intermediate
10765 
10766   Notes:
10767     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10768          different matrices
10769 
10770     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10771 
10772     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10773 
10774 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10775 @*/
10776 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10777 {
10778   PetscFunctionBegin;
10779   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10780   *state = mat->nonzerostate;
10781   PetscFunctionReturn(PETSC_SUCCESS);
10782 }
10783 
10784 /*@
10785       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10786                  matrices from each processor
10787 
10788     Collective
10789 
10790    Input Parameters:
10791 +    comm - the communicators the parallel matrix will live on
10792 .    seqmat - the input sequential matrices
10793 .    n - number of local columns (or `PETSC_DECIDE`)
10794 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10795 
10796    Output Parameter:
10797 .    mpimat - the parallel matrix generated
10798 
10799     Level: developer
10800 
10801    Note:
10802     The number of columns of the matrix in EACH processor MUST be the same.
10803 
10804 .seealso: [](chapter_matrices), `Mat`
10805 @*/
10806 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10807 {
10808   PetscMPIInt size;
10809 
10810   PetscFunctionBegin;
10811   PetscCallMPI(MPI_Comm_size(comm, &size));
10812   if (size == 1) {
10813     if (reuse == MAT_INITIAL_MATRIX) {
10814       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10815     } else {
10816       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10817     }
10818     PetscFunctionReturn(PETSC_SUCCESS);
10819   }
10820 
10821   PetscCheck(reuse != MAT_REUSE_MATRIX || seqmat != *mpimat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10822 
10823   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10824   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10825   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10826   PetscFunctionReturn(PETSC_SUCCESS);
10827 }
10828 
10829 /*@
10830      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10831 
10832     Collective
10833 
10834    Input Parameters:
10835 +    A   - the matrix to create subdomains from
10836 -    N   - requested number of subdomains
10837 
10838    Output Parameters:
10839 +    n   - number of subdomains resulting on this MPI process
10840 -    iss - `IS` list with indices of subdomains on this MPI process
10841 
10842     Level: advanced
10843 
10844     Note:
10845     The number of subdomains must be smaller than the communicator size
10846 
10847 .seealso: [](chapter_matrices), `Mat`, `IS`
10848 @*/
10849 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10850 {
10851   MPI_Comm    comm, subcomm;
10852   PetscMPIInt size, rank, color;
10853   PetscInt    rstart, rend, k;
10854 
10855   PetscFunctionBegin;
10856   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10857   PetscCallMPI(MPI_Comm_size(comm, &size));
10858   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10859   PetscCheck(N >= 1 && N < (PetscInt)size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N);
10860   *n    = 1;
10861   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10862   color = rank / k;
10863   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10864   PetscCall(PetscMalloc1(1, iss));
10865   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10866   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10867   PetscCallMPI(MPI_Comm_free(&subcomm));
10868   PetscFunctionReturn(PETSC_SUCCESS);
10869 }
10870 
10871 /*@
10872    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10873 
10874    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10875    If they are not the same, uses `MatMatMatMult()`.
10876 
10877    Once the coarse grid problem is constructed, correct for interpolation operators
10878    that are not of full rank, which can legitimately happen in the case of non-nested
10879    geometric multigrid.
10880 
10881    Input Parameters:
10882 +  restrct - restriction operator
10883 .  dA - fine grid matrix
10884 .  interpolate - interpolation operator
10885 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10886 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10887 
10888    Output Parameter:
10889 .  A - the Galerkin coarse matrix
10890 
10891    Options Database Key:
10892 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10893 
10894    Level: developer
10895 
10896 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10897 @*/
10898 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10899 {
10900   IS  zerorows;
10901   Vec diag;
10902 
10903   PetscFunctionBegin;
10904   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10905   /* Construct the coarse grid matrix */
10906   if (interpolate == restrct) {
10907     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10908   } else {
10909     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10910   }
10911 
10912   /* If the interpolation matrix is not of full rank, A will have zero rows.
10913      This can legitimately happen in the case of non-nested geometric multigrid.
10914      In that event, we set the rows of the matrix to the rows of the identity,
10915      ignoring the equations (as the RHS will also be zero). */
10916 
10917   PetscCall(MatFindZeroRows(*A, &zerorows));
10918 
10919   if (zerorows != NULL) { /* if there are any zero rows */
10920     PetscCall(MatCreateVecs(*A, &diag, NULL));
10921     PetscCall(MatGetDiagonal(*A, diag));
10922     PetscCall(VecISSet(diag, zerorows, 1.0));
10923     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10924     PetscCall(VecDestroy(&diag));
10925     PetscCall(ISDestroy(&zerorows));
10926   }
10927   PetscFunctionReturn(PETSC_SUCCESS);
10928 }
10929 
10930 /*@C
10931     MatSetOperation - Allows user to set a matrix operation for any matrix type
10932 
10933    Logically Collective
10934 
10935     Input Parameters:
10936 +   mat - the matrix
10937 .   op - the name of the operation
10938 -   f - the function that provides the operation
10939 
10940    Level: developer
10941 
10942     Usage:
10943 .vb
10944   extern PetscErrorCode usermult(Mat, Vec, Vec);
10945 
10946   PetscCall(MatCreateXXX(comm, ..., &A));
10947   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10948 .ve
10949 
10950     Notes:
10951     See the file `include/petscmat.h` for a complete list of matrix
10952     operations, which all have the form MATOP_<OPERATION>, where
10953     <OPERATION> is the name (in all capital letters) of the
10954     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10955 
10956     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10957     sequence as the usual matrix interface routines, since they
10958     are intended to be accessed via the usual matrix interface
10959     routines, e.g.,
10960 .vb
10961   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10962 .ve
10963 
10964     In particular each function MUST return `PETSC_SUCCESS` on success and
10965     nonzero on failure.
10966 
10967     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10968 
10969 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10970 @*/
10971 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10972 {
10973   PetscFunctionBegin;
10974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10975   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10976   (((void (**)(void))mat->ops)[op]) = f;
10977   PetscFunctionReturn(PETSC_SUCCESS);
10978 }
10979 
10980 /*@C
10981     MatGetOperation - Gets a matrix operation for any matrix type.
10982 
10983     Not Collective
10984 
10985     Input Parameters:
10986 +   mat - the matrix
10987 -   op - the name of the operation
10988 
10989     Output Parameter:
10990 .   f - the function that provides the operation
10991 
10992     Level: developer
10993 
10994     Usage:
10995 .vb
10996       PetscErrorCode (*usermult)(Mat, Vec, Vec);
10997       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
10998 .ve
10999 
11000     Notes:
11001     See the file include/petscmat.h for a complete list of matrix
11002     operations, which all have the form MATOP_<OPERATION>, where
11003     <OPERATION> is the name (in all capital letters) of the
11004     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11005 
11006     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11007 
11008 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11009 @*/
11010 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11011 {
11012   PetscFunctionBegin;
11013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11014   *f = (((void (**)(void))mat->ops)[op]);
11015   PetscFunctionReturn(PETSC_SUCCESS);
11016 }
11017 
11018 /*@
11019     MatHasOperation - Determines whether the given matrix supports the particular operation.
11020 
11021    Not Collective
11022 
11023    Input Parameters:
11024 +  mat - the matrix
11025 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11026 
11027    Output Parameter:
11028 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11029 
11030    Level: advanced
11031 
11032    Note:
11033    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11034 
11035 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11036 @*/
11037 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11038 {
11039   PetscFunctionBegin;
11040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11041   PetscValidBoolPointer(has, 3);
11042   if (mat->ops->hasoperation) {
11043     PetscUseTypeMethod(mat, hasoperation, op, has);
11044   } else {
11045     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11046     else {
11047       *has = PETSC_FALSE;
11048       if (op == MATOP_CREATE_SUBMATRIX) {
11049         PetscMPIInt size;
11050 
11051         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11052         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11053       }
11054     }
11055   }
11056   PetscFunctionReturn(PETSC_SUCCESS);
11057 }
11058 
11059 /*@
11060     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11061 
11062    Collective
11063 
11064    Input Parameter:
11065 .  mat - the matrix
11066 
11067    Output Parameter:
11068 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11069 
11070    Level: beginner
11071 
11072 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11073 @*/
11074 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11075 {
11076   PetscFunctionBegin;
11077   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11078   PetscValidType(mat, 1);
11079   PetscValidBoolPointer(cong, 2);
11080   if (!mat->rmap || !mat->cmap) {
11081     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11082     PetscFunctionReturn(PETSC_SUCCESS);
11083   }
11084   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11085     PetscCall(PetscLayoutSetUp(mat->rmap));
11086     PetscCall(PetscLayoutSetUp(mat->cmap));
11087     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11088     if (*cong) mat->congruentlayouts = 1;
11089     else mat->congruentlayouts = 0;
11090   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11091   PetscFunctionReturn(PETSC_SUCCESS);
11092 }
11093 
11094 PetscErrorCode MatSetInf(Mat A)
11095 {
11096   PetscFunctionBegin;
11097   PetscUseTypeMethod(A, setinf);
11098   PetscFunctionReturn(PETSC_SUCCESS);
11099 }
11100 
11101 /*@C
11102    MatCreateGraph - create a scalar matrix (that is a matrix with one vertex for each block vertex in the original matrix), for use in graph algorithms
11103    and possibly removes small values from the graph structure.
11104 
11105    Collective
11106 
11107    Input Parameters:
11108 +  A - the matrix
11109 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11110 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11111 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11112 
11113    Output Parameter:
11114 .  graph - the resulting graph
11115 
11116    Level: advanced
11117 
11118 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11119 @*/
11120 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11121 {
11122   PetscFunctionBegin;
11123   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11124   PetscValidType(A, 1);
11125   PetscValidLogicalCollectiveBool(A, scale, 3);
11126   PetscValidPointer(graph, 5);
11127   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11128   PetscFunctionReturn(PETSC_SUCCESS);
11129 }
11130 
11131 /*@
11132   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11133   meaning the same memory is used for the matrix, and no new memory is allocated.
11134 
11135   Collective
11136 
11137   Input Parameter:
11138 . A - the matrix
11139 
11140   Level: intermediate
11141 
11142   Developer Note:
11143   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11144   of the arrays in the data structure are unneeded.
11145 
11146 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11147 @*/
11148 PetscErrorCode MatEliminateZeros(Mat A)
11149 {
11150   PetscFunctionBegin;
11151   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11152   PetscUseTypeMethod(A, eliminatezeros);
11153   PetscFunctionReturn(PETSC_SUCCESS);
11154 }
11155