xref: /petsc/src/mat/interface/matrix.c (revision b2e8165f902b29d33cb5c6fcd6da9ceca759ca7a)
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, MAT_HIPCopyToGPU;
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 nonzero locations, it fills the locations with random numbers.
73 
74   It generates an error if used on unassembled sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `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: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
130 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
149 . mat - the factored matrix
150 
151   Output Parameter:
152 . err - the error code
153 
154   Level: advanced
155 
156   Note:
157   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172   MatFactorClearError - clears the error code in a factorization
173 
174   Logically Collective
175 
176   Input Parameter:
177 . mat - the factored matrix
178 
179   Level: developer
180 
181   Note:
182   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n, st;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
207     PetscCall(MatGetSize(mat, &N, NULL));
208     PetscCall(MatGetLocalSize(mat, &n, NULL));
209     PetscCall(VecSet(l, 0.0));
210     PetscCall(VecSetRandom(r, NULL));
211     PetscCall(MatMult(mat, r, l));
212     PetscCall(VecGetArrayRead(l, &al));
213   } else { /* nonzero columns */
214     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
215     PetscCall(MatGetSize(mat, NULL, &N));
216     PetscCall(MatGetLocalSize(mat, NULL, &n));
217     PetscCall(VecSet(r, 0.0));
218     PetscCall(VecSetRandom(l, NULL));
219     PetscCall(MatMultTranspose(mat, l, r));
220     PetscCall(VecGetArrayRead(r, &al));
221   }
222   if (tol <= 0.0) {
223     for (i = 0, nz = 0; i < n; i++)
224       if (al[i] != 0.0) nz++;
225   } else {
226     for (i = 0, nz = 0; i < n; i++)
227       if (PetscAbsScalar(al[i]) > tol) nz++;
228   }
229   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
230   if (gnz != N) {
231     PetscInt *nzr;
232     PetscCall(PetscMalloc1(nz, &nzr));
233     if (nz) {
234       if (tol < 0) {
235         for (i = 0, nz = 0; i < n; i++)
236           if (al[i] != 0.0) nzr[nz++] = i + st;
237       } else {
238         for (i = 0, nz = 0; i < n; i++)
239           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
240       }
241     }
242     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
243   } else *nonzero = NULL;
244   if (!cols) { /* nonzero rows */
245     PetscCall(VecRestoreArrayRead(l, &al));
246   } else {
247     PetscCall(VecRestoreArrayRead(r, &al));
248   }
249   PetscCall(VecDestroy(&l));
250   PetscCall(VecDestroy(&r));
251   PetscFunctionReturn(PETSC_SUCCESS);
252 }
253 
254 /*@
255   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
256 
257   Input Parameter:
258 . mat - the matrix
259 
260   Output Parameter:
261 . keptrows - the rows that are not completely zero
262 
263   Level: intermediate
264 
265   Note:
266   `keptrows` is set to `NULL` if all rows are nonzero.
267 
268   Developer Note:
269   If `keptrows` is not `NULL`, it must be sorted.
270 
271 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
272  @*/
273 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
274 {
275   PetscFunctionBegin;
276   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
277   PetscValidType(mat, 1);
278   PetscAssertPointer(keptrows, 2);
279   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
280   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
281   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
282   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
283   if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
284   PetscFunctionReturn(PETSC_SUCCESS);
285 }
286 
287 /*@
288   MatFindZeroRows - Locate all rows that are completely zero in the matrix
289 
290   Input Parameter:
291 . mat - the matrix
292 
293   Output Parameter:
294 . zerorows - the rows that are completely zero
295 
296   Level: intermediate
297 
298   Note:
299   `zerorows` is set to `NULL` if no rows are zero.
300 
301 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
302  @*/
303 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
304 {
305   IS       keptrows;
306   PetscInt m, n;
307 
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
310   PetscValidType(mat, 1);
311   PetscAssertPointer(zerorows, 2);
312   PetscCall(MatFindNonzeroRows(mat, &keptrows));
313   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
314      In keeping with this convention, we set zerorows to NULL if there are no zero
315      rows. */
316   if (keptrows == NULL) {
317     *zerorows = NULL;
318   } else {
319     PetscCall(MatGetOwnershipRange(mat, &m, &n));
320     PetscCall(ISComplement(keptrows, m, n, zerorows));
321     PetscCall(ISDestroy(&keptrows));
322   }
323   PetscFunctionReturn(PETSC_SUCCESS);
324 }
325 
326 /*@
327   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
328 
329   Not Collective
330 
331   Input Parameter:
332 . A - the matrix
333 
334   Output Parameter:
335 . a - the diagonal part (which is a SEQUENTIAL matrix)
336 
337   Level: advanced
338 
339   Notes:
340   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
341 
342   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
343 
344 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
345 @*/
346 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
347 {
348   PetscFunctionBegin;
349   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
350   PetscValidType(A, 1);
351   PetscAssertPointer(a, 2);
352   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
353   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
354   else {
355     PetscMPIInt size;
356 
357     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
358     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
359     *a = A;
360   }
361   PetscFunctionReturn(PETSC_SUCCESS);
362 }
363 
364 /*@
365   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
366 
367   Collective
368 
369   Input Parameter:
370 . mat - the matrix
371 
372   Output Parameter:
373 . trace - the sum of the diagonal entries
374 
375   Level: advanced
376 
377 .seealso: [](ch_matrices), `Mat`
378 @*/
379 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
380 {
381   Vec diag;
382 
383   PetscFunctionBegin;
384   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
385   PetscAssertPointer(trace, 2);
386   PetscCall(MatCreateVecs(mat, &diag, NULL));
387   PetscCall(MatGetDiagonal(mat, diag));
388   PetscCall(VecSum(diag, trace));
389   PetscCall(VecDestroy(&diag));
390   PetscFunctionReturn(PETSC_SUCCESS);
391 }
392 
393 /*@
394   MatRealPart - Zeros out the imaginary part of the matrix
395 
396   Logically Collective
397 
398   Input Parameter:
399 . mat - the matrix
400 
401   Level: advanced
402 
403 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
404 @*/
405 PetscErrorCode MatRealPart(Mat mat)
406 {
407   PetscFunctionBegin;
408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
409   PetscValidType(mat, 1);
410   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
411   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
412   MatCheckPreallocated(mat, 1);
413   PetscUseTypeMethod(mat, realpart);
414   PetscFunctionReturn(PETSC_SUCCESS);
415 }
416 
417 /*@C
418   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
419 
420   Collective
421 
422   Input Parameter:
423 . mat - the matrix
424 
425   Output Parameters:
426 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
427 - ghosts  - the global indices of the ghost points
428 
429   Level: advanced
430 
431   Note:
432   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
433 
434 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
435 @*/
436 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
437 {
438   PetscFunctionBegin;
439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
440   PetscValidType(mat, 1);
441   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
442   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
443   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
444   else {
445     if (nghosts) *nghosts = 0;
446     if (ghosts) *ghosts = NULL;
447   }
448   PetscFunctionReturn(PETSC_SUCCESS);
449 }
450 
451 /*@
452   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
453 
454   Logically Collective
455 
456   Input Parameter:
457 . mat - the matrix
458 
459   Level: advanced
460 
461 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
462 @*/
463 PetscErrorCode MatImaginaryPart(Mat mat)
464 {
465   PetscFunctionBegin;
466   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
467   PetscValidType(mat, 1);
468   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
469   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
470   MatCheckPreallocated(mat, 1);
471   PetscUseTypeMethod(mat, imaginarypart);
472   PetscFunctionReturn(PETSC_SUCCESS);
473 }
474 
475 /*@
476   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
477 
478   Not Collective
479 
480   Input Parameter:
481 . mat - the matrix
482 
483   Output Parameters:
484 + missing - is any diagonal entry missing
485 - dd      - first diagonal entry that is missing (optional) on this process
486 
487   Level: advanced
488 
489   Note:
490   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
491 
492 .seealso: [](ch_matrices), `Mat`
493 @*/
494 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
495 {
496   PetscFunctionBegin;
497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
498   PetscValidType(mat, 1);
499   PetscAssertPointer(missing, 2);
500   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
501   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
502   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
503   PetscFunctionReturn(PETSC_SUCCESS);
504 }
505 
506 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
507 /*@C
508   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
509   for each row that you get to ensure that your application does
510   not bleed memory.
511 
512   Not Collective
513 
514   Input Parameters:
515 + mat - the matrix
516 - row - the row to get
517 
518   Output Parameters:
519 + ncols - if not `NULL`, the number of nonzeros in `row`
520 . cols  - if not `NULL`, the column numbers
521 - vals  - if not `NULL`, the numerical values
522 
523   Level: advanced
524 
525   Notes:
526   This routine is provided for people who need to have direct access
527   to the structure of a matrix.  We hope that we provide enough
528   high-level matrix routines that few users will need it.
529 
530   `MatGetRow()` always returns 0-based column indices, regardless of
531   whether the internal representation is 0-based (default) or 1-based.
532 
533   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
534   not wish to extract these quantities.
535 
536   The user can only examine the values extracted with `MatGetRow()`;
537   the values CANNOT be altered.  To change the matrix entries, one
538   must use `MatSetValues()`.
539 
540   You can only have one call to `MatGetRow()` outstanding for a particular
541   matrix at a time, per processor. `MatGetRow()` can only obtain rows
542   associated with the given processor, it cannot get rows from the
543   other processors; for that we suggest using `MatCreateSubMatrices()`, then
544   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
545   is in the global number of rows.
546 
547   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
548 
549   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
550 
551   Fortran Note:
552   The calling sequence is
553 .vb
554    MatGetRow(matrix,row,ncols,cols,values,ierr)
555          Mat     matrix (input)
556          integer row    (input)
557          integer ncols  (output)
558          integer cols(maxcols) (output)
559          double precision (or double complex) values(maxcols) output
560 .ve
561   where maxcols >= maximum nonzeros in any row of the matrix.
562 
563 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
564 @*/
565 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
566 {
567   PetscInt incols;
568 
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
571   PetscValidType(mat, 1);
572   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
573   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
574   MatCheckPreallocated(mat, 1);
575   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);
576   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
577   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
578   if (ncols) *ncols = incols;
579   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
580   PetscFunctionReturn(PETSC_SUCCESS);
581 }
582 
583 /*@
584   MatConjugate - replaces the matrix values with their complex conjugates
585 
586   Logically Collective
587 
588   Input Parameter:
589 . mat - the matrix
590 
591   Level: advanced
592 
593 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
594 @*/
595 PetscErrorCode MatConjugate(Mat mat)
596 {
597   PetscFunctionBegin;
598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
599   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
600   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
601     PetscUseTypeMethod(mat, conjugate);
602     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
603   }
604   PetscFunctionReturn(PETSC_SUCCESS);
605 }
606 
607 /*@C
608   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
609 
610   Not Collective
611 
612   Input Parameters:
613 + mat   - the matrix
614 . row   - the row to get
615 . ncols - the number of nonzeros
616 . cols  - the columns of the nonzeros
617 - vals  - if nonzero the column values
618 
619   Level: advanced
620 
621   Notes:
622   This routine should be called after you have finished examining the entries.
623 
624   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
625   us of the array after it has been restored. If you pass `NULL`, it will
626   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
627 
628   Fortran Notes:
629   The calling sequence is
630 .vb
631    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
632       Mat     matrix (input)
633       integer row    (input)
634       integer ncols  (output)
635       integer cols(maxcols) (output)
636       double precision (or double complex) values(maxcols) output
637 .ve
638   Where maxcols >= maximum nonzeros in any row of the matrix.
639 
640   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
641   before another call to `MatGetRow()` can be made.
642 
643 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
644 @*/
645 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
646 {
647   PetscFunctionBegin;
648   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
649   if (ncols) PetscAssertPointer(ncols, 3);
650   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
651   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
652   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
653   if (ncols) *ncols = 0;
654   if (cols) *cols = NULL;
655   if (vals) *vals = NULL;
656   PetscFunctionReturn(PETSC_SUCCESS);
657 }
658 
659 /*@
660   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
661   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
662 
663   Not Collective
664 
665   Input Parameter:
666 . mat - the matrix
667 
668   Level: advanced
669 
670   Note:
671   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.
672 
673 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
674 @*/
675 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
676 {
677   PetscFunctionBegin;
678   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
679   PetscValidType(mat, 1);
680   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
681   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
682   MatCheckPreallocated(mat, 1);
683   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
684   PetscUseTypeMethod(mat, getrowuppertriangular);
685   PetscFunctionReturn(PETSC_SUCCESS);
686 }
687 
688 /*@
689   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
690 
691   Not Collective
692 
693   Input Parameter:
694 . mat - the matrix
695 
696   Level: advanced
697 
698   Note:
699   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
700 
701 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
702 @*/
703 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
704 {
705   PetscFunctionBegin;
706   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
707   PetscValidType(mat, 1);
708   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
709   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
710   MatCheckPreallocated(mat, 1);
711   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
712   PetscUseTypeMethod(mat, restorerowuppertriangular);
713   PetscFunctionReturn(PETSC_SUCCESS);
714 }
715 
716 /*@
717   MatSetOptionsPrefix - Sets the prefix used for searching for all
718   `Mat` options in the database.
719 
720   Logically Collective
721 
722   Input Parameters:
723 + A      - the matrix
724 - prefix - the prefix to prepend to all option names
725 
726   Level: advanced
727 
728   Notes:
729   A hyphen (-) must NOT be given at the beginning of the prefix name.
730   The first character of all runtime options is AUTOMATICALLY the hyphen.
731 
732   This is NOT used for options for the factorization of the matrix. Normally the
733   prefix is automatically passed in from the PC calling the factorization. To set
734   it directly use  `MatSetOptionsPrefixFactor()`
735 
736 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
737 @*/
738 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
739 {
740   PetscFunctionBegin;
741   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
742   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
743   PetscFunctionReturn(PETSC_SUCCESS);
744 }
745 
746 /*@
747   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
748   for matrices created with `MatGetFactor()`
749 
750   Logically Collective
751 
752   Input Parameters:
753 + A      - the matrix
754 - prefix - the prefix to prepend to all option names for the factored matrix
755 
756   Level: developer
757 
758   Notes:
759   A hyphen (-) must NOT be given at the beginning of the prefix name.
760   The first character of all runtime options is AUTOMATICALLY the hyphen.
761 
762   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
763   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
764 
765 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
766 @*/
767 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
768 {
769   PetscFunctionBegin;
770   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
771   if (prefix) {
772     PetscAssertPointer(prefix, 2);
773     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
774     if (prefix != A->factorprefix) {
775       PetscCall(PetscFree(A->factorprefix));
776       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
777     }
778   } else PetscCall(PetscFree(A->factorprefix));
779   PetscFunctionReturn(PETSC_SUCCESS);
780 }
781 
782 /*@
783   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
784   for matrices created with `MatGetFactor()`
785 
786   Logically Collective
787 
788   Input Parameters:
789 + A      - the matrix
790 - prefix - the prefix to prepend to all option names for the factored matrix
791 
792   Level: developer
793 
794   Notes:
795   A hyphen (-) must NOT be given at the beginning of the prefix name.
796   The first character of all runtime options is AUTOMATICALLY the hyphen.
797 
798   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
799   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
800 
801 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
802           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
803           `MatSetOptionsPrefix()`
804 @*/
805 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
806 {
807   size_t len1, len2, new_len;
808 
809   PetscFunctionBegin;
810   PetscValidHeader(A, 1);
811   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
812   if (!A->factorprefix) {
813     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
814     PetscFunctionReturn(PETSC_SUCCESS);
815   }
816   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
817 
818   PetscCall(PetscStrlen(A->factorprefix, &len1));
819   PetscCall(PetscStrlen(prefix, &len2));
820   new_len = len1 + len2 + 1;
821   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
822   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
823   PetscFunctionReturn(PETSC_SUCCESS);
824 }
825 
826 /*@
827   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
828   matrix options in the database.
829 
830   Logically Collective
831 
832   Input Parameters:
833 + A      - the matrix
834 - prefix - the prefix to prepend to all option names
835 
836   Level: advanced
837 
838   Note:
839   A hyphen (-) must NOT be given at the beginning of the prefix name.
840   The first character of all runtime options is AUTOMATICALLY the hyphen.
841 
842 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
843 @*/
844 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
845 {
846   PetscFunctionBegin;
847   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
848   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
849   PetscFunctionReturn(PETSC_SUCCESS);
850 }
851 
852 /*@
853   MatGetOptionsPrefix - Gets the prefix used for searching for all
854   matrix options in the database.
855 
856   Not Collective
857 
858   Input Parameter:
859 . A - the matrix
860 
861   Output Parameter:
862 . prefix - pointer to the prefix string used
863 
864   Level: advanced
865 
866   Fortran Note:
867   The user should pass in a string `prefix` of
868   sufficient length to hold the prefix.
869 
870 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
871 @*/
872 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
873 {
874   PetscFunctionBegin;
875   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
876   PetscAssertPointer(prefix, 2);
877   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
878   PetscFunctionReturn(PETSC_SUCCESS);
879 }
880 
881 /*@C
882   MatGetState - Gets the state of a `Mat`.
883 
884   Not Collective
885 
886   Input Parameter:
887 . A - the matrix
888 
889   Output Parameter:
890 . state - the object state
891 
892   Level: advanced
893 
894   Note:
895   Object state is an integer which gets increased every time
896   the object is changed. By saving and later querying the object state
897   one can determine whether information about the object is still current.
898 
899 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`
900 @*/
901 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
902 {
903   PetscFunctionBegin;
904   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
905   PetscAssertPointer(state, 2);
906   PetscCall(PetscObjectStateGet((PetscObject)A, state));
907   PetscFunctionReturn(PETSC_SUCCESS);
908 }
909 
910 /*@
911   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
912 
913   Collective
914 
915   Input Parameter:
916 . A - the matrix
917 
918   Level: beginner
919 
920   Notes:
921   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
922 
923   Users can reset the preallocation to access the original memory.
924 
925   Currently only supported for  `MATAIJ` matrices.
926 
927 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
928 @*/
929 PetscErrorCode MatResetPreallocation(Mat A)
930 {
931   PetscFunctionBegin;
932   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
933   PetscValidType(A, 1);
934   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
935   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
936   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 /*@
941   MatSetUp - Sets up the internal matrix data structures for later use.
942 
943   Collective
944 
945   Input Parameter:
946 . A - the matrix
947 
948   Level: intermediate
949 
950   Notes:
951   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
952   setting values in the matrix.
953 
954   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
955 
956 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
957 @*/
958 PetscErrorCode MatSetUp(Mat A)
959 {
960   PetscFunctionBegin;
961   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
962   if (!((PetscObject)A)->type_name) {
963     PetscMPIInt size;
964 
965     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
966     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
967   }
968   if (!A->preallocated) PetscTryTypeMethod(A, setup);
969   PetscCall(PetscLayoutSetUp(A->rmap));
970   PetscCall(PetscLayoutSetUp(A->cmap));
971   A->preallocated = PETSC_TRUE;
972   PetscFunctionReturn(PETSC_SUCCESS);
973 }
974 
975 #if defined(PETSC_HAVE_SAWS)
976   #include <petscviewersaws.h>
977 #endif
978 
979 /*
980    If threadsafety is on extraneous matrices may be printed
981 
982    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
983 */
984 #if !defined(PETSC_HAVE_THREADSAFETY)
985 static PetscInt insidematview = 0;
986 #endif
987 
988 /*@
989   MatViewFromOptions - View properties of the matrix based on options set in the options database
990 
991   Collective
992 
993   Input Parameters:
994 + A    - the matrix
995 . obj  - optional additional object that provides the options prefix to use
996 - name - command line option
997 
998   Options Database Key:
999 . -mat_view [viewertype]:... - the viewer and its options
1000 
1001   Level: intermediate
1002 
1003   Note:
1004 .vb
1005     If no value is provided ascii:stdout is used
1006        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1007                                                   for example ascii::ascii_info prints just the information about the object not all details
1008                                                   unless :append is given filename opens in write mode, overwriting what was already there
1009        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1010        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1011        socket[:port]                             defaults to the standard output port
1012        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1013 .ve
1014 
1015 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1016 @*/
1017 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1018 {
1019   PetscFunctionBegin;
1020   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1021 #if !defined(PETSC_HAVE_THREADSAFETY)
1022   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1023 #endif
1024   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1025   PetscFunctionReturn(PETSC_SUCCESS);
1026 }
1027 
1028 /*@
1029   MatView - display information about a matrix in a variety ways
1030 
1031   Collective on viewer
1032 
1033   Input Parameters:
1034 + mat    - the matrix
1035 - viewer - visualization context
1036 
1037   Options Database Keys:
1038 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1039 . -mat_view ::ascii_info_detail    - Prints more detailed info
1040 . -mat_view                        - Prints matrix in ASCII format
1041 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1042 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1043 . -display <name>                  - Sets display name (default is host)
1044 . -draw_pause <sec>                - Sets number of seconds to pause after display
1045 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1046 . -viewer_socket_machine <machine> - -
1047 . -viewer_socket_port <port>       - -
1048 . -mat_view binary                 - save matrix to file in binary format
1049 - -viewer_binary_filename <name>   - -
1050 
1051   Level: beginner
1052 
1053   Notes:
1054   The available visualization contexts include
1055 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1056 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1057 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1058 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1059 
1060   The user can open alternative visualization contexts with
1061 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1062 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1063   specified file; corresponding input uses `MatLoad()`
1064 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1065   an X window display
1066 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1067   Currently only the `MATSEQDENSE` and `MATAIJ`
1068   matrix types support the Socket viewer.
1069 
1070   The user can call `PetscViewerPushFormat()` to specify the output
1071   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1072   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1073 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1074 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1075 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1076 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1077   format common among all matrix types
1078 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1079   format (which is in many cases the same as the default)
1080 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1081   size and structure (not the matrix entries)
1082 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1083   the matrix structure
1084 
1085   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1086   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1087 
1088   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1089 
1090   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1091   viewer is used.
1092 
1093   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1094   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1095 
1096   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1097   and then use the following mouse functions.
1098 .vb
1099   left mouse: zoom in
1100   middle mouse: zoom out
1101   right mouse: continue with the simulation
1102 .ve
1103 
1104 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1105           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1106 @*/
1107 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1108 {
1109   PetscInt          rows, cols, rbs, cbs;
1110   PetscBool         isascii, isstring, issaws;
1111   PetscViewerFormat format;
1112   PetscMPIInt       size;
1113 
1114   PetscFunctionBegin;
1115   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1116   PetscValidType(mat, 1);
1117   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1118   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1119 
1120   PetscCall(PetscViewerGetFormat(viewer, &format));
1121   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1122   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1123 
1124 #if !defined(PETSC_HAVE_THREADSAFETY)
1125   insidematview++;
1126 #endif
1127   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1128   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1129   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1130   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1131 
1132   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1133   if (isascii) {
1134     if (!mat->preallocated) {
1135       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1136 #if !defined(PETSC_HAVE_THREADSAFETY)
1137       insidematview--;
1138 #endif
1139       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1140       PetscFunctionReturn(PETSC_SUCCESS);
1141     }
1142     if (!mat->assembled) {
1143       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1144 #if !defined(PETSC_HAVE_THREADSAFETY)
1145       insidematview--;
1146 #endif
1147       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1148       PetscFunctionReturn(PETSC_SUCCESS);
1149     }
1150     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1151     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1152       MatNullSpace nullsp, transnullsp;
1153 
1154       PetscCall(PetscViewerASCIIPushTab(viewer));
1155       PetscCall(MatGetSize(mat, &rows, &cols));
1156       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1157       if (rbs != 1 || cbs != 1) {
1158         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : ""));
1159         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1160       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1161       if (mat->factortype) {
1162         MatSolverType solver;
1163         PetscCall(MatFactorGetSolverType(mat, &solver));
1164         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1165       }
1166       if (mat->ops->getinfo) {
1167         MatInfo info;
1168         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1169         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1170         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1171       }
1172       PetscCall(MatGetNullSpace(mat, &nullsp));
1173       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1174       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1175       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1176       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1177       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1178       PetscCall(PetscViewerASCIIPushTab(viewer));
1179       PetscCall(MatProductView(mat, viewer));
1180       PetscCall(PetscViewerASCIIPopTab(viewer));
1181       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1182         IS tmp;
1183 
1184         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1185         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1186         PetscCall(PetscViewerASCIIPushTab(viewer));
1187         PetscCall(ISView(tmp, viewer));
1188         PetscCall(PetscViewerASCIIPopTab(viewer));
1189         PetscCall(ISDestroy(&tmp));
1190       }
1191     }
1192   } else if (issaws) {
1193 #if defined(PETSC_HAVE_SAWS)
1194     PetscMPIInt rank;
1195 
1196     PetscCall(PetscObjectName((PetscObject)mat));
1197     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1198     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1199 #endif
1200   } else if (isstring) {
1201     const char *type;
1202     PetscCall(MatGetType(mat, &type));
1203     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1204     PetscTryTypeMethod(mat, view, viewer);
1205   }
1206   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1207     PetscCall(PetscViewerASCIIPushTab(viewer));
1208     PetscUseTypeMethod(mat, viewnative, viewer);
1209     PetscCall(PetscViewerASCIIPopTab(viewer));
1210   } else if (mat->ops->view) {
1211     PetscCall(PetscViewerASCIIPushTab(viewer));
1212     PetscUseTypeMethod(mat, view, viewer);
1213     PetscCall(PetscViewerASCIIPopTab(viewer));
1214   }
1215   if (isascii) {
1216     PetscCall(PetscViewerGetFormat(viewer, &format));
1217     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1218   }
1219   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1220 #if !defined(PETSC_HAVE_THREADSAFETY)
1221   insidematview--;
1222 #endif
1223   PetscFunctionReturn(PETSC_SUCCESS);
1224 }
1225 
1226 #if defined(PETSC_USE_DEBUG)
1227   #include <../src/sys/totalview/tv_data_display.h>
1228 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1229 {
1230   TV_add_row("Local rows", "int", &mat->rmap->n);
1231   TV_add_row("Local columns", "int", &mat->cmap->n);
1232   TV_add_row("Global rows", "int", &mat->rmap->N);
1233   TV_add_row("Global columns", "int", &mat->cmap->N);
1234   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1235   return TV_format_OK;
1236 }
1237 #endif
1238 
1239 /*@
1240   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1241   with `MatView()`.  The matrix format is determined from the options database.
1242   Generates a parallel MPI matrix if the communicator has more than one
1243   processor.  The default matrix type is `MATAIJ`.
1244 
1245   Collective
1246 
1247   Input Parameters:
1248 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1249             or some related function before a call to `MatLoad()`
1250 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1251 
1252   Options Database Key:
1253 . -matload_block_size <bs> - set block size
1254 
1255   Level: beginner
1256 
1257   Notes:
1258   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1259   `Mat` before calling this routine if you wish to set it from the options database.
1260 
1261   `MatLoad()` automatically loads into the options database any options
1262   given in the file filename.info where filename is the name of the file
1263   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1264   file will be ignored if you use the -viewer_binary_skip_info option.
1265 
1266   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1267   sets the default matrix type AIJ and sets the local and global sizes.
1268   If type and/or size is already set, then the same are used.
1269 
1270   In parallel, each processor can load a subset of rows (or the
1271   entire matrix).  This routine is especially useful when a large
1272   matrix is stored on disk and only part of it is desired on each
1273   processor.  For example, a parallel solver may access only some of
1274   the rows from each processor.  The algorithm used here reads
1275   relatively small blocks of data rather than reading the entire
1276   matrix and then subsetting it.
1277 
1278   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1279   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1280   or the sequence like
1281 .vb
1282     `PetscViewer` v;
1283     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1284     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1285     `PetscViewerSetFromOptions`(v);
1286     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1287     `PetscViewerFileSetName`(v,"datafile");
1288 .ve
1289   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1290 $ -viewer_type {binary, hdf5}
1291 
1292   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1293   and src/mat/tutorials/ex10.c with the second approach.
1294 
1295   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1296   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1297   Multiple objects, both matrices and vectors, can be stored within the same file.
1298   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1299 
1300   Most users should not need to know the details of the binary storage
1301   format, since `MatLoad()` and `MatView()` completely hide these details.
1302   But for anyone who is interested, the standard binary matrix storage
1303   format is
1304 
1305 .vb
1306     PetscInt    MAT_FILE_CLASSID
1307     PetscInt    number of rows
1308     PetscInt    number of columns
1309     PetscInt    total number of nonzeros
1310     PetscInt    *number nonzeros in each row
1311     PetscInt    *column indices of all nonzeros (starting index is zero)
1312     PetscScalar *values of all nonzeros
1313 .ve
1314   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1315   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
1316   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1317 
1318   PETSc automatically does the byte swapping for
1319   machines that store the bytes reversed. Thus if you write your own binary
1320   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1321   and `PetscBinaryWrite()` to see how this may be done.
1322 
1323   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1324   Each processor's chunk is loaded independently by its owning MPI process.
1325   Multiple objects, both matrices and vectors, can be stored within the same file.
1326   They are looked up by their PetscObject name.
1327 
1328   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1329   by default the same structure and naming of the AIJ arrays and column count
1330   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1331 $    save example.mat A b -v7.3
1332   can be directly read by this routine (see Reference 1 for details).
1333 
1334   Depending on your MATLAB version, this format might be a default,
1335   otherwise you can set it as default in Preferences.
1336 
1337   Unless -nocompression flag is used to save the file in MATLAB,
1338   PETSc must be configured with ZLIB package.
1339 
1340   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1341 
1342   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1343 
1344   Corresponding `MatView()` is not yet implemented.
1345 
1346   The loaded matrix is actually a transpose of the original one in MATLAB,
1347   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1348   With this format, matrix is automatically transposed by PETSc,
1349   unless the matrix is marked as SPD or symmetric
1350   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1351 
1352   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1353 
1354 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1355  @*/
1356 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1357 {
1358   PetscBool flg;
1359 
1360   PetscFunctionBegin;
1361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1362   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1363 
1364   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1365 
1366   flg = PETSC_FALSE;
1367   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1368   if (flg) {
1369     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1370     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1371   }
1372   flg = PETSC_FALSE;
1373   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1374   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1375 
1376   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1377   PetscUseTypeMethod(mat, load, viewer);
1378   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1379   PetscFunctionReturn(PETSC_SUCCESS);
1380 }
1381 
1382 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1383 {
1384   Mat_Redundant *redund = *redundant;
1385 
1386   PetscFunctionBegin;
1387   if (redund) {
1388     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1389       PetscCall(ISDestroy(&redund->isrow));
1390       PetscCall(ISDestroy(&redund->iscol));
1391       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1392     } else {
1393       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1394       PetscCall(PetscFree(redund->sbuf_j));
1395       PetscCall(PetscFree(redund->sbuf_a));
1396       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1397         PetscCall(PetscFree(redund->rbuf_j[i]));
1398         PetscCall(PetscFree(redund->rbuf_a[i]));
1399       }
1400       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1401     }
1402 
1403     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1404     PetscCall(PetscFree(redund));
1405   }
1406   PetscFunctionReturn(PETSC_SUCCESS);
1407 }
1408 
1409 /*@
1410   MatDestroy - Frees space taken by a matrix.
1411 
1412   Collective
1413 
1414   Input Parameter:
1415 . A - the matrix
1416 
1417   Level: beginner
1418 
1419   Developer Note:
1420   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1421   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1422   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1423   if changes are needed here.
1424 
1425 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1426 @*/
1427 PetscErrorCode MatDestroy(Mat *A)
1428 {
1429   PetscFunctionBegin;
1430   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1431   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1432   if (--((PetscObject)*A)->refct > 0) {
1433     *A = NULL;
1434     PetscFunctionReturn(PETSC_SUCCESS);
1435   }
1436 
1437   /* if memory was published with SAWs then destroy it */
1438   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1439   PetscTryTypeMethod(*A, destroy);
1440 
1441   PetscCall(PetscFree((*A)->factorprefix));
1442   PetscCall(PetscFree((*A)->defaultvectype));
1443   PetscCall(PetscFree((*A)->defaultrandtype));
1444   PetscCall(PetscFree((*A)->bsizes));
1445   PetscCall(PetscFree((*A)->solvertype));
1446   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1447   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1448   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1449   PetscCall(MatProductClear(*A));
1450   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1451   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1452   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1453   PetscCall(MatDestroy(&(*A)->schur));
1454   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1455   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1456   PetscCall(PetscHeaderDestroy(A));
1457   PetscFunctionReturn(PETSC_SUCCESS);
1458 }
1459 
1460 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1461 /*@C
1462   MatSetValues - Inserts or adds a block of values into a matrix.
1463   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1464   MUST be called after all calls to `MatSetValues()` have been completed.
1465 
1466   Not Collective
1467 
1468   Input Parameters:
1469 + mat  - the matrix
1470 . v    - a logically two-dimensional array of values
1471 . m    - the number of rows
1472 . idxm - the global indices of the rows
1473 . n    - the number of columns
1474 . idxn - the global indices of the columns
1475 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1476 
1477   Level: beginner
1478 
1479   Notes:
1480   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1481 
1482   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1483   options cannot be mixed without intervening calls to the assembly
1484   routines.
1485 
1486   `MatSetValues()` uses 0-based row and column numbers in Fortran
1487   as well as in C.
1488 
1489   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1490   simply ignored. This allows easily inserting element stiffness matrices
1491   with homogeneous Dirichlet boundary conditions that you don't want represented
1492   in the matrix.
1493 
1494   Efficiency Alert:
1495   The routine `MatSetValuesBlocked()` may offer much better efficiency
1496   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1497 
1498   Developer Note:
1499   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1500   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1501 
1502 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1503           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1504 @*/
1505 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1506 {
1507   PetscFunctionBeginHot;
1508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1509   PetscValidType(mat, 1);
1510   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1511   PetscAssertPointer(idxm, 3);
1512   PetscAssertPointer(idxn, 5);
1513   MatCheckPreallocated(mat, 1);
1514 
1515   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1516   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1517 
1518   if (PetscDefined(USE_DEBUG)) {
1519     PetscInt i, j;
1520 
1521     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1522     if (v) {
1523       for (i = 0; i < m; i++) {
1524         for (j = 0; j < n; j++) {
1525           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1526 #if defined(PETSC_USE_COMPLEX)
1527             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]);
1528 #else
1529             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]);
1530 #endif
1531         }
1532       }
1533     }
1534     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);
1535     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);
1536   }
1537 
1538   if (mat->assembled) {
1539     mat->was_assembled = PETSC_TRUE;
1540     mat->assembled     = PETSC_FALSE;
1541   }
1542   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1543   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1544   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1545   PetscFunctionReturn(PETSC_SUCCESS);
1546 }
1547 
1548 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1549 /*@
1550   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1551   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1552   MUST be called after all calls to `MatSetValues()` have been completed.
1553 
1554   Not Collective
1555 
1556   Input Parameters:
1557 + mat  - the matrix
1558 . v    - a logically two-dimensional array of values
1559 . ism  - the rows to provide
1560 . isn  - the columns to provide
1561 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1562 
1563   Level: beginner
1564 
1565   Notes:
1566   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1567 
1568   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1569   options cannot be mixed without intervening calls to the assembly
1570   routines.
1571 
1572   `MatSetValues()` uses 0-based row and column numbers in Fortran
1573   as well as in C.
1574 
1575   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1576   simply ignored. This allows easily inserting element stiffness matrices
1577   with homogeneous Dirichlet boundary conditions that you don't want represented
1578   in the matrix.
1579 
1580   Efficiency Alert:
1581   The routine `MatSetValuesBlocked()` may offer much better efficiency
1582   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1583 
1584   This is currently not optimized for any particular `ISType`
1585 
1586   Developer Note:
1587   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1588   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1589 
1590 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1591           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1592 @*/
1593 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1594 {
1595   PetscInt        m, n;
1596   const PetscInt *rows, *cols;
1597 
1598   PetscFunctionBeginHot;
1599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1600   PetscCall(ISGetIndices(ism, &rows));
1601   PetscCall(ISGetIndices(isn, &cols));
1602   PetscCall(ISGetLocalSize(ism, &m));
1603   PetscCall(ISGetLocalSize(isn, &n));
1604   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1605   PetscCall(ISRestoreIndices(ism, &rows));
1606   PetscCall(ISRestoreIndices(isn, &cols));
1607   PetscFunctionReturn(PETSC_SUCCESS);
1608 }
1609 
1610 /*@
1611   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1612   values into a matrix
1613 
1614   Not Collective
1615 
1616   Input Parameters:
1617 + mat - the matrix
1618 . row - the (block) row to set
1619 - v   - a logically two-dimensional array of values
1620 
1621   Level: intermediate
1622 
1623   Notes:
1624   The values, `v`, are column-oriented (for the block version) and sorted
1625 
1626   All the nonzero values in `row` must be provided
1627 
1628   The matrix must have previously had its column indices set, likely by having been assembled.
1629 
1630   `row` must belong to this MPI process
1631 
1632 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1633           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1634 @*/
1635 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1636 {
1637   PetscInt globalrow;
1638 
1639   PetscFunctionBegin;
1640   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1641   PetscValidType(mat, 1);
1642   PetscAssertPointer(v, 3);
1643   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1644   PetscCall(MatSetValuesRow(mat, globalrow, v));
1645   PetscFunctionReturn(PETSC_SUCCESS);
1646 }
1647 
1648 /*@
1649   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1650   values into a matrix
1651 
1652   Not Collective
1653 
1654   Input Parameters:
1655 + mat - the matrix
1656 . row - the (block) row to set
1657 - 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
1658 
1659   Level: advanced
1660 
1661   Notes:
1662   The values, `v`, are column-oriented for the block version.
1663 
1664   All the nonzeros in `row` must be provided
1665 
1666   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1667 
1668   `row` must belong to this process
1669 
1670 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1671           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1672 @*/
1673 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1674 {
1675   PetscFunctionBeginHot;
1676   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1677   PetscValidType(mat, 1);
1678   MatCheckPreallocated(mat, 1);
1679   PetscAssertPointer(v, 3);
1680   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1681   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1682   mat->insertmode = INSERT_VALUES;
1683 
1684   if (mat->assembled) {
1685     mat->was_assembled = PETSC_TRUE;
1686     mat->assembled     = PETSC_FALSE;
1687   }
1688   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1689   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1690   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1691   PetscFunctionReturn(PETSC_SUCCESS);
1692 }
1693 
1694 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1695 /*@
1696   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1697   Using structured grid indexing
1698 
1699   Not Collective
1700 
1701   Input Parameters:
1702 + mat  - the matrix
1703 . m    - number of rows being entered
1704 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1705 . n    - number of columns being entered
1706 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1707 . v    - a logically two-dimensional array of values
1708 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1709 
1710   Level: beginner
1711 
1712   Notes:
1713   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1714 
1715   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1716   options cannot be mixed without intervening calls to the assembly
1717   routines.
1718 
1719   The grid coordinates are across the entire grid, not just the local portion
1720 
1721   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1722   as well as in C.
1723 
1724   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1725 
1726   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1727   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1728 
1729   The columns and rows in the stencil passed in MUST be contained within the
1730   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1731   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1732   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1733   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1734 
1735   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1736   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1737   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1738   `DM_BOUNDARY_PERIODIC` boundary type.
1739 
1740   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
1741   a single value per point) you can skip filling those indices.
1742 
1743   Inspired by the structured grid interface to the HYPRE package
1744   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1745 
1746   Efficiency Alert:
1747   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1748   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1749 
1750   Fortran Note:
1751   `idxm` and `idxn` should be declared as
1752 $     MatStencil idxm(4,m),idxn(4,n)
1753   and the values inserted using
1754 .vb
1755     idxm(MatStencil_i,1) = i
1756     idxm(MatStencil_j,1) = j
1757     idxm(MatStencil_k,1) = k
1758     idxm(MatStencil_c,1) = c
1759     etc
1760 .ve
1761 
1762 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1763           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1764 @*/
1765 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1766 {
1767   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1768   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1769   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1770 
1771   PetscFunctionBegin;
1772   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1774   PetscValidType(mat, 1);
1775   PetscAssertPointer(idxm, 3);
1776   PetscAssertPointer(idxn, 5);
1777 
1778   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1779     jdxm = buf;
1780     jdxn = buf + m;
1781   } else {
1782     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1783     jdxm = bufm;
1784     jdxn = bufn;
1785   }
1786   for (i = 0; i < m; i++) {
1787     for (j = 0; j < 3 - sdim; j++) dxm++;
1788     tmp = *dxm++ - starts[0];
1789     for (j = 0; j < dim - 1; j++) {
1790       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1791       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1792     }
1793     if (mat->stencil.noc) dxm++;
1794     jdxm[i] = tmp;
1795   }
1796   for (i = 0; i < n; i++) {
1797     for (j = 0; j < 3 - sdim; j++) dxn++;
1798     tmp = *dxn++ - starts[0];
1799     for (j = 0; j < dim - 1; j++) {
1800       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1801       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1802     }
1803     if (mat->stencil.noc) dxn++;
1804     jdxn[i] = tmp;
1805   }
1806   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1807   PetscCall(PetscFree2(bufm, bufn));
1808   PetscFunctionReturn(PETSC_SUCCESS);
1809 }
1810 
1811 /*@
1812   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1813   Using structured grid indexing
1814 
1815   Not Collective
1816 
1817   Input Parameters:
1818 + mat  - the matrix
1819 . m    - number of rows being entered
1820 . idxm - grid coordinates for matrix rows being entered
1821 . n    - number of columns being entered
1822 . idxn - grid coordinates for matrix columns being entered
1823 . v    - a logically two-dimensional array of values
1824 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1825 
1826   Level: beginner
1827 
1828   Notes:
1829   By default the values, `v`, are row-oriented and unsorted.
1830   See `MatSetOption()` for other options.
1831 
1832   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1833   options cannot be mixed without intervening calls to the assembly
1834   routines.
1835 
1836   The grid coordinates are across the entire grid, not just the local portion
1837 
1838   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1839   as well as in C.
1840 
1841   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1842 
1843   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1844   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1845 
1846   The columns and rows in the stencil passed in MUST be contained within the
1847   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1848   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1849   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1850   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1851 
1852   Negative indices may be passed in idxm and idxn, these rows and columns are
1853   simply ignored. This allows easily inserting element stiffness matrices
1854   with homogeneous Dirichlet boundary conditions that you don't want represented
1855   in the matrix.
1856 
1857   Inspired by the structured grid interface to the HYPRE package
1858   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1859 
1860   Fortran Note:
1861   `idxm` and `idxn` should be declared as
1862 $     MatStencil idxm(4,m),idxn(4,n)
1863   and the values inserted using
1864 .vb
1865     idxm(MatStencil_i,1) = i
1866     idxm(MatStencil_j,1) = j
1867     idxm(MatStencil_k,1) = k
1868    etc
1869 .ve
1870 
1871 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1872           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1873           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1874 @*/
1875 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1876 {
1877   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1878   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1879   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1880 
1881   PetscFunctionBegin;
1882   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1884   PetscValidType(mat, 1);
1885   PetscAssertPointer(idxm, 3);
1886   PetscAssertPointer(idxn, 5);
1887   PetscAssertPointer(v, 6);
1888 
1889   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1890     jdxm = buf;
1891     jdxn = buf + m;
1892   } else {
1893     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1894     jdxm = bufm;
1895     jdxn = bufn;
1896   }
1897   for (i = 0; i < m; i++) {
1898     for (j = 0; j < 3 - sdim; j++) dxm++;
1899     tmp = *dxm++ - starts[0];
1900     for (j = 0; j < sdim - 1; j++) {
1901       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1902       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1903     }
1904     dxm++;
1905     jdxm[i] = tmp;
1906   }
1907   for (i = 0; i < n; i++) {
1908     for (j = 0; j < 3 - sdim; j++) dxn++;
1909     tmp = *dxn++ - starts[0];
1910     for (j = 0; j < sdim - 1; j++) {
1911       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1912       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1913     }
1914     dxn++;
1915     jdxn[i] = tmp;
1916   }
1917   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1918   PetscCall(PetscFree2(bufm, bufn));
1919   PetscFunctionReturn(PETSC_SUCCESS);
1920 }
1921 
1922 /*@
1923   MatSetStencil - Sets the grid information for setting values into a matrix via
1924   `MatSetValuesStencil()`
1925 
1926   Not Collective
1927 
1928   Input Parameters:
1929 + mat    - the matrix
1930 . dim    - dimension of the grid 1, 2, or 3
1931 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1932 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1933 - dof    - number of degrees of freedom per node
1934 
1935   Level: beginner
1936 
1937   Notes:
1938   Inspired by the structured grid interface to the HYPRE package
1939   (www.llnl.gov/CASC/hyper)
1940 
1941   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1942   user.
1943 
1944 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1945           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1946 @*/
1947 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1948 {
1949   PetscFunctionBegin;
1950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1951   PetscAssertPointer(dims, 3);
1952   PetscAssertPointer(starts, 4);
1953 
1954   mat->stencil.dim = dim + (dof > 1);
1955   for (PetscInt i = 0; i < dim; i++) {
1956     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1957     mat->stencil.starts[i] = starts[dim - i - 1];
1958   }
1959   mat->stencil.dims[dim]   = dof;
1960   mat->stencil.starts[dim] = 0;
1961   mat->stencil.noc         = (PetscBool)(dof == 1);
1962   PetscFunctionReturn(PETSC_SUCCESS);
1963 }
1964 
1965 /*@C
1966   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1967 
1968   Not Collective
1969 
1970   Input Parameters:
1971 + mat  - the matrix
1972 . v    - a logically two-dimensional array of values
1973 . m    - the number of block rows
1974 . idxm - the global block indices
1975 . n    - the number of block columns
1976 . idxn - the global block indices
1977 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1978 
1979   Level: intermediate
1980 
1981   Notes:
1982   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1983   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1984 
1985   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1986   NOT the total number of rows/columns; for example, if the block size is 2 and
1987   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
1988   The values in `idxm` would be 1 2; that is the first index for each block divided by
1989   the block size.
1990 
1991   You must call `MatSetBlockSize()` when constructing this matrix (before
1992   preallocating it).
1993 
1994   By default the values, `v`, are row-oriented, so the layout of
1995   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1996 
1997   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1998   options cannot be mixed without intervening calls to the assembly
1999   routines.
2000 
2001   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2002   as well as in C.
2003 
2004   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2005   simply ignored. This allows easily inserting element stiffness matrices
2006   with homogeneous Dirichlet boundary conditions that you don't want represented
2007   in the matrix.
2008 
2009   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2010   internal searching must be done to determine where to place the
2011   data in the matrix storage space.  By instead inserting blocks of
2012   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2013   reduced.
2014 
2015   Example:
2016 .vb
2017    Suppose m=n=2 and block size(bs) = 2 The array is
2018 
2019    1  2  | 3  4
2020    5  6  | 7  8
2021    - - - | - - -
2022    9  10 | 11 12
2023    13 14 | 15 16
2024 
2025    v[] should be passed in like
2026    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2027 
2028   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2029    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2030 .ve
2031 
2032 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2033 @*/
2034 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2035 {
2036   PetscFunctionBeginHot;
2037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2038   PetscValidType(mat, 1);
2039   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2040   PetscAssertPointer(idxm, 3);
2041   PetscAssertPointer(idxn, 5);
2042   MatCheckPreallocated(mat, 1);
2043   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2044   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2045   if (PetscDefined(USE_DEBUG)) {
2046     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2047     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2048   }
2049   if (PetscDefined(USE_DEBUG)) {
2050     PetscInt rbs, cbs, M, N, i;
2051     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2052     PetscCall(MatGetSize(mat, &M, &N));
2053     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M);
2054     for (i = 0; i < n; i++)
2055       PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N);
2056   }
2057   if (mat->assembled) {
2058     mat->was_assembled = PETSC_TRUE;
2059     mat->assembled     = PETSC_FALSE;
2060   }
2061   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2062   if (mat->ops->setvaluesblocked) {
2063     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2064   } else {
2065     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2066     PetscInt i, j, bs, cbs;
2067 
2068     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2069     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2070       iidxm = buf;
2071       iidxn = buf + m * bs;
2072     } else {
2073       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2074       iidxm = bufr;
2075       iidxn = bufc;
2076     }
2077     for (i = 0; i < m; i++) {
2078       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2079     }
2080     if (m != n || bs != cbs || idxm != idxn) {
2081       for (i = 0; i < n; i++) {
2082         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2083       }
2084     } else iidxn = iidxm;
2085     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2086     PetscCall(PetscFree2(bufr, bufc));
2087   }
2088   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2089   PetscFunctionReturn(PETSC_SUCCESS);
2090 }
2091 
2092 /*@C
2093   MatGetValues - Gets a block of local values from a matrix.
2094 
2095   Not Collective; can only return values that are owned by the give process
2096 
2097   Input Parameters:
2098 + mat  - the matrix
2099 . v    - a logically two-dimensional array for storing the values
2100 . m    - the number of rows
2101 . idxm - the  global indices of the rows
2102 . n    - the number of columns
2103 - idxn - the global indices of the columns
2104 
2105   Level: advanced
2106 
2107   Notes:
2108   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2109   The values, `v`, are then returned in a row-oriented format,
2110   analogous to that used by default in `MatSetValues()`.
2111 
2112   `MatGetValues()` uses 0-based row and column numbers in
2113   Fortran as well as in C.
2114 
2115   `MatGetValues()` requires that the matrix has been assembled
2116   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2117   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2118   without intermediate matrix assembly.
2119 
2120   Negative row or column indices will be ignored and those locations in `v` will be
2121   left unchanged.
2122 
2123   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2124   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2125   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2126 
2127 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2128 @*/
2129 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2130 {
2131   PetscFunctionBegin;
2132   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2133   PetscValidType(mat, 1);
2134   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2135   PetscAssertPointer(idxm, 3);
2136   PetscAssertPointer(idxn, 5);
2137   PetscAssertPointer(v, 6);
2138   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2139   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2140   MatCheckPreallocated(mat, 1);
2141 
2142   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2143   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2144   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2145   PetscFunctionReturn(PETSC_SUCCESS);
2146 }
2147 
2148 /*@C
2149   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2150   defined previously by `MatSetLocalToGlobalMapping()`
2151 
2152   Not Collective
2153 
2154   Input Parameters:
2155 + mat  - the matrix
2156 . nrow - number of rows
2157 . irow - the row local indices
2158 . ncol - number of columns
2159 - icol - the column local indices
2160 
2161   Output Parameter:
2162 . y - a logically two-dimensional array of values
2163 
2164   Level: advanced
2165 
2166   Notes:
2167   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2168 
2169   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,
2170   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2171   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2172   with `MatSetLocalToGlobalMapping()`.
2173 
2174   Developer Note:
2175   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2176   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2177 
2178 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2179           `MatSetValuesLocal()`, `MatGetValues()`
2180 @*/
2181 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2182 {
2183   PetscFunctionBeginHot;
2184   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2185   PetscValidType(mat, 1);
2186   MatCheckPreallocated(mat, 1);
2187   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2188   PetscAssertPointer(irow, 3);
2189   PetscAssertPointer(icol, 5);
2190   if (PetscDefined(USE_DEBUG)) {
2191     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2192     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2193   }
2194   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2195   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2196   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2197   else {
2198     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2199     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2200       irowm = buf;
2201       icolm = buf + nrow;
2202     } else {
2203       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2204       irowm = bufr;
2205       icolm = bufc;
2206     }
2207     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2208     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2209     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2210     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2211     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2212     PetscCall(PetscFree2(bufr, bufc));
2213   }
2214   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2215   PetscFunctionReturn(PETSC_SUCCESS);
2216 }
2217 
2218 /*@
2219   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2220   the same size. Currently, this can only be called once and creates the given matrix.
2221 
2222   Not Collective
2223 
2224   Input Parameters:
2225 + mat  - the matrix
2226 . nb   - the number of blocks
2227 . bs   - the number of rows (and columns) in each block
2228 . rows - a concatenation of the rows for each block
2229 - v    - a concatenation of logically two-dimensional arrays of values
2230 
2231   Level: advanced
2232 
2233   Notes:
2234   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2235 
2236   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2237 
2238 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2239           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2240 @*/
2241 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2242 {
2243   PetscFunctionBegin;
2244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2245   PetscValidType(mat, 1);
2246   PetscAssertPointer(rows, 4);
2247   PetscAssertPointer(v, 5);
2248   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2249 
2250   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2251   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2252   else {
2253     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2254   }
2255   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2256   PetscFunctionReturn(PETSC_SUCCESS);
2257 }
2258 
2259 /*@
2260   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2261   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2262   using a local (per-processor) numbering.
2263 
2264   Not Collective
2265 
2266   Input Parameters:
2267 + x        - the matrix
2268 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2269 - cmapping - column mapping
2270 
2271   Level: intermediate
2272 
2273   Note:
2274   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2275 
2276 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2277 @*/
2278 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2279 {
2280   PetscFunctionBegin;
2281   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2282   PetscValidType(x, 1);
2283   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2284   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2285   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2286   else {
2287     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2288     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2289   }
2290   PetscFunctionReturn(PETSC_SUCCESS);
2291 }
2292 
2293 /*@
2294   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2295 
2296   Not Collective
2297 
2298   Input Parameter:
2299 . A - the matrix
2300 
2301   Output Parameters:
2302 + rmapping - row mapping
2303 - cmapping - column mapping
2304 
2305   Level: advanced
2306 
2307 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2308 @*/
2309 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2310 {
2311   PetscFunctionBegin;
2312   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2313   PetscValidType(A, 1);
2314   if (rmapping) {
2315     PetscAssertPointer(rmapping, 2);
2316     *rmapping = A->rmap->mapping;
2317   }
2318   if (cmapping) {
2319     PetscAssertPointer(cmapping, 3);
2320     *cmapping = A->cmap->mapping;
2321   }
2322   PetscFunctionReturn(PETSC_SUCCESS);
2323 }
2324 
2325 /*@
2326   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2327 
2328   Logically Collective
2329 
2330   Input Parameters:
2331 + A    - the matrix
2332 . rmap - row layout
2333 - cmap - column layout
2334 
2335   Level: advanced
2336 
2337   Note:
2338   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2339 
2340 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2341 @*/
2342 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2343 {
2344   PetscFunctionBegin;
2345   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2346   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2347   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2348   PetscFunctionReturn(PETSC_SUCCESS);
2349 }
2350 
2351 /*@
2352   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2353 
2354   Not Collective
2355 
2356   Input Parameter:
2357 . A - the matrix
2358 
2359   Output Parameters:
2360 + rmap - row layout
2361 - cmap - column layout
2362 
2363   Level: advanced
2364 
2365 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2366 @*/
2367 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2368 {
2369   PetscFunctionBegin;
2370   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2371   PetscValidType(A, 1);
2372   if (rmap) {
2373     PetscAssertPointer(rmap, 2);
2374     *rmap = A->rmap;
2375   }
2376   if (cmap) {
2377     PetscAssertPointer(cmap, 3);
2378     *cmap = A->cmap;
2379   }
2380   PetscFunctionReturn(PETSC_SUCCESS);
2381 }
2382 
2383 /*@C
2384   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2385   using a local numbering of the rows and columns.
2386 
2387   Not Collective
2388 
2389   Input Parameters:
2390 + mat  - the matrix
2391 . nrow - number of rows
2392 . irow - the row local indices
2393 . ncol - number of columns
2394 . icol - the column local indices
2395 . y    - a logically two-dimensional array of values
2396 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2397 
2398   Level: intermediate
2399 
2400   Notes:
2401   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2402 
2403   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2404   options cannot be mixed without intervening calls to the assembly
2405   routines.
2406 
2407   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2408   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2409 
2410   Developer Note:
2411   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2412   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2413 
2414 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2415           `MatGetValuesLocal()`
2416 @*/
2417 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2418 {
2419   PetscFunctionBeginHot;
2420   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2421   PetscValidType(mat, 1);
2422   MatCheckPreallocated(mat, 1);
2423   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2424   PetscAssertPointer(irow, 3);
2425   PetscAssertPointer(icol, 5);
2426   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2427   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2428   if (PetscDefined(USE_DEBUG)) {
2429     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2430     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2431   }
2432 
2433   if (mat->assembled) {
2434     mat->was_assembled = PETSC_TRUE;
2435     mat->assembled     = PETSC_FALSE;
2436   }
2437   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2438   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2439   else {
2440     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2441     const PetscInt *irowm, *icolm;
2442 
2443     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2444       bufr  = buf;
2445       bufc  = buf + nrow;
2446       irowm = bufr;
2447       icolm = bufc;
2448     } else {
2449       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2450       irowm = bufr;
2451       icolm = bufc;
2452     }
2453     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2454     else irowm = irow;
2455     if (mat->cmap->mapping) {
2456       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2457         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2458       } else icolm = irowm;
2459     } else icolm = icol;
2460     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2461     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2462   }
2463   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2464   PetscFunctionReturn(PETSC_SUCCESS);
2465 }
2466 
2467 /*@C
2468   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2469   using a local ordering of the nodes a block at a time.
2470 
2471   Not Collective
2472 
2473   Input Parameters:
2474 + mat  - the matrix
2475 . nrow - number of rows
2476 . irow - the row local indices
2477 . ncol - number of columns
2478 . icol - the column local indices
2479 . y    - a logically two-dimensional array of values
2480 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2481 
2482   Level: intermediate
2483 
2484   Notes:
2485   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2486   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2487 
2488   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2489   options cannot be mixed without intervening calls to the assembly
2490   routines.
2491 
2492   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2493   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2494 
2495   Developer Note:
2496   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2497   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2498 
2499 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2500           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2501 @*/
2502 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2503 {
2504   PetscFunctionBeginHot;
2505   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2506   PetscValidType(mat, 1);
2507   MatCheckPreallocated(mat, 1);
2508   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2509   PetscAssertPointer(irow, 3);
2510   PetscAssertPointer(icol, 5);
2511   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2512   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2513   if (PetscDefined(USE_DEBUG)) {
2514     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2515     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);
2516   }
2517 
2518   if (mat->assembled) {
2519     mat->was_assembled = PETSC_TRUE;
2520     mat->assembled     = PETSC_FALSE;
2521   }
2522   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2523     PetscInt irbs, rbs;
2524     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2525     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2526     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2527   }
2528   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2529     PetscInt icbs, cbs;
2530     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2531     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2532     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2533   }
2534   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2535   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2536   else {
2537     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2538     const PetscInt *irowm, *icolm;
2539 
2540     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2541       bufr  = buf;
2542       bufc  = buf + nrow;
2543       irowm = bufr;
2544       icolm = bufc;
2545     } else {
2546       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2547       irowm = bufr;
2548       icolm = bufc;
2549     }
2550     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2551     else irowm = irow;
2552     if (mat->cmap->mapping) {
2553       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2554         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2555       } else icolm = irowm;
2556     } else icolm = icol;
2557     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2558     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2559   }
2560   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2561   PetscFunctionReturn(PETSC_SUCCESS);
2562 }
2563 
2564 /*@
2565   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2566 
2567   Collective
2568 
2569   Input Parameters:
2570 + mat - the matrix
2571 - x   - the vector to be multiplied
2572 
2573   Output Parameter:
2574 . y - the result
2575 
2576   Level: developer
2577 
2578   Note:
2579   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2580   call `MatMultDiagonalBlock`(A,y,y).
2581 
2582 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2583 @*/
2584 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2585 {
2586   PetscFunctionBegin;
2587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2588   PetscValidType(mat, 1);
2589   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2590   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2591 
2592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2593   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2594   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2595   MatCheckPreallocated(mat, 1);
2596 
2597   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2598   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2599   PetscFunctionReturn(PETSC_SUCCESS);
2600 }
2601 
2602 /*@
2603   MatMult - Computes the matrix-vector product, $y = Ax$.
2604 
2605   Neighbor-wise Collective
2606 
2607   Input Parameters:
2608 + mat - the matrix
2609 - x   - the vector to be multiplied
2610 
2611   Output Parameter:
2612 . y - the result
2613 
2614   Level: beginner
2615 
2616   Note:
2617   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2618   call `MatMult`(A,y,y).
2619 
2620 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2621 @*/
2622 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2623 {
2624   PetscFunctionBegin;
2625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2626   PetscValidType(mat, 1);
2627   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2628   VecCheckAssembled(x);
2629   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2630   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2631   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2632   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2633   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);
2634   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);
2635   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);
2636   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);
2637   PetscCall(VecSetErrorIfLocked(y, 3));
2638   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2639   MatCheckPreallocated(mat, 1);
2640 
2641   PetscCall(VecLockReadPush(x));
2642   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2643   PetscUseTypeMethod(mat, mult, x, y);
2644   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2645   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2646   PetscCall(VecLockReadPop(x));
2647   PetscFunctionReturn(PETSC_SUCCESS);
2648 }
2649 
2650 /*@
2651   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2652 
2653   Neighbor-wise Collective
2654 
2655   Input Parameters:
2656 + mat - the matrix
2657 - x   - the vector to be multiplied
2658 
2659   Output Parameter:
2660 . y - the result
2661 
2662   Level: beginner
2663 
2664   Notes:
2665   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2666   call `MatMultTranspose`(A,y,y).
2667 
2668   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2669   use `MatMultHermitianTranspose()`
2670 
2671 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2672 @*/
2673 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2674 {
2675   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2676 
2677   PetscFunctionBegin;
2678   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2679   PetscValidType(mat, 1);
2680   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2681   VecCheckAssembled(x);
2682   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2683 
2684   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2685   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2686   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2687   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);
2688   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);
2689   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);
2690   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);
2691   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2692   MatCheckPreallocated(mat, 1);
2693 
2694   if (!mat->ops->multtranspose) {
2695     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2696     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);
2697   } else op = mat->ops->multtranspose;
2698   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2699   PetscCall(VecLockReadPush(x));
2700   PetscCall((*op)(mat, x, y));
2701   PetscCall(VecLockReadPop(x));
2702   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2703   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2704   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2705   PetscFunctionReturn(PETSC_SUCCESS);
2706 }
2707 
2708 /*@
2709   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2710 
2711   Neighbor-wise Collective
2712 
2713   Input Parameters:
2714 + mat - the matrix
2715 - x   - the vector to be multiplied
2716 
2717   Output Parameter:
2718 . y - the result
2719 
2720   Level: beginner
2721 
2722   Notes:
2723   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2724   call `MatMultHermitianTranspose`(A,y,y).
2725 
2726   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2727 
2728   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2729 
2730 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2731 @*/
2732 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2733 {
2734   PetscFunctionBegin;
2735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2736   PetscValidType(mat, 1);
2737   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2738   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2739 
2740   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2741   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2742   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2743   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);
2744   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);
2745   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);
2746   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);
2747   MatCheckPreallocated(mat, 1);
2748 
2749   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2750 #if defined(PETSC_USE_COMPLEX)
2751   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2752     PetscCall(VecLockReadPush(x));
2753     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2754     else PetscUseTypeMethod(mat, mult, x, y);
2755     PetscCall(VecLockReadPop(x));
2756   } else {
2757     Vec w;
2758     PetscCall(VecDuplicate(x, &w));
2759     PetscCall(VecCopy(x, w));
2760     PetscCall(VecConjugate(w));
2761     PetscCall(MatMultTranspose(mat, w, y));
2762     PetscCall(VecDestroy(&w));
2763     PetscCall(VecConjugate(y));
2764   }
2765   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2766 #else
2767   PetscCall(MatMultTranspose(mat, x, y));
2768 #endif
2769   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2770   PetscFunctionReturn(PETSC_SUCCESS);
2771 }
2772 
2773 /*@
2774   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2775 
2776   Neighbor-wise Collective
2777 
2778   Input Parameters:
2779 + mat - the matrix
2780 . v1  - the vector to be multiplied by `mat`
2781 - v2  - the vector to be added to the result
2782 
2783   Output Parameter:
2784 . v3 - the result
2785 
2786   Level: beginner
2787 
2788   Note:
2789   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2790   call `MatMultAdd`(A,v1,v2,v1).
2791 
2792 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2793 @*/
2794 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2795 {
2796   PetscFunctionBegin;
2797   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2798   PetscValidType(mat, 1);
2799   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2800   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2801   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2802 
2803   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2804   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2805   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);
2806   /* 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);
2807      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); */
2808   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);
2809   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);
2810   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2811   MatCheckPreallocated(mat, 1);
2812 
2813   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2814   PetscCall(VecLockReadPush(v1));
2815   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2816   PetscCall(VecLockReadPop(v1));
2817   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2818   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2819   PetscFunctionReturn(PETSC_SUCCESS);
2820 }
2821 
2822 /*@
2823   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2824 
2825   Neighbor-wise Collective
2826 
2827   Input Parameters:
2828 + mat - the matrix
2829 . v1  - the vector to be multiplied by the transpose of the matrix
2830 - v2  - the vector to be added to the result
2831 
2832   Output Parameter:
2833 . v3 - the result
2834 
2835   Level: beginner
2836 
2837   Note:
2838   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2839   call `MatMultTransposeAdd`(A,v1,v2,v1).
2840 
2841 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2842 @*/
2843 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2844 {
2845   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2846 
2847   PetscFunctionBegin;
2848   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2849   PetscValidType(mat, 1);
2850   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2851   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2852   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2853 
2854   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2855   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2856   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);
2857   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);
2858   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);
2859   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2860   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2861   MatCheckPreallocated(mat, 1);
2862 
2863   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2864   PetscCall(VecLockReadPush(v1));
2865   PetscCall((*op)(mat, v1, v2, v3));
2866   PetscCall(VecLockReadPop(v1));
2867   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2868   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2869   PetscFunctionReturn(PETSC_SUCCESS);
2870 }
2871 
2872 /*@
2873   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2874 
2875   Neighbor-wise Collective
2876 
2877   Input Parameters:
2878 + mat - the matrix
2879 . v1  - the vector to be multiplied by the Hermitian transpose
2880 - v2  - the vector to be added to the result
2881 
2882   Output Parameter:
2883 . v3 - the result
2884 
2885   Level: beginner
2886 
2887   Note:
2888   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2889   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2890 
2891 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2892 @*/
2893 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2894 {
2895   PetscFunctionBegin;
2896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2897   PetscValidType(mat, 1);
2898   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2899   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2900   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2901 
2902   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2903   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2904   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2905   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);
2906   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);
2907   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);
2908   MatCheckPreallocated(mat, 1);
2909 
2910   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2911   PetscCall(VecLockReadPush(v1));
2912   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2913   else {
2914     Vec w, z;
2915     PetscCall(VecDuplicate(v1, &w));
2916     PetscCall(VecCopy(v1, w));
2917     PetscCall(VecConjugate(w));
2918     PetscCall(VecDuplicate(v3, &z));
2919     PetscCall(MatMultTranspose(mat, w, z));
2920     PetscCall(VecDestroy(&w));
2921     PetscCall(VecConjugate(z));
2922     if (v2 != v3) {
2923       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2924     } else {
2925       PetscCall(VecAXPY(v3, 1.0, z));
2926     }
2927     PetscCall(VecDestroy(&z));
2928   }
2929   PetscCall(VecLockReadPop(v1));
2930   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2931   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2932   PetscFunctionReturn(PETSC_SUCCESS);
2933 }
2934 
2935 /*@
2936   MatGetFactorType - gets the type of factorization a matrix is
2937 
2938   Not Collective
2939 
2940   Input Parameter:
2941 . mat - the matrix
2942 
2943   Output Parameter:
2944 . 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`
2945 
2946   Level: intermediate
2947 
2948 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2949           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2950 @*/
2951 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2952 {
2953   PetscFunctionBegin;
2954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2955   PetscValidType(mat, 1);
2956   PetscAssertPointer(t, 2);
2957   *t = mat->factortype;
2958   PetscFunctionReturn(PETSC_SUCCESS);
2959 }
2960 
2961 /*@
2962   MatSetFactorType - sets the type of factorization a matrix is
2963 
2964   Logically Collective
2965 
2966   Input Parameters:
2967 + mat - the matrix
2968 - 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`
2969 
2970   Level: intermediate
2971 
2972 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2973           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2974 @*/
2975 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2976 {
2977   PetscFunctionBegin;
2978   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2979   PetscValidType(mat, 1);
2980   mat->factortype = t;
2981   PetscFunctionReturn(PETSC_SUCCESS);
2982 }
2983 
2984 /*@C
2985   MatGetInfo - Returns information about matrix storage (number of
2986   nonzeros, memory, etc.).
2987 
2988   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2989 
2990   Input Parameters:
2991 + mat  - the matrix
2992 - 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)
2993 
2994   Output Parameter:
2995 . info - matrix information context
2996 
2997   Options Database Key:
2998 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2999 
3000   Notes:
3001   The `MatInfo` context contains a variety of matrix data, including
3002   number of nonzeros allocated and used, number of mallocs during
3003   matrix assembly, etc.  Additional information for factored matrices
3004   is provided (such as the fill ratio, number of mallocs during
3005   factorization, etc.).
3006 
3007   Example:
3008   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3009   data within the MatInfo context.  For example,
3010 .vb
3011       MatInfo info;
3012       Mat     A;
3013       double  mal, nz_a, nz_u;
3014 
3015       MatGetInfo(A, MAT_LOCAL, &info);
3016       mal  = info.mallocs;
3017       nz_a = info.nz_allocated;
3018 .ve
3019 
3020   Fortran users should declare info as a double precision
3021   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3022   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3023   a complete list of parameter names.
3024 .vb
3025       double  precision info(MAT_INFO_SIZE)
3026       double  precision mal, nz_a
3027       Mat     A
3028       integer ierr
3029 
3030       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3031       mal = info(MAT_INFO_MALLOCS)
3032       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3033 .ve
3034 
3035   Level: intermediate
3036 
3037   Developer Note:
3038   The Fortran interface is not autogenerated as the
3039   interface definition cannot be generated correctly [due to `MatInfo` argument]
3040 
3041 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3042 @*/
3043 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3044 {
3045   PetscFunctionBegin;
3046   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3047   PetscValidType(mat, 1);
3048   PetscAssertPointer(info, 3);
3049   MatCheckPreallocated(mat, 1);
3050   PetscUseTypeMethod(mat, getinfo, flag, info);
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*
3055    This is used by external packages where it is not easy to get the info from the actual
3056    matrix factorization.
3057 */
3058 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3059 {
3060   PetscFunctionBegin;
3061   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3062   PetscFunctionReturn(PETSC_SUCCESS);
3063 }
3064 
3065 /*@C
3066   MatLUFactor - Performs in-place LU factorization of matrix.
3067 
3068   Collective
3069 
3070   Input Parameters:
3071 + mat  - the matrix
3072 . row  - row permutation
3073 . col  - column permutation
3074 - info - options for factorization, includes
3075 .vb
3076           fill - expected fill as ratio of original fill.
3077           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3078                    Run with the option -info to determine an optimal value to use
3079 .ve
3080 
3081   Level: developer
3082 
3083   Notes:
3084   Most users should employ the `KSP` interface for linear solvers
3085   instead of working directly with matrix algebra routines such as this.
3086   See, e.g., `KSPCreate()`.
3087 
3088   This changes the state of the matrix to a factored matrix; it cannot be used
3089   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3090 
3091   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3092   when not using `KSP`.
3093 
3094   Developer Note:
3095   The Fortran interface is not autogenerated as the
3096   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3097 
3098 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3099           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3100 @*/
3101 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3102 {
3103   MatFactorInfo tinfo;
3104 
3105   PetscFunctionBegin;
3106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3107   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3108   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3109   if (info) PetscAssertPointer(info, 4);
3110   PetscValidType(mat, 1);
3111   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3112   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3113   MatCheckPreallocated(mat, 1);
3114   if (!info) {
3115     PetscCall(MatFactorInfoInitialize(&tinfo));
3116     info = &tinfo;
3117   }
3118 
3119   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3120   PetscUseTypeMethod(mat, lufactor, row, col, info);
3121   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3122   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3123   PetscFunctionReturn(PETSC_SUCCESS);
3124 }
3125 
3126 /*@C
3127   MatILUFactor - Performs in-place ILU factorization of matrix.
3128 
3129   Collective
3130 
3131   Input Parameters:
3132 + mat  - the matrix
3133 . row  - row permutation
3134 . col  - column permutation
3135 - info - structure containing
3136 .vb
3137       levels - number of levels of fill.
3138       expected fill - as ratio of original fill.
3139       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3140                 missing diagonal entries)
3141 .ve
3142 
3143   Level: developer
3144 
3145   Notes:
3146   Most users should employ the `KSP` interface for linear solvers
3147   instead of working directly with matrix algebra routines such as this.
3148   See, e.g., `KSPCreate()`.
3149 
3150   Probably really in-place only when level of fill is zero, otherwise allocates
3151   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3152   when not using `KSP`.
3153 
3154   Developer Note:
3155   The Fortran interface is not autogenerated as the
3156   interface definition cannot be generated correctly [due to MatFactorInfo]
3157 
3158 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3159 @*/
3160 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3161 {
3162   PetscFunctionBegin;
3163   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3164   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3165   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3166   PetscAssertPointer(info, 4);
3167   PetscValidType(mat, 1);
3168   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3169   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3170   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3171   MatCheckPreallocated(mat, 1);
3172 
3173   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3174   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3175   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3176   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3177   PetscFunctionReturn(PETSC_SUCCESS);
3178 }
3179 
3180 /*@C
3181   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3182   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3183 
3184   Collective
3185 
3186   Input Parameters:
3187 + fact - the factor matrix obtained with `MatGetFactor()`
3188 . mat  - the matrix
3189 . row  - the row permutation
3190 . col  - the column permutation
3191 - info - options for factorization, includes
3192 .vb
3193           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3194           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3195 .ve
3196 
3197   Level: developer
3198 
3199   Notes:
3200   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3201 
3202   Most users should employ the simplified `KSP` interface for linear solvers
3203   instead of working directly with matrix algebra routines such as this.
3204   See, e.g., `KSPCreate()`.
3205 
3206   Developer Note:
3207   The Fortran interface is not autogenerated as the
3208   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3209 
3210 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3211 @*/
3212 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3213 {
3214   MatFactorInfo tinfo;
3215 
3216   PetscFunctionBegin;
3217   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3218   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3219   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3220   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3221   if (info) PetscAssertPointer(info, 5);
3222   PetscValidType(fact, 1);
3223   PetscValidType(mat, 2);
3224   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3225   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3226   MatCheckPreallocated(mat, 2);
3227   if (!info) {
3228     PetscCall(MatFactorInfoInitialize(&tinfo));
3229     info = &tinfo;
3230   }
3231 
3232   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3233   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3234   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3235   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3236   PetscFunctionReturn(PETSC_SUCCESS);
3237 }
3238 
3239 /*@C
3240   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3241   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3242 
3243   Collective
3244 
3245   Input Parameters:
3246 + fact - the factor matrix obtained with `MatGetFactor()`
3247 . mat  - the matrix
3248 - info - options for factorization
3249 
3250   Level: developer
3251 
3252   Notes:
3253   See `MatLUFactor()` for in-place factorization.  See
3254   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3255 
3256   Most users should employ the `KSP` interface for linear solvers
3257   instead of working directly with matrix algebra routines such as this.
3258   See, e.g., `KSPCreate()`.
3259 
3260   Developer Note:
3261   The Fortran interface is not autogenerated as the
3262   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3263 
3264 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3265 @*/
3266 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3267 {
3268   MatFactorInfo tinfo;
3269 
3270   PetscFunctionBegin;
3271   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3272   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3273   PetscValidType(fact, 1);
3274   PetscValidType(mat, 2);
3275   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3276   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,
3277              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3278 
3279   MatCheckPreallocated(mat, 2);
3280   if (!info) {
3281     PetscCall(MatFactorInfoInitialize(&tinfo));
3282     info = &tinfo;
3283   }
3284 
3285   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3286   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3287   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3288   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3289   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3290   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3291   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3292   PetscFunctionReturn(PETSC_SUCCESS);
3293 }
3294 
3295 /*@C
3296   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3297   symmetric matrix.
3298 
3299   Collective
3300 
3301   Input Parameters:
3302 + mat  - the matrix
3303 . perm - row and column permutations
3304 - info - expected fill as ratio of original fill
3305 
3306   Level: developer
3307 
3308   Notes:
3309   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3310   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3311 
3312   Most users should employ the `KSP` interface for linear solvers
3313   instead of working directly with matrix algebra routines such as this.
3314   See, e.g., `KSPCreate()`.
3315 
3316   Developer Note:
3317   The Fortran interface is not autogenerated as the
3318   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3319 
3320 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3321           `MatGetOrdering()`
3322 @*/
3323 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3324 {
3325   MatFactorInfo tinfo;
3326 
3327   PetscFunctionBegin;
3328   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3329   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3330   if (info) PetscAssertPointer(info, 3);
3331   PetscValidType(mat, 1);
3332   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3333   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3334   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3335   MatCheckPreallocated(mat, 1);
3336   if (!info) {
3337     PetscCall(MatFactorInfoInitialize(&tinfo));
3338     info = &tinfo;
3339   }
3340 
3341   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3342   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3343   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3344   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3345   PetscFunctionReturn(PETSC_SUCCESS);
3346 }
3347 
3348 /*@C
3349   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3350   of a symmetric matrix.
3351 
3352   Collective
3353 
3354   Input Parameters:
3355 + fact - the factor matrix obtained with `MatGetFactor()`
3356 . mat  - the matrix
3357 . perm - row and column permutations
3358 - info - options for factorization, includes
3359 .vb
3360           fill - expected fill as ratio of original fill.
3361           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3362                    Run with the option -info to determine an optimal value to use
3363 .ve
3364 
3365   Level: developer
3366 
3367   Notes:
3368   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3369   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3370 
3371   Most users should employ the `KSP` interface for linear solvers
3372   instead of working directly with matrix algebra routines such as this.
3373   See, e.g., `KSPCreate()`.
3374 
3375   Developer Note:
3376   The Fortran interface is not autogenerated as the
3377   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3378 
3379 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3380           `MatGetOrdering()`
3381 @*/
3382 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3383 {
3384   MatFactorInfo tinfo;
3385 
3386   PetscFunctionBegin;
3387   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3388   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3389   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3390   if (info) PetscAssertPointer(info, 4);
3391   PetscValidType(fact, 1);
3392   PetscValidType(mat, 2);
3393   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3394   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3395   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3396   MatCheckPreallocated(mat, 2);
3397   if (!info) {
3398     PetscCall(MatFactorInfoInitialize(&tinfo));
3399     info = &tinfo;
3400   }
3401 
3402   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3403   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3404   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3405   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3406   PetscFunctionReturn(PETSC_SUCCESS);
3407 }
3408 
3409 /*@C
3410   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3411   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3412   `MatCholeskyFactorSymbolic()`.
3413 
3414   Collective
3415 
3416   Input Parameters:
3417 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3418 . mat  - the initial matrix that is to be factored
3419 - info - options for factorization
3420 
3421   Level: developer
3422 
3423   Note:
3424   Most users should employ the `KSP` interface for linear solvers
3425   instead of working directly with matrix algebra routines such as this.
3426   See, e.g., `KSPCreate()`.
3427 
3428   Developer Note:
3429   The Fortran interface is not autogenerated as the
3430   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3431 
3432 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3433 @*/
3434 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3435 {
3436   MatFactorInfo tinfo;
3437 
3438   PetscFunctionBegin;
3439   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3440   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3441   PetscValidType(fact, 1);
3442   PetscValidType(mat, 2);
3443   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3444   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,
3445              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3446   MatCheckPreallocated(mat, 2);
3447   if (!info) {
3448     PetscCall(MatFactorInfoInitialize(&tinfo));
3449     info = &tinfo;
3450   }
3451 
3452   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3453   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3454   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3455   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3456   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3457   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3458   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3459   PetscFunctionReturn(PETSC_SUCCESS);
3460 }
3461 
3462 /*@
3463   MatQRFactor - Performs in-place QR factorization of matrix.
3464 
3465   Collective
3466 
3467   Input Parameters:
3468 + mat  - the matrix
3469 . col  - column permutation
3470 - info - options for factorization, includes
3471 .vb
3472           fill - expected fill as ratio of original fill.
3473           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3474                    Run with the option -info to determine an optimal value to use
3475 .ve
3476 
3477   Level: developer
3478 
3479   Notes:
3480   Most users should employ the `KSP` interface for linear solvers
3481   instead of working directly with matrix algebra routines such as this.
3482   See, e.g., `KSPCreate()`.
3483 
3484   This changes the state of the matrix to a factored matrix; it cannot be used
3485   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3486 
3487   Developer Note:
3488   The Fortran interface is not autogenerated as the
3489   interface definition cannot be generated correctly [due to MatFactorInfo]
3490 
3491 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3492           `MatSetUnfactored()`
3493 @*/
3494 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3495 {
3496   PetscFunctionBegin;
3497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3498   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3499   if (info) PetscAssertPointer(info, 3);
3500   PetscValidType(mat, 1);
3501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3503   MatCheckPreallocated(mat, 1);
3504   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3505   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3506   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3507   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3508   PetscFunctionReturn(PETSC_SUCCESS);
3509 }
3510 
3511 /*@
3512   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3513   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3514 
3515   Collective
3516 
3517   Input Parameters:
3518 + fact - the factor matrix obtained with `MatGetFactor()`
3519 . mat  - the matrix
3520 . col  - column permutation
3521 - info - options for factorization, includes
3522 .vb
3523           fill - expected fill as ratio of original fill.
3524           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3525                    Run with the option -info to determine an optimal value to use
3526 .ve
3527 
3528   Level: developer
3529 
3530   Note:
3531   Most users should employ the `KSP` interface for linear solvers
3532   instead of working directly with matrix algebra routines such as this.
3533   See, e.g., `KSPCreate()`.
3534 
3535   Developer Note:
3536   The Fortran interface is not autogenerated as the
3537   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3538 
3539 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3540 @*/
3541 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3542 {
3543   MatFactorInfo tinfo;
3544 
3545   PetscFunctionBegin;
3546   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3548   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3549   if (info) PetscAssertPointer(info, 4);
3550   PetscValidType(fact, 1);
3551   PetscValidType(mat, 2);
3552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3554   MatCheckPreallocated(mat, 2);
3555   if (!info) {
3556     PetscCall(MatFactorInfoInitialize(&tinfo));
3557     info = &tinfo;
3558   }
3559 
3560   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3561   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3562   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3563   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3564   PetscFunctionReturn(PETSC_SUCCESS);
3565 }
3566 
3567 /*@
3568   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3569   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3570 
3571   Collective
3572 
3573   Input Parameters:
3574 + fact - the factor matrix obtained with `MatGetFactor()`
3575 . mat  - the matrix
3576 - info - options for factorization
3577 
3578   Level: developer
3579 
3580   Notes:
3581   See `MatQRFactor()` for in-place factorization.
3582 
3583   Most users should employ the `KSP` interface for linear solvers
3584   instead of working directly with matrix algebra routines such as this.
3585   See, e.g., `KSPCreate()`.
3586 
3587   Developer Note:
3588   The Fortran interface is not autogenerated as the
3589   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3590 
3591 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3592 @*/
3593 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3594 {
3595   MatFactorInfo tinfo;
3596 
3597   PetscFunctionBegin;
3598   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3600   PetscValidType(fact, 1);
3601   PetscValidType(mat, 2);
3602   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3603   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,
3604              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3605 
3606   MatCheckPreallocated(mat, 2);
3607   if (!info) {
3608     PetscCall(MatFactorInfoInitialize(&tinfo));
3609     info = &tinfo;
3610   }
3611 
3612   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3613   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3614   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3615   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3616   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3617   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3618   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3619   PetscFunctionReturn(PETSC_SUCCESS);
3620 }
3621 
3622 /*@
3623   MatSolve - Solves $A x = b$, given a factored matrix.
3624 
3625   Neighbor-wise Collective
3626 
3627   Input Parameters:
3628 + mat - the factored matrix
3629 - b   - the right-hand-side vector
3630 
3631   Output Parameter:
3632 . x - the result vector
3633 
3634   Level: developer
3635 
3636   Notes:
3637   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3638   call `MatSolve`(A,x,x).
3639 
3640   Most users should employ the `KSP` interface for linear solvers
3641   instead of working directly with matrix algebra routines such as this.
3642   See, e.g., `KSPCreate()`.
3643 
3644 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3645 @*/
3646 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3647 {
3648   PetscFunctionBegin;
3649   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3650   PetscValidType(mat, 1);
3651   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3652   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3653   PetscCheckSameComm(mat, 1, b, 2);
3654   PetscCheckSameComm(mat, 1, x, 3);
3655   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3656   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);
3657   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);
3658   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);
3659   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3660   MatCheckPreallocated(mat, 1);
3661 
3662   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3663   if (mat->factorerrortype) {
3664     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3665     PetscCall(VecSetInf(x));
3666   } else PetscUseTypeMethod(mat, solve, b, x);
3667   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3668   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3669   PetscFunctionReturn(PETSC_SUCCESS);
3670 }
3671 
3672 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3673 {
3674   Vec      b, x;
3675   PetscInt N, i;
3676   PetscErrorCode (*f)(Mat, Vec, Vec);
3677   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3678 
3679   PetscFunctionBegin;
3680   if (A->factorerrortype) {
3681     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3682     PetscCall(MatSetInf(X));
3683     PetscFunctionReturn(PETSC_SUCCESS);
3684   }
3685   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3686   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3687   PetscCall(MatBoundToCPU(A, &Abound));
3688   if (!Abound) {
3689     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3690     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3691   }
3692 #if PetscDefined(HAVE_CUDA)
3693   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3694   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3695 #elif PetscDefined(HAVE_HIP)
3696   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3697   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3698 #endif
3699   PetscCall(MatGetSize(B, NULL, &N));
3700   for (i = 0; i < N; i++) {
3701     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3702     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3703     PetscCall((*f)(A, b, x));
3704     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3705     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3706   }
3707   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3708   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3709   PetscFunctionReturn(PETSC_SUCCESS);
3710 }
3711 
3712 /*@
3713   MatMatSolve - Solves $A X = B$, given a factored matrix.
3714 
3715   Neighbor-wise Collective
3716 
3717   Input Parameters:
3718 + A - the factored matrix
3719 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3720 
3721   Output Parameter:
3722 . X - the result matrix (dense matrix)
3723 
3724   Level: developer
3725 
3726   Note:
3727   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3728   otherwise, `B` and `X` cannot be the same.
3729 
3730 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3731 @*/
3732 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3733 {
3734   PetscFunctionBegin;
3735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3736   PetscValidType(A, 1);
3737   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3738   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3739   PetscCheckSameComm(A, 1, B, 2);
3740   PetscCheckSameComm(A, 1, X, 3);
3741   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);
3742   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);
3743   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");
3744   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3745   MatCheckPreallocated(A, 1);
3746 
3747   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3748   if (!A->ops->matsolve) {
3749     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3750     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3751   } else PetscUseTypeMethod(A, matsolve, B, X);
3752   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3753   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3754   PetscFunctionReturn(PETSC_SUCCESS);
3755 }
3756 
3757 /*@
3758   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3759 
3760   Neighbor-wise Collective
3761 
3762   Input Parameters:
3763 + A - the factored matrix
3764 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3765 
3766   Output Parameter:
3767 . X - the result matrix (dense matrix)
3768 
3769   Level: developer
3770 
3771   Note:
3772   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3773   call `MatMatSolveTranspose`(A,X,X).
3774 
3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3776 @*/
3777 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3778 {
3779   PetscFunctionBegin;
3780   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3781   PetscValidType(A, 1);
3782   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3783   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3784   PetscCheckSameComm(A, 1, B, 2);
3785   PetscCheckSameComm(A, 1, X, 3);
3786   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3787   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);
3788   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);
3789   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);
3790   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");
3791   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3792   MatCheckPreallocated(A, 1);
3793 
3794   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3795   if (!A->ops->matsolvetranspose) {
3796     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3797     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3798   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3799   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3800   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3801   PetscFunctionReturn(PETSC_SUCCESS);
3802 }
3803 
3804 /*@
3805   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3806 
3807   Neighbor-wise Collective
3808 
3809   Input Parameters:
3810 + A  - the factored matrix
3811 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3812 
3813   Output Parameter:
3814 . X - the result matrix (dense matrix)
3815 
3816   Level: developer
3817 
3818   Note:
3819   For MUMPS, it only supports centralized sparse compressed column format on the host processor for right-hand side matrix. User must create `Bt` in sparse compressed row
3820   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3821 
3822 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3823 @*/
3824 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3825 {
3826   PetscFunctionBegin;
3827   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3828   PetscValidType(A, 1);
3829   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3830   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3831   PetscCheckSameComm(A, 1, Bt, 2);
3832   PetscCheckSameComm(A, 1, X, 3);
3833 
3834   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3835   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);
3836   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);
3837   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");
3838   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3839   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3840   MatCheckPreallocated(A, 1);
3841 
3842   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3843   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3844   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3845   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3846   PetscFunctionReturn(PETSC_SUCCESS);
3847 }
3848 
3849 /*@
3850   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3851   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3852 
3853   Neighbor-wise Collective
3854 
3855   Input Parameters:
3856 + mat - the factored matrix
3857 - b   - the right-hand-side vector
3858 
3859   Output Parameter:
3860 . x - the result vector
3861 
3862   Level: developer
3863 
3864   Notes:
3865   `MatSolve()` should be used for most applications, as it performs
3866   a forward solve followed by a backward solve.
3867 
3868   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3869   call `MatForwardSolve`(A,x,x).
3870 
3871   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3872   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3873   `MatForwardSolve()` solves $U^T*D y = b$, and
3874   `MatBackwardSolve()` solves $U x = y$.
3875   Thus they do not provide a symmetric preconditioner.
3876 
3877 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3878 @*/
3879 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3880 {
3881   PetscFunctionBegin;
3882   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3883   PetscValidType(mat, 1);
3884   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3885   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3886   PetscCheckSameComm(mat, 1, b, 2);
3887   PetscCheckSameComm(mat, 1, x, 3);
3888   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3889   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);
3890   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);
3891   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);
3892   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3893   MatCheckPreallocated(mat, 1);
3894 
3895   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3896   PetscUseTypeMethod(mat, forwardsolve, b, x);
3897   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3898   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3899   PetscFunctionReturn(PETSC_SUCCESS);
3900 }
3901 
3902 /*@
3903   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3904   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3905 
3906   Neighbor-wise Collective
3907 
3908   Input Parameters:
3909 + mat - the factored matrix
3910 - b   - the right-hand-side vector
3911 
3912   Output Parameter:
3913 . x - the result vector
3914 
3915   Level: developer
3916 
3917   Notes:
3918   `MatSolve()` should be used for most applications, as it performs
3919   a forward solve followed by a backward solve.
3920 
3921   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3922   call `MatBackwardSolve`(A,x,x).
3923 
3924   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3925   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3926   `MatForwardSolve()` solves $U^T*D y = b$, and
3927   `MatBackwardSolve()` solves $U x = y$.
3928   Thus they do not provide a symmetric preconditioner.
3929 
3930 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3931 @*/
3932 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3933 {
3934   PetscFunctionBegin;
3935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3936   PetscValidType(mat, 1);
3937   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3938   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3939   PetscCheckSameComm(mat, 1, b, 2);
3940   PetscCheckSameComm(mat, 1, x, 3);
3941   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3942   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);
3943   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);
3944   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);
3945   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3946   MatCheckPreallocated(mat, 1);
3947 
3948   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3949   PetscUseTypeMethod(mat, backwardsolve, b, x);
3950   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3951   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3952   PetscFunctionReturn(PETSC_SUCCESS);
3953 }
3954 
3955 /*@
3956   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3957 
3958   Neighbor-wise Collective
3959 
3960   Input Parameters:
3961 + mat - the factored matrix
3962 . b   - the right-hand-side vector
3963 - y   - the vector to be added to
3964 
3965   Output Parameter:
3966 . x - the result vector
3967 
3968   Level: developer
3969 
3970   Note:
3971   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3972   call `MatSolveAdd`(A,x,y,x).
3973 
3974 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3975 @*/
3976 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3977 {
3978   PetscScalar one = 1.0;
3979   Vec         tmp;
3980 
3981   PetscFunctionBegin;
3982   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3983   PetscValidType(mat, 1);
3984   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3985   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3986   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3987   PetscCheckSameComm(mat, 1, b, 2);
3988   PetscCheckSameComm(mat, 1, y, 3);
3989   PetscCheckSameComm(mat, 1, x, 4);
3990   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3991   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);
3992   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);
3993   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);
3994   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);
3995   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);
3996   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3997   MatCheckPreallocated(mat, 1);
3998 
3999   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4000   if (mat->factorerrortype) {
4001     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4002     PetscCall(VecSetInf(x));
4003   } else if (mat->ops->solveadd) {
4004     PetscUseTypeMethod(mat, solveadd, b, y, x);
4005   } else {
4006     /* do the solve then the add manually */
4007     if (x != y) {
4008       PetscCall(MatSolve(mat, b, x));
4009       PetscCall(VecAXPY(x, one, y));
4010     } else {
4011       PetscCall(VecDuplicate(x, &tmp));
4012       PetscCall(VecCopy(x, tmp));
4013       PetscCall(MatSolve(mat, b, x));
4014       PetscCall(VecAXPY(x, one, tmp));
4015       PetscCall(VecDestroy(&tmp));
4016     }
4017   }
4018   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4019   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4020   PetscFunctionReturn(PETSC_SUCCESS);
4021 }
4022 
4023 /*@
4024   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4025 
4026   Neighbor-wise Collective
4027 
4028   Input Parameters:
4029 + mat - the factored matrix
4030 - b   - the right-hand-side vector
4031 
4032   Output Parameter:
4033 . x - the result vector
4034 
4035   Level: developer
4036 
4037   Notes:
4038   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4039   call `MatSolveTranspose`(A,x,x).
4040 
4041   Most users should employ the `KSP` interface for linear solvers
4042   instead of working directly with matrix algebra routines such as this.
4043   See, e.g., `KSPCreate()`.
4044 
4045 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4046 @*/
4047 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4048 {
4049   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4050 
4051   PetscFunctionBegin;
4052   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4053   PetscValidType(mat, 1);
4054   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4055   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4056   PetscCheckSameComm(mat, 1, b, 2);
4057   PetscCheckSameComm(mat, 1, x, 3);
4058   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4059   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);
4060   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);
4061   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4062   MatCheckPreallocated(mat, 1);
4063   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4064   if (mat->factorerrortype) {
4065     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4066     PetscCall(VecSetInf(x));
4067   } else {
4068     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4069     PetscCall((*f)(mat, b, x));
4070   }
4071   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4072   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4073   PetscFunctionReturn(PETSC_SUCCESS);
4074 }
4075 
4076 /*@
4077   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4078   factored matrix.
4079 
4080   Neighbor-wise Collective
4081 
4082   Input Parameters:
4083 + mat - the factored matrix
4084 . b   - the right-hand-side vector
4085 - y   - the vector to be added to
4086 
4087   Output Parameter:
4088 . x - the result vector
4089 
4090   Level: developer
4091 
4092   Note:
4093   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4094   call `MatSolveTransposeAdd`(A,x,y,x).
4095 
4096 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4097 @*/
4098 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4099 {
4100   PetscScalar one = 1.0;
4101   Vec         tmp;
4102   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4103 
4104   PetscFunctionBegin;
4105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4106   PetscValidType(mat, 1);
4107   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4108   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4109   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4110   PetscCheckSameComm(mat, 1, b, 2);
4111   PetscCheckSameComm(mat, 1, y, 3);
4112   PetscCheckSameComm(mat, 1, x, 4);
4113   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4114   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);
4115   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);
4116   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);
4117   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);
4118   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4119   MatCheckPreallocated(mat, 1);
4120 
4121   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4122   if (mat->factorerrortype) {
4123     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4124     PetscCall(VecSetInf(x));
4125   } else if (f) {
4126     PetscCall((*f)(mat, b, y, x));
4127   } else {
4128     /* do the solve then the add manually */
4129     if (x != y) {
4130       PetscCall(MatSolveTranspose(mat, b, x));
4131       PetscCall(VecAXPY(x, one, y));
4132     } else {
4133       PetscCall(VecDuplicate(x, &tmp));
4134       PetscCall(VecCopy(x, tmp));
4135       PetscCall(MatSolveTranspose(mat, b, x));
4136       PetscCall(VecAXPY(x, one, tmp));
4137       PetscCall(VecDestroy(&tmp));
4138     }
4139   }
4140   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4141   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4142   PetscFunctionReturn(PETSC_SUCCESS);
4143 }
4144 
4145 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4146 /*@
4147   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4148 
4149   Neighbor-wise Collective
4150 
4151   Input Parameters:
4152 + mat   - the matrix
4153 . b     - the right-hand side
4154 . omega - the relaxation factor
4155 . flag  - flag indicating the type of SOR (see below)
4156 . shift - diagonal shift
4157 . its   - the number of iterations
4158 - lits  - the number of local iterations
4159 
4160   Output Parameter:
4161 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4162 
4163   SOR Flags:
4164 +     `SOR_FORWARD_SWEEP` - forward SOR
4165 .     `SOR_BACKWARD_SWEEP` - backward SOR
4166 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4167 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4168 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4169 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4170 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4171 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4172   upper/lower triangular part of matrix to
4173   vector (with omega)
4174 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4175 
4176   Level: developer
4177 
4178   Notes:
4179   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4180   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4181   on each processor.
4182 
4183   Application programmers will not generally use `MatSOR()` directly,
4184   but instead will employ the `KSP`/`PC` interface.
4185 
4186   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4187 
4188   Most users should employ the `KSP` interface for linear solvers
4189   instead of working directly with matrix algebra routines such as this.
4190   See, e.g., `KSPCreate()`.
4191 
4192   Vectors `x` and `b` CANNOT be the same
4193 
4194   The flags are implemented as bitwise inclusive or operations.
4195   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4196   to specify a zero initial guess for SSOR.
4197 
4198   Developer Note:
4199   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4200 
4201 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4202 @*/
4203 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4204 {
4205   PetscFunctionBegin;
4206   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4207   PetscValidType(mat, 1);
4208   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4209   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4210   PetscCheckSameComm(mat, 1, b, 2);
4211   PetscCheckSameComm(mat, 1, x, 8);
4212   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4213   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4214   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);
4215   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);
4216   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);
4217   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4218   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4219   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4220 
4221   MatCheckPreallocated(mat, 1);
4222   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4223   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4224   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4225   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4226   PetscFunctionReturn(PETSC_SUCCESS);
4227 }
4228 
4229 /*
4230       Default matrix copy routine.
4231 */
4232 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4233 {
4234   PetscInt           i, rstart = 0, rend = 0, nz;
4235   const PetscInt    *cwork;
4236   const PetscScalar *vwork;
4237 
4238   PetscFunctionBegin;
4239   if (B->assembled) PetscCall(MatZeroEntries(B));
4240   if (str == SAME_NONZERO_PATTERN) {
4241     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4242     for (i = rstart; i < rend; i++) {
4243       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4244       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4245       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4246     }
4247   } else {
4248     PetscCall(MatAYPX(B, 0.0, A, str));
4249   }
4250   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4251   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4252   PetscFunctionReturn(PETSC_SUCCESS);
4253 }
4254 
4255 /*@
4256   MatCopy - Copies a matrix to another matrix.
4257 
4258   Collective
4259 
4260   Input Parameters:
4261 + A   - the matrix
4262 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4263 
4264   Output Parameter:
4265 . B - where the copy is put
4266 
4267   Level: intermediate
4268 
4269   Notes:
4270   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4271 
4272   `MatCopy()` copies the matrix entries of a matrix to another existing
4273   matrix (after first zeroing the second matrix).  A related routine is
4274   `MatConvert()`, which first creates a new matrix and then copies the data.
4275 
4276 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4277 @*/
4278 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4279 {
4280   PetscInt i;
4281 
4282   PetscFunctionBegin;
4283   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4284   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4285   PetscValidType(A, 1);
4286   PetscValidType(B, 2);
4287   PetscCheckSameComm(A, 1, B, 2);
4288   MatCheckPreallocated(B, 2);
4289   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4290   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4291   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,
4292              A->cmap->N, B->cmap->N);
4293   MatCheckPreallocated(A, 1);
4294   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4295 
4296   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4297   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4298   else PetscCall(MatCopy_Basic(A, B, str));
4299 
4300   B->stencil.dim = A->stencil.dim;
4301   B->stencil.noc = A->stencil.noc;
4302   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4303     B->stencil.dims[i]   = A->stencil.dims[i];
4304     B->stencil.starts[i] = A->stencil.starts[i];
4305   }
4306 
4307   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4308   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4309   PetscFunctionReturn(PETSC_SUCCESS);
4310 }
4311 
4312 /*@
4313   MatConvert - Converts a matrix to another matrix, either of the same
4314   or different type.
4315 
4316   Collective
4317 
4318   Input Parameters:
4319 + mat     - the matrix
4320 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4321             same type as the original matrix.
4322 - reuse   - denotes if the destination matrix is to be created or reused.
4323             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
4324             `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).
4325 
4326   Output Parameter:
4327 . M - pointer to place new matrix
4328 
4329   Level: intermediate
4330 
4331   Notes:
4332   `MatConvert()` first creates a new matrix and then copies the data from
4333   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4334   entries of one matrix to another already existing matrix context.
4335 
4336   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4337   the MPI communicator of the generated matrix is always the same as the communicator
4338   of the input matrix.
4339 
4340 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4341 @*/
4342 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4343 {
4344   PetscBool  sametype, issame, flg;
4345   PetscBool3 issymmetric, ishermitian;
4346   char       convname[256], mtype[256];
4347   Mat        B;
4348 
4349   PetscFunctionBegin;
4350   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4351   PetscValidType(mat, 1);
4352   PetscAssertPointer(M, 4);
4353   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4354   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4355   MatCheckPreallocated(mat, 1);
4356 
4357   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4358   if (flg) newtype = mtype;
4359 
4360   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4361   PetscCall(PetscStrcmp(newtype, "same", &issame));
4362   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4363   if (reuse == MAT_REUSE_MATRIX) {
4364     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4365     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4366   }
4367 
4368   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4369     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4370     PetscFunctionReturn(PETSC_SUCCESS);
4371   }
4372 
4373   /* Cache Mat options because some converters use MatHeaderReplace  */
4374   issymmetric = mat->symmetric;
4375   ishermitian = mat->hermitian;
4376 
4377   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4378     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4379     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4380   } else {
4381     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4382     const char *prefix[3]                                 = {"seq", "mpi", ""};
4383     PetscInt    i;
4384     /*
4385        Order of precedence:
4386        0) See if newtype is a superclass of the current matrix.
4387        1) See if a specialized converter is known to the current matrix.
4388        2) See if a specialized converter is known to the desired matrix class.
4389        3) See if a good general converter is registered for the desired class
4390           (as of 6/27/03 only MATMPIADJ falls into this category).
4391        4) See if a good general converter is known for the current matrix.
4392        5) Use a really basic converter.
4393     */
4394 
4395     /* 0) See if newtype is a superclass of the current matrix.
4396           i.e mat is mpiaij and newtype is aij */
4397     for (i = 0; i < 2; i++) {
4398       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4399       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4400       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4401       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4402       if (flg) {
4403         if (reuse == MAT_INPLACE_MATRIX) {
4404           PetscCall(PetscInfo(mat, "Early return\n"));
4405           PetscFunctionReturn(PETSC_SUCCESS);
4406         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4407           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4408           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4409           PetscFunctionReturn(PETSC_SUCCESS);
4410         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4411           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4412           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4413           PetscFunctionReturn(PETSC_SUCCESS);
4414         }
4415       }
4416     }
4417     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4418     for (i = 0; i < 3; i++) {
4419       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4420       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4421       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4422       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4423       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4424       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4425       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4426       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4427       if (conv) goto foundconv;
4428     }
4429 
4430     /* 2)  See if a specialized converter is known to the desired matrix class. */
4431     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4432     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4433     PetscCall(MatSetType(B, newtype));
4434     for (i = 0; i < 3; i++) {
4435       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4436       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4437       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4438       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4439       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4440       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4441       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4442       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4443       if (conv) {
4444         PetscCall(MatDestroy(&B));
4445         goto foundconv;
4446       }
4447     }
4448 
4449     /* 3) See if a good general converter is registered for the desired class */
4450     conv = B->ops->convertfrom;
4451     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4452     PetscCall(MatDestroy(&B));
4453     if (conv) goto foundconv;
4454 
4455     /* 4) See if a good general converter is known for the current matrix */
4456     if (mat->ops->convert) conv = mat->ops->convert;
4457     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4458     if (conv) goto foundconv;
4459 
4460     /* 5) Use a really basic converter. */
4461     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4462     conv = MatConvert_Basic;
4463 
4464   foundconv:
4465     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4466     PetscCall((*conv)(mat, newtype, reuse, M));
4467     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4468       /* the block sizes must be same if the mappings are copied over */
4469       (*M)->rmap->bs = mat->rmap->bs;
4470       (*M)->cmap->bs = mat->cmap->bs;
4471       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4472       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4473       (*M)->rmap->mapping = mat->rmap->mapping;
4474       (*M)->cmap->mapping = mat->cmap->mapping;
4475     }
4476     (*M)->stencil.dim = mat->stencil.dim;
4477     (*M)->stencil.noc = mat->stencil.noc;
4478     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4479       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4480       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4481     }
4482     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4483   }
4484   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4485 
4486   /* Copy Mat options */
4487   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4488   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4489   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4490   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4491   PetscFunctionReturn(PETSC_SUCCESS);
4492 }
4493 
4494 /*@C
4495   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4496 
4497   Not Collective
4498 
4499   Input Parameter:
4500 . mat - the matrix, must be a factored matrix
4501 
4502   Output Parameter:
4503 . type - the string name of the package (do not free this string)
4504 
4505   Level: intermediate
4506 
4507   Fortran Note:
4508   Pass in an empty string that is long enough and the package name will be copied into it.
4509 
4510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4511 @*/
4512 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4513 {
4514   PetscErrorCode (*conv)(Mat, MatSolverType *);
4515 
4516   PetscFunctionBegin;
4517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4518   PetscValidType(mat, 1);
4519   PetscAssertPointer(type, 2);
4520   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4521   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4522   if (conv) PetscCall((*conv)(mat, type));
4523   else *type = MATSOLVERPETSC;
4524   PetscFunctionReturn(PETSC_SUCCESS);
4525 }
4526 
4527 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4528 struct _MatSolverTypeForSpecifcType {
4529   MatType mtype;
4530   /* no entry for MAT_FACTOR_NONE */
4531   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4532   MatSolverTypeForSpecifcType next;
4533 };
4534 
4535 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4536 struct _MatSolverTypeHolder {
4537   char                       *name;
4538   MatSolverTypeForSpecifcType handlers;
4539   MatSolverTypeHolder         next;
4540 };
4541 
4542 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4543 
4544 /*@C
4545   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4546 
4547   Logically Collective, No Fortran Support
4548 
4549   Input Parameters:
4550 + package      - name of the package, for example petsc or superlu
4551 . mtype        - the matrix type that works with this package
4552 . ftype        - the type of factorization supported by the package
4553 - createfactor - routine that will create the factored matrix ready to be used
4554 
4555   Level: developer
4556 
4557 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4558   `MatGetFactor()`
4559 @*/
4560 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4561 {
4562   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4563   PetscBool                   flg;
4564   MatSolverTypeForSpecifcType inext, iprev = NULL;
4565 
4566   PetscFunctionBegin;
4567   PetscCall(MatInitializePackage());
4568   if (!next) {
4569     PetscCall(PetscNew(&MatSolverTypeHolders));
4570     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4571     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4572     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4573     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4574     PetscFunctionReturn(PETSC_SUCCESS);
4575   }
4576   while (next) {
4577     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4578     if (flg) {
4579       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4580       inext = next->handlers;
4581       while (inext) {
4582         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4583         if (flg) {
4584           inext->createfactor[(int)ftype - 1] = createfactor;
4585           PetscFunctionReturn(PETSC_SUCCESS);
4586         }
4587         iprev = inext;
4588         inext = inext->next;
4589       }
4590       PetscCall(PetscNew(&iprev->next));
4591       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4592       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4593       PetscFunctionReturn(PETSC_SUCCESS);
4594     }
4595     prev = next;
4596     next = next->next;
4597   }
4598   PetscCall(PetscNew(&prev->next));
4599   PetscCall(PetscStrallocpy(package, &prev->next->name));
4600   PetscCall(PetscNew(&prev->next->handlers));
4601   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4602   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4603   PetscFunctionReturn(PETSC_SUCCESS);
4604 }
4605 
4606 /*@C
4607   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4608 
4609   Input Parameters:
4610 + type  - name of the package, for example petsc or superlu, if this is 'NULL', then the first result that satisfies the other criteria is returned
4611 . ftype - the type of factorization supported by the type
4612 - mtype - the matrix type that works with this type
4613 
4614   Output Parameters:
4615 + foundtype    - `PETSC_TRUE` if the type was registered
4616 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4617 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4618 
4619   Calling sequence of `createfactor`:
4620 + A     - the matrix providing the factor matrix
4621 . mtype - the `MatType` of the factor requested
4622 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4623 
4624   Level: developer
4625 
4626   Note:
4627   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4628   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4629   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4630 
4631 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4632           `MatInitializePackage()`
4633 @*/
4634 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4635 {
4636   MatSolverTypeHolder         next = MatSolverTypeHolders;
4637   PetscBool                   flg;
4638   MatSolverTypeForSpecifcType inext;
4639 
4640   PetscFunctionBegin;
4641   if (foundtype) *foundtype = PETSC_FALSE;
4642   if (foundmtype) *foundmtype = PETSC_FALSE;
4643   if (createfactor) *createfactor = NULL;
4644 
4645   if (type) {
4646     while (next) {
4647       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4648       if (flg) {
4649         if (foundtype) *foundtype = PETSC_TRUE;
4650         inext = next->handlers;
4651         while (inext) {
4652           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4653           if (flg) {
4654             if (foundmtype) *foundmtype = PETSC_TRUE;
4655             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4656             PetscFunctionReturn(PETSC_SUCCESS);
4657           }
4658           inext = inext->next;
4659         }
4660       }
4661       next = next->next;
4662     }
4663   } else {
4664     while (next) {
4665       inext = next->handlers;
4666       while (inext) {
4667         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4668         if (flg && inext->createfactor[(int)ftype - 1]) {
4669           if (foundtype) *foundtype = PETSC_TRUE;
4670           if (foundmtype) *foundmtype = PETSC_TRUE;
4671           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4672           PetscFunctionReturn(PETSC_SUCCESS);
4673         }
4674         inext = inext->next;
4675       }
4676       next = next->next;
4677     }
4678     /* try with base classes inext->mtype */
4679     next = MatSolverTypeHolders;
4680     while (next) {
4681       inext = next->handlers;
4682       while (inext) {
4683         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4684         if (flg && inext->createfactor[(int)ftype - 1]) {
4685           if (foundtype) *foundtype = PETSC_TRUE;
4686           if (foundmtype) *foundmtype = PETSC_TRUE;
4687           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4688           PetscFunctionReturn(PETSC_SUCCESS);
4689         }
4690         inext = inext->next;
4691       }
4692       next = next->next;
4693     }
4694   }
4695   PetscFunctionReturn(PETSC_SUCCESS);
4696 }
4697 
4698 PetscErrorCode MatSolverTypeDestroy(void)
4699 {
4700   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4701   MatSolverTypeForSpecifcType inext, iprev;
4702 
4703   PetscFunctionBegin;
4704   while (next) {
4705     PetscCall(PetscFree(next->name));
4706     inext = next->handlers;
4707     while (inext) {
4708       PetscCall(PetscFree(inext->mtype));
4709       iprev = inext;
4710       inext = inext->next;
4711       PetscCall(PetscFree(iprev));
4712     }
4713     prev = next;
4714     next = next->next;
4715     PetscCall(PetscFree(prev));
4716   }
4717   MatSolverTypeHolders = NULL;
4718   PetscFunctionReturn(PETSC_SUCCESS);
4719 }
4720 
4721 /*@
4722   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4723 
4724   Logically Collective
4725 
4726   Input Parameter:
4727 . mat - the matrix
4728 
4729   Output Parameter:
4730 . flg - `PETSC_TRUE` if uses the ordering
4731 
4732   Level: developer
4733 
4734   Note:
4735   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4736   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4737 
4738 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4739 @*/
4740 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4741 {
4742   PetscFunctionBegin;
4743   *flg = mat->canuseordering;
4744   PetscFunctionReturn(PETSC_SUCCESS);
4745 }
4746 
4747 /*@
4748   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4749 
4750   Logically Collective
4751 
4752   Input Parameters:
4753 + mat   - the matrix obtained with `MatGetFactor()`
4754 - ftype - the factorization type to be used
4755 
4756   Output Parameter:
4757 . otype - the preferred ordering type
4758 
4759   Level: developer
4760 
4761 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4762 @*/
4763 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4764 {
4765   PetscFunctionBegin;
4766   *otype = mat->preferredordering[ftype];
4767   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4768   PetscFunctionReturn(PETSC_SUCCESS);
4769 }
4770 
4771 /*@
4772   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4773 
4774   Collective
4775 
4776   Input Parameters:
4777 + mat   - the matrix
4778 . type  - name of solver type, for example, superlu, petsc (to use PETSc's solver if it is available), if this is 'NULL', then the first result that satisfies
4779           the other criteria is returned
4780 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4781 
4782   Output Parameter:
4783 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4784 
4785   Options Database Keys:
4786 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4787 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4788                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4789 
4790   Level: intermediate
4791 
4792   Notes:
4793   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4794   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4795 
4796   Users usually access the factorization solvers via `KSP`
4797 
4798   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4799   such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir
4800 
4801   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4802   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4803   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4804 
4805   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4806   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4807   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4808 
4809   Developer Note:
4810   This should actually be called `MatCreateFactor()` since it creates a new factor object
4811 
4812 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4813           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4814           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4815 @*/
4816 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4817 {
4818   PetscBool foundtype, foundmtype;
4819   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4820 
4821   PetscFunctionBegin;
4822   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4823   PetscValidType(mat, 1);
4824 
4825   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4826   MatCheckPreallocated(mat, 1);
4827 
4828   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4829   if (!foundtype) {
4830     if (type) {
4831       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],
4832               ((PetscObject)mat)->type_name, type);
4833     } else {
4834       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);
4835     }
4836   }
4837   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4838   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);
4839 
4840   PetscCall((*conv)(mat, ftype, f));
4841   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4842   PetscFunctionReturn(PETSC_SUCCESS);
4843 }
4844 
4845 /*@
4846   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4847 
4848   Not Collective
4849 
4850   Input Parameters:
4851 + mat   - the matrix
4852 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4853 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4854 
4855   Output Parameter:
4856 . flg - PETSC_TRUE if the factorization is available
4857 
4858   Level: intermediate
4859 
4860   Notes:
4861   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4862   such as pastix, superlu, mumps etc.
4863 
4864   PETSc must have been ./configure to use the external solver, using the option --download-package
4865 
4866   Developer Note:
4867   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4868 
4869 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4870           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4871 @*/
4872 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4873 {
4874   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4875 
4876   PetscFunctionBegin;
4877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4878   PetscAssertPointer(flg, 4);
4879 
4880   *flg = PETSC_FALSE;
4881   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4882 
4883   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4884   MatCheckPreallocated(mat, 1);
4885 
4886   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4887   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4888   PetscFunctionReturn(PETSC_SUCCESS);
4889 }
4890 
4891 /*@
4892   MatDuplicate - Duplicates a matrix including the non-zero structure.
4893 
4894   Collective
4895 
4896   Input Parameters:
4897 + mat - the matrix
4898 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4899         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4900 
4901   Output Parameter:
4902 . M - pointer to place new matrix
4903 
4904   Level: intermediate
4905 
4906   Notes:
4907   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4908 
4909   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4910 
4911   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.
4912 
4913   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4914   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4915   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4916 
4917 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4918 @*/
4919 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4920 {
4921   Mat         B;
4922   VecType     vtype;
4923   PetscInt    i;
4924   PetscObject dm, container_h, container_d;
4925   void (*viewf)(void);
4926 
4927   PetscFunctionBegin;
4928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4929   PetscValidType(mat, 1);
4930   PetscAssertPointer(M, 3);
4931   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4932   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4933   MatCheckPreallocated(mat, 1);
4934 
4935   *M = NULL;
4936   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4937   PetscUseTypeMethod(mat, duplicate, op, M);
4938   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4939   B = *M;
4940 
4941   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4942   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4943   PetscCall(MatGetVecType(mat, &vtype));
4944   PetscCall(MatSetVecType(B, vtype));
4945 
4946   B->stencil.dim = mat->stencil.dim;
4947   B->stencil.noc = mat->stencil.noc;
4948   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4949     B->stencil.dims[i]   = mat->stencil.dims[i];
4950     B->stencil.starts[i] = mat->stencil.starts[i];
4951   }
4952 
4953   B->nooffproczerorows = mat->nooffproczerorows;
4954   B->nooffprocentries  = mat->nooffprocentries;
4955 
4956   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4957   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4958   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4959   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4960   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4961   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4962   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4963   PetscFunctionReturn(PETSC_SUCCESS);
4964 }
4965 
4966 /*@
4967   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4968 
4969   Logically Collective
4970 
4971   Input Parameter:
4972 . mat - the matrix
4973 
4974   Output Parameter:
4975 . v - the diagonal of the matrix
4976 
4977   Level: intermediate
4978 
4979   Note:
4980   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4981   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4982   is larger than `ndiag`, the values of the remaining entries are unspecified.
4983 
4984   Currently only correct in parallel for square matrices.
4985 
4986 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4987 @*/
4988 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4989 {
4990   PetscFunctionBegin;
4991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4992   PetscValidType(mat, 1);
4993   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4994   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4995   MatCheckPreallocated(mat, 1);
4996   if (PetscDefined(USE_DEBUG)) {
4997     PetscInt nv, row, col, ndiag;
4998 
4999     PetscCall(VecGetLocalSize(v, &nv));
5000     PetscCall(MatGetLocalSize(mat, &row, &col));
5001     ndiag = PetscMin(row, col);
5002     PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag);
5003   }
5004 
5005   PetscUseTypeMethod(mat, getdiagonal, v);
5006   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5007   PetscFunctionReturn(PETSC_SUCCESS);
5008 }
5009 
5010 /*@
5011   MatGetRowMin - Gets the minimum value (of the real part) of each
5012   row of the matrix
5013 
5014   Logically Collective
5015 
5016   Input Parameter:
5017 . mat - the matrix
5018 
5019   Output Parameters:
5020 + v   - the vector for storing the maximums
5021 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5022 
5023   Level: intermediate
5024 
5025   Note:
5026   The result of this call are the same as if one converted the matrix to dense format
5027   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5028 
5029   This code is only implemented for a couple of matrix formats.
5030 
5031 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5032           `MatGetRowMax()`
5033 @*/
5034 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5035 {
5036   PetscFunctionBegin;
5037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5038   PetscValidType(mat, 1);
5039   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5040   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5041 
5042   if (!mat->cmap->N) {
5043     PetscCall(VecSet(v, PETSC_MAX_REAL));
5044     if (idx) {
5045       PetscInt i, m = mat->rmap->n;
5046       for (i = 0; i < m; i++) idx[i] = -1;
5047     }
5048   } else {
5049     MatCheckPreallocated(mat, 1);
5050   }
5051   PetscUseTypeMethod(mat, getrowmin, v, idx);
5052   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5053   PetscFunctionReturn(PETSC_SUCCESS);
5054 }
5055 
5056 /*@
5057   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5058   row of the matrix
5059 
5060   Logically Collective
5061 
5062   Input Parameter:
5063 . mat - the matrix
5064 
5065   Output Parameters:
5066 + v   - the vector for storing the minimums
5067 - idx - the indices of the column found for each row (or `NULL` if not needed)
5068 
5069   Level: intermediate
5070 
5071   Notes:
5072   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5073   row is 0 (the first column).
5074 
5075   This code is only implemented for a couple of matrix formats.
5076 
5077 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5078 @*/
5079 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5080 {
5081   PetscFunctionBegin;
5082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5083   PetscValidType(mat, 1);
5084   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5085   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5086   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5087 
5088   if (!mat->cmap->N) {
5089     PetscCall(VecSet(v, 0.0));
5090     if (idx) {
5091       PetscInt i, m = mat->rmap->n;
5092       for (i = 0; i < m; i++) idx[i] = -1;
5093     }
5094   } else {
5095     MatCheckPreallocated(mat, 1);
5096     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5097     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5098   }
5099   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5100   PetscFunctionReturn(PETSC_SUCCESS);
5101 }
5102 
5103 /*@
5104   MatGetRowMax - Gets the maximum value (of the real part) of each
5105   row of the matrix
5106 
5107   Logically Collective
5108 
5109   Input Parameter:
5110 . mat - the matrix
5111 
5112   Output Parameters:
5113 + v   - the vector for storing the maximums
5114 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5115 
5116   Level: intermediate
5117 
5118   Notes:
5119   The result of this call are the same as if one converted the matrix to dense format
5120   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5121 
5122   This code is only implemented for a couple of matrix formats.
5123 
5124 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5125 @*/
5126 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5127 {
5128   PetscFunctionBegin;
5129   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5130   PetscValidType(mat, 1);
5131   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5132   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5133 
5134   if (!mat->cmap->N) {
5135     PetscCall(VecSet(v, PETSC_MIN_REAL));
5136     if (idx) {
5137       PetscInt i, m = mat->rmap->n;
5138       for (i = 0; i < m; i++) idx[i] = -1;
5139     }
5140   } else {
5141     MatCheckPreallocated(mat, 1);
5142     PetscUseTypeMethod(mat, getrowmax, v, idx);
5143   }
5144   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5145   PetscFunctionReturn(PETSC_SUCCESS);
5146 }
5147 
5148 /*@
5149   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5150   row of the matrix
5151 
5152   Logically Collective
5153 
5154   Input Parameter:
5155 . mat - the matrix
5156 
5157   Output Parameters:
5158 + v   - the vector for storing the maximums
5159 - idx - the indices of the column found for each row (or `NULL` if not needed)
5160 
5161   Level: intermediate
5162 
5163   Notes:
5164   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5165   row is 0 (the first column).
5166 
5167   This code is only implemented for a couple of matrix formats.
5168 
5169 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5170 @*/
5171 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5172 {
5173   PetscFunctionBegin;
5174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5175   PetscValidType(mat, 1);
5176   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5178 
5179   if (!mat->cmap->N) {
5180     PetscCall(VecSet(v, 0.0));
5181     if (idx) {
5182       PetscInt i, m = mat->rmap->n;
5183       for (i = 0; i < m; i++) idx[i] = -1;
5184     }
5185   } else {
5186     MatCheckPreallocated(mat, 1);
5187     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5188     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5189   }
5190   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5191   PetscFunctionReturn(PETSC_SUCCESS);
5192 }
5193 
5194 /*@
5195   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5196 
5197   Logically Collective
5198 
5199   Input Parameter:
5200 . mat - the matrix
5201 
5202   Output Parameter:
5203 . v - the vector for storing the sum
5204 
5205   Level: intermediate
5206 
5207   This code is only implemented for a couple of matrix formats.
5208 
5209 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5210 @*/
5211 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5212 {
5213   PetscFunctionBegin;
5214   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5215   PetscValidType(mat, 1);
5216   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5217   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5218 
5219   if (!mat->cmap->N) {
5220     PetscCall(VecSet(v, 0.0));
5221   } else {
5222     MatCheckPreallocated(mat, 1);
5223     PetscUseTypeMethod(mat, getrowsumabs, v);
5224   }
5225   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5226   PetscFunctionReturn(PETSC_SUCCESS);
5227 }
5228 
5229 /*@
5230   MatGetRowSum - Gets the sum of each row of the matrix
5231 
5232   Logically or Neighborhood Collective
5233 
5234   Input Parameter:
5235 . mat - the matrix
5236 
5237   Output Parameter:
5238 . v - the vector for storing the sum of rows
5239 
5240   Level: intermediate
5241 
5242   Note:
5243   This code is slow since it is not currently specialized for different formats
5244 
5245 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5246 @*/
5247 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5248 {
5249   Vec ones;
5250 
5251   PetscFunctionBegin;
5252   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5253   PetscValidType(mat, 1);
5254   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5255   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5256   MatCheckPreallocated(mat, 1);
5257   PetscCall(MatCreateVecs(mat, &ones, NULL));
5258   PetscCall(VecSet(ones, 1.));
5259   PetscCall(MatMult(mat, ones, v));
5260   PetscCall(VecDestroy(&ones));
5261   PetscFunctionReturn(PETSC_SUCCESS);
5262 }
5263 
5264 /*@
5265   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5266   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5267 
5268   Collective
5269 
5270   Input Parameter:
5271 . mat - the matrix to provide the transpose
5272 
5273   Output Parameter:
5274 . B - 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
5275 
5276   Level: advanced
5277 
5278   Note:
5279   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
5280   routine allows bypassing that call.
5281 
5282 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5283 @*/
5284 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5285 {
5286   PetscContainer  rB = NULL;
5287   MatParentState *rb = NULL;
5288 
5289   PetscFunctionBegin;
5290   PetscCall(PetscNew(&rb));
5291   rb->id    = ((PetscObject)mat)->id;
5292   rb->state = 0;
5293   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5294   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5295   PetscCall(PetscContainerSetPointer(rB, rb));
5296   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5297   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5298   PetscCall(PetscObjectDereference((PetscObject)rB));
5299   PetscFunctionReturn(PETSC_SUCCESS);
5300 }
5301 
5302 /*@
5303   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5304 
5305   Collective
5306 
5307   Input Parameters:
5308 + mat   - the matrix to transpose
5309 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5310 
5311   Output Parameter:
5312 . B - the transpose
5313 
5314   Level: intermediate
5315 
5316   Notes:
5317   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5318 
5319   `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
5320   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5321 
5322   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.
5323 
5324   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5325 
5326   If mat is unchanged from the last call this function returns immediately without recomputing the result
5327 
5328   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5329 
5330 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5331           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5332 @*/
5333 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5334 {
5335   PetscContainer  rB = NULL;
5336   MatParentState *rb = NULL;
5337 
5338   PetscFunctionBegin;
5339   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5340   PetscValidType(mat, 1);
5341   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5342   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5343   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5344   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5345   MatCheckPreallocated(mat, 1);
5346   if (reuse == MAT_REUSE_MATRIX) {
5347     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5348     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5349     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5350     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5351     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5352   }
5353 
5354   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5355   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5356     PetscUseTypeMethod(mat, transpose, reuse, B);
5357     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5358   }
5359   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5360 
5361   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5362   if (reuse != MAT_INPLACE_MATRIX) {
5363     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5364     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5365     rb->state        = ((PetscObject)mat)->state;
5366     rb->nonzerostate = mat->nonzerostate;
5367   }
5368   PetscFunctionReturn(PETSC_SUCCESS);
5369 }
5370 
5371 /*@
5372   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5373 
5374   Collective
5375 
5376   Input Parameter:
5377 . A - the matrix to transpose
5378 
5379   Output Parameter:
5380 . 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
5381       numerical portion.
5382 
5383   Level: intermediate
5384 
5385   Note:
5386   This is not supported for many matrix types, use `MatTranspose()` in those cases
5387 
5388 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5389 @*/
5390 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5391 {
5392   PetscFunctionBegin;
5393   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5394   PetscValidType(A, 1);
5395   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5396   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5397   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5398   PetscUseTypeMethod(A, transposesymbolic, B);
5399   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5400 
5401   PetscCall(MatTransposeSetPrecursor(A, *B));
5402   PetscFunctionReturn(PETSC_SUCCESS);
5403 }
5404 
5405 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5406 {
5407   PetscContainer  rB;
5408   MatParentState *rb;
5409 
5410   PetscFunctionBegin;
5411   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5412   PetscValidType(A, 1);
5413   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5414   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5415   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5416   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5417   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5418   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5419   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5420   PetscFunctionReturn(PETSC_SUCCESS);
5421 }
5422 
5423 /*@
5424   MatIsTranspose - Test whether a matrix is another one's transpose,
5425   or its own, in which case it tests symmetry.
5426 
5427   Collective
5428 
5429   Input Parameters:
5430 + A   - the matrix to test
5431 . B   - the matrix to test against, this can equal the first parameter
5432 - tol - tolerance, differences between entries smaller than this are counted as zero
5433 
5434   Output Parameter:
5435 . flg - the result
5436 
5437   Level: intermediate
5438 
5439   Notes:
5440   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5441   test involves parallel copies of the block off-diagonal parts of the matrix.
5442 
5443 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5444 @*/
5445 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5446 {
5447   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5448 
5449   PetscFunctionBegin;
5450   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5451   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5452   PetscAssertPointer(flg, 4);
5453   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5454   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5455   *flg = PETSC_FALSE;
5456   if (f && g) {
5457     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5458     PetscCall((*f)(A, B, tol, flg));
5459   } else {
5460     MatType mattype;
5461 
5462     PetscCall(MatGetType(f ? B : A, &mattype));
5463     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5464   }
5465   PetscFunctionReturn(PETSC_SUCCESS);
5466 }
5467 
5468 /*@
5469   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5470 
5471   Collective
5472 
5473   Input Parameters:
5474 + mat   - the matrix to transpose and complex conjugate
5475 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5476 
5477   Output Parameter:
5478 . B - the Hermitian transpose
5479 
5480   Level: intermediate
5481 
5482 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5483 @*/
5484 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5485 {
5486   PetscFunctionBegin;
5487   PetscCall(MatTranspose(mat, reuse, B));
5488 #if defined(PETSC_USE_COMPLEX)
5489   PetscCall(MatConjugate(*B));
5490 #endif
5491   PetscFunctionReturn(PETSC_SUCCESS);
5492 }
5493 
5494 /*@
5495   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5496 
5497   Collective
5498 
5499   Input Parameters:
5500 + A   - the matrix to test
5501 . B   - the matrix to test against, this can equal the first parameter
5502 - tol - tolerance, differences between entries smaller than this are counted as zero
5503 
5504   Output Parameter:
5505 . flg - the result
5506 
5507   Level: intermediate
5508 
5509   Notes:
5510   Only available for `MATAIJ` matrices.
5511 
5512   The sequential algorithm
5513   has a running time of the order of the number of nonzeros; the parallel
5514   test involves parallel copies of the block off-diagonal parts of the matrix.
5515 
5516 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5517 @*/
5518 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5519 {
5520   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5521 
5522   PetscFunctionBegin;
5523   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5524   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5525   PetscAssertPointer(flg, 4);
5526   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5527   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5528   if (f && g) {
5529     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5530     PetscCall((*f)(A, B, tol, flg));
5531   }
5532   PetscFunctionReturn(PETSC_SUCCESS);
5533 }
5534 
5535 /*@
5536   MatPermute - Creates a new matrix with rows and columns permuted from the
5537   original.
5538 
5539   Collective
5540 
5541   Input Parameters:
5542 + mat - the matrix to permute
5543 . row - row permutation, each processor supplies only the permutation for its rows
5544 - col - column permutation, each processor supplies only the permutation for its columns
5545 
5546   Output Parameter:
5547 . B - the permuted matrix
5548 
5549   Level: advanced
5550 
5551   Note:
5552   The index sets map from row/col of permuted matrix to row/col of original matrix.
5553   The index sets should be on the same communicator as mat and have the same local sizes.
5554 
5555   Developer Note:
5556   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5557   exploit the fact that row and col are permutations, consider implementing the
5558   more general `MatCreateSubMatrix()` instead.
5559 
5560 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5561 @*/
5562 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5563 {
5564   PetscFunctionBegin;
5565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5566   PetscValidType(mat, 1);
5567   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5568   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5569   PetscAssertPointer(B, 4);
5570   PetscCheckSameComm(mat, 1, row, 2);
5571   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5572   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5573   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5574   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5575   MatCheckPreallocated(mat, 1);
5576 
5577   if (mat->ops->permute) {
5578     PetscUseTypeMethod(mat, permute, row, col, B);
5579     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5580   } else {
5581     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5582   }
5583   PetscFunctionReturn(PETSC_SUCCESS);
5584 }
5585 
5586 /*@
5587   MatEqual - Compares two matrices.
5588 
5589   Collective
5590 
5591   Input Parameters:
5592 + A - the first matrix
5593 - B - the second matrix
5594 
5595   Output Parameter:
5596 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5597 
5598   Level: intermediate
5599 
5600 .seealso: [](ch_matrices), `Mat`
5601 @*/
5602 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5603 {
5604   PetscFunctionBegin;
5605   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5606   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5607   PetscValidType(A, 1);
5608   PetscValidType(B, 2);
5609   PetscAssertPointer(flg, 3);
5610   PetscCheckSameComm(A, 1, B, 2);
5611   MatCheckPreallocated(A, 1);
5612   MatCheckPreallocated(B, 2);
5613   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5614   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5615   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,
5616              B->cmap->N);
5617   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5618     PetscUseTypeMethod(A, equal, B, flg);
5619   } else {
5620     PetscCall(MatMultEqual(A, B, 10, flg));
5621   }
5622   PetscFunctionReturn(PETSC_SUCCESS);
5623 }
5624 
5625 /*@
5626   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5627   matrices that are stored as vectors.  Either of the two scaling
5628   matrices can be `NULL`.
5629 
5630   Collective
5631 
5632   Input Parameters:
5633 + mat - the matrix to be scaled
5634 . l   - the left scaling vector (or `NULL`)
5635 - r   - the right scaling vector (or `NULL`)
5636 
5637   Level: intermediate
5638 
5639   Note:
5640   `MatDiagonalScale()` computes $A = LAR$, where
5641   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5642   The L scales the rows of the matrix, the R scales the columns of the matrix.
5643 
5644 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5645 @*/
5646 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5647 {
5648   PetscFunctionBegin;
5649   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5650   PetscValidType(mat, 1);
5651   if (l) {
5652     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5653     PetscCheckSameComm(mat, 1, l, 2);
5654   }
5655   if (r) {
5656     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5657     PetscCheckSameComm(mat, 1, r, 3);
5658   }
5659   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5660   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5661   MatCheckPreallocated(mat, 1);
5662   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5663 
5664   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5665   PetscUseTypeMethod(mat, diagonalscale, l, r);
5666   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5667   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5668   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5669   PetscFunctionReturn(PETSC_SUCCESS);
5670 }
5671 
5672 /*@
5673   MatScale - Scales all elements of a matrix by a given number.
5674 
5675   Logically Collective
5676 
5677   Input Parameters:
5678 + mat - the matrix to be scaled
5679 - a   - the scaling value
5680 
5681   Level: intermediate
5682 
5683 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5684 @*/
5685 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5686 {
5687   PetscFunctionBegin;
5688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5689   PetscValidType(mat, 1);
5690   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5691   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5692   PetscValidLogicalCollectiveScalar(mat, a, 2);
5693   MatCheckPreallocated(mat, 1);
5694 
5695   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5696   if (a != (PetscScalar)1.0) {
5697     PetscUseTypeMethod(mat, scale, a);
5698     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5699   }
5700   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5701   PetscFunctionReturn(PETSC_SUCCESS);
5702 }
5703 
5704 /*@
5705   MatNorm - Calculates various norms of a matrix.
5706 
5707   Collective
5708 
5709   Input Parameters:
5710 + mat  - the matrix
5711 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5712 
5713   Output Parameter:
5714 . nrm - the resulting norm
5715 
5716   Level: intermediate
5717 
5718 .seealso: [](ch_matrices), `Mat`
5719 @*/
5720 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5721 {
5722   PetscFunctionBegin;
5723   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5724   PetscValidType(mat, 1);
5725   PetscAssertPointer(nrm, 3);
5726 
5727   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5728   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5729   MatCheckPreallocated(mat, 1);
5730 
5731   PetscUseTypeMethod(mat, norm, type, nrm);
5732   PetscFunctionReturn(PETSC_SUCCESS);
5733 }
5734 
5735 /*
5736      This variable is used to prevent counting of MatAssemblyBegin() that
5737    are called from within a MatAssemblyEnd().
5738 */
5739 static PetscInt MatAssemblyEnd_InUse = 0;
5740 /*@
5741   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5742   be called after completing all calls to `MatSetValues()`.
5743 
5744   Collective
5745 
5746   Input Parameters:
5747 + mat  - the matrix
5748 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5749 
5750   Level: beginner
5751 
5752   Notes:
5753   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5754   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5755 
5756   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5757   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5758   using the matrix.
5759 
5760   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5761   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
5762   a global collective operation requiring all processes that share the matrix.
5763 
5764   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5765   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5766   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5767 
5768 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5769 @*/
5770 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5771 {
5772   PetscFunctionBegin;
5773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5774   PetscValidType(mat, 1);
5775   MatCheckPreallocated(mat, 1);
5776   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5777   if (mat->assembled) {
5778     mat->was_assembled = PETSC_TRUE;
5779     mat->assembled     = PETSC_FALSE;
5780   }
5781 
5782   if (!MatAssemblyEnd_InUse) {
5783     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5784     PetscTryTypeMethod(mat, assemblybegin, type);
5785     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5786   } else PetscTryTypeMethod(mat, assemblybegin, type);
5787   PetscFunctionReturn(PETSC_SUCCESS);
5788 }
5789 
5790 /*@
5791   MatAssembled - Indicates if a matrix has been assembled and is ready for
5792   use; for example, in matrix-vector product.
5793 
5794   Not Collective
5795 
5796   Input Parameter:
5797 . mat - the matrix
5798 
5799   Output Parameter:
5800 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5801 
5802   Level: advanced
5803 
5804 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5805 @*/
5806 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5807 {
5808   PetscFunctionBegin;
5809   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5810   PetscAssertPointer(assembled, 2);
5811   *assembled = mat->assembled;
5812   PetscFunctionReturn(PETSC_SUCCESS);
5813 }
5814 
5815 /*@
5816   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5817   be called after `MatAssemblyBegin()`.
5818 
5819   Collective
5820 
5821   Input Parameters:
5822 + mat  - the matrix
5823 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5824 
5825   Options Database Keys:
5826 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5827 . -mat_view ::ascii_info_detail      - Prints more detailed info
5828 . -mat_view                          - Prints matrix in ASCII format
5829 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5830 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5831 . -display <name>                    - Sets display name (default is host)
5832 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5833 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5834 . -viewer_socket_machine <machine>   - Machine to use for socket
5835 . -viewer_socket_port <port>         - Port number to use for socket
5836 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5837 
5838   Level: beginner
5839 
5840 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5841 @*/
5842 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5843 {
5844   static PetscInt inassm = 0;
5845   PetscBool       flg    = PETSC_FALSE;
5846 
5847   PetscFunctionBegin;
5848   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5849   PetscValidType(mat, 1);
5850 
5851   inassm++;
5852   MatAssemblyEnd_InUse++;
5853   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5854     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5855     PetscTryTypeMethod(mat, assemblyend, type);
5856     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5857   } else PetscTryTypeMethod(mat, assemblyend, type);
5858 
5859   /* Flush assembly is not a true assembly */
5860   if (type != MAT_FLUSH_ASSEMBLY) {
5861     if (mat->num_ass) {
5862       if (!mat->symmetry_eternal) {
5863         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5864         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5865       }
5866       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5867       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5868     }
5869     mat->num_ass++;
5870     mat->assembled        = PETSC_TRUE;
5871     mat->ass_nonzerostate = mat->nonzerostate;
5872   }
5873 
5874   mat->insertmode = NOT_SET_VALUES;
5875   MatAssemblyEnd_InUse--;
5876   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5877   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5878     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5879 
5880     if (mat->checksymmetryonassembly) {
5881       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5882       if (flg) {
5883         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5884       } else {
5885         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5886       }
5887     }
5888     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5889   }
5890   inassm--;
5891   PetscFunctionReturn(PETSC_SUCCESS);
5892 }
5893 
5894 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5895 /*@
5896   MatSetOption - Sets a parameter option for a matrix. Some options
5897   may be specific to certain storage formats.  Some options
5898   determine how values will be inserted (or added). Sorted,
5899   row-oriented input will generally assemble the fastest. The default
5900   is row-oriented.
5901 
5902   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5903 
5904   Input Parameters:
5905 + mat - the matrix
5906 . op  - the option, one of those listed below (and possibly others),
5907 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5908 
5909   Options Describing Matrix Structure:
5910 + `MAT_SPD`                         - symmetric positive definite
5911 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5912 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5913 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5914 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5915 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5916 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5917 
5918    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5919    do not need to be computed (usually at a high cost)
5920 
5921    Options For Use with `MatSetValues()`:
5922    Insert a logically dense subblock, which can be
5923 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5924 
5925    These options reflect the data you pass in with `MatSetValues()`; it has
5926    nothing to do with how the data is stored internally in the matrix
5927    data structure.
5928 
5929    When (re)assembling a matrix, we can restrict the input for
5930    efficiency/debugging purposes.  These options include
5931 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5932 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5933 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5934 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5935 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5936 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5937         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5938         performance for very large process counts.
5939 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5940         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5941         functions, instead sending only neighbor messages.
5942 
5943   Level: intermediate
5944 
5945   Notes:
5946   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5947 
5948   Some options are relevant only for particular matrix types and
5949   are thus ignored by others.  Other options are not supported by
5950   certain matrix types and will generate an error message if set.
5951 
5952   If using Fortran to compute a matrix, one may need to
5953   use the column-oriented option (or convert to the row-oriented
5954   format).
5955 
5956   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5957   that would generate a new entry in the nonzero structure is instead
5958   ignored.  Thus, if memory has not already been allocated for this particular
5959   data, then the insertion is ignored. For dense matrices, in which
5960   the entire array is allocated, no entries are ever ignored.
5961   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5962 
5963   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5964   that would generate a new entry in the nonzero structure instead produces
5965   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
5966 
5967   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5968   that would generate a new entry that has not been preallocated will
5969   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5970   only.) This is a useful flag when debugging matrix memory preallocation.
5971   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5972 
5973   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5974   other processors should be dropped, rather than stashed.
5975   This is useful if you know that the "owning" processor is also
5976   always generating the correct matrix entries, so that PETSc need
5977   not transfer duplicate entries generated on another processor.
5978 
5979   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5980   searches during matrix assembly. When this flag is set, the hash table
5981   is created during the first matrix assembly. This hash table is
5982   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5983   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5984   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5985   supported by `MATMPIBAIJ` format only.
5986 
5987   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5988   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
5989 
5990   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5991   a zero location in the matrix
5992 
5993   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5994 
5995   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5996   zero row routines and thus improves performance for very large process counts.
5997 
5998   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5999   part of the matrix (since they should match the upper triangular part).
6000 
6001   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6002   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6003   with finite difference schemes with non-periodic boundary conditions.
6004 
6005   Developer Note:
6006   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6007   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6008   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6009   not changed.
6010 
6011 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6012 @*/
6013 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6014 {
6015   PetscFunctionBegin;
6016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6017   if (op > 0) {
6018     PetscValidLogicalCollectiveEnum(mat, op, 2);
6019     PetscValidLogicalCollectiveBool(mat, flg, 3);
6020   }
6021 
6022   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);
6023 
6024   switch (op) {
6025   case MAT_FORCE_DIAGONAL_ENTRIES:
6026     mat->force_diagonals = flg;
6027     PetscFunctionReturn(PETSC_SUCCESS);
6028   case MAT_NO_OFF_PROC_ENTRIES:
6029     mat->nooffprocentries = flg;
6030     PetscFunctionReturn(PETSC_SUCCESS);
6031   case MAT_SUBSET_OFF_PROC_ENTRIES:
6032     mat->assembly_subset = flg;
6033     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6034 #if !defined(PETSC_HAVE_MPIUNI)
6035       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6036 #endif
6037       mat->stash.first_assembly_done = PETSC_FALSE;
6038     }
6039     PetscFunctionReturn(PETSC_SUCCESS);
6040   case MAT_NO_OFF_PROC_ZERO_ROWS:
6041     mat->nooffproczerorows = flg;
6042     PetscFunctionReturn(PETSC_SUCCESS);
6043   case MAT_SPD:
6044     if (flg) {
6045       mat->spd                    = PETSC_BOOL3_TRUE;
6046       mat->symmetric              = PETSC_BOOL3_TRUE;
6047       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6048     } else {
6049       mat->spd = PETSC_BOOL3_FALSE;
6050     }
6051     break;
6052   case MAT_SYMMETRIC:
6053     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6054     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6055 #if !defined(PETSC_USE_COMPLEX)
6056     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6057 #endif
6058     break;
6059   case MAT_HERMITIAN:
6060     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6061     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6062 #if !defined(PETSC_USE_COMPLEX)
6063     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6064 #endif
6065     break;
6066   case MAT_STRUCTURALLY_SYMMETRIC:
6067     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6068     break;
6069   case MAT_SYMMETRY_ETERNAL:
6070     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");
6071     mat->symmetry_eternal = flg;
6072     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6073     break;
6074   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6075     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURALLY_SYMMETRIC to true or false");
6076     mat->structural_symmetry_eternal = flg;
6077     break;
6078   case MAT_SPD_ETERNAL:
6079     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");
6080     mat->spd_eternal = flg;
6081     if (flg) {
6082       mat->structural_symmetry_eternal = PETSC_TRUE;
6083       mat->symmetry_eternal            = PETSC_TRUE;
6084     }
6085     break;
6086   case MAT_STRUCTURE_ONLY:
6087     mat->structure_only = flg;
6088     break;
6089   case MAT_SORTED_FULL:
6090     mat->sortedfull = flg;
6091     break;
6092   default:
6093     break;
6094   }
6095   PetscTryTypeMethod(mat, setoption, op, flg);
6096   PetscFunctionReturn(PETSC_SUCCESS);
6097 }
6098 
6099 /*@
6100   MatGetOption - Gets a parameter option that has been set for a matrix.
6101 
6102   Logically Collective
6103 
6104   Input Parameters:
6105 + mat - the matrix
6106 - op  - the option, this only responds to certain options, check the code for which ones
6107 
6108   Output Parameter:
6109 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6110 
6111   Level: intermediate
6112 
6113   Notes:
6114   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6115 
6116   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6117   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6118 
6119 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6120     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6121 @*/
6122 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6123 {
6124   PetscFunctionBegin;
6125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6126   PetscValidType(mat, 1);
6127 
6128   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);
6129   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()");
6130 
6131   switch (op) {
6132   case MAT_NO_OFF_PROC_ENTRIES:
6133     *flg = mat->nooffprocentries;
6134     break;
6135   case MAT_NO_OFF_PROC_ZERO_ROWS:
6136     *flg = mat->nooffproczerorows;
6137     break;
6138   case MAT_SYMMETRIC:
6139     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6140     break;
6141   case MAT_HERMITIAN:
6142     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6143     break;
6144   case MAT_STRUCTURALLY_SYMMETRIC:
6145     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6146     break;
6147   case MAT_SPD:
6148     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6149     break;
6150   case MAT_SYMMETRY_ETERNAL:
6151     *flg = mat->symmetry_eternal;
6152     break;
6153   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6154     *flg = mat->symmetry_eternal;
6155     break;
6156   default:
6157     break;
6158   }
6159   PetscFunctionReturn(PETSC_SUCCESS);
6160 }
6161 
6162 /*@
6163   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6164   this routine retains the old nonzero structure.
6165 
6166   Logically Collective
6167 
6168   Input Parameter:
6169 . mat - the matrix
6170 
6171   Level: intermediate
6172 
6173   Note:
6174   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.
6175   See the Performance chapter of the users manual for information on preallocating matrices.
6176 
6177 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6178 @*/
6179 PetscErrorCode MatZeroEntries(Mat mat)
6180 {
6181   PetscFunctionBegin;
6182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6183   PetscValidType(mat, 1);
6184   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6185   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");
6186   MatCheckPreallocated(mat, 1);
6187 
6188   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6189   PetscUseTypeMethod(mat, zeroentries);
6190   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6191   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6192   PetscFunctionReturn(PETSC_SUCCESS);
6193 }
6194 
6195 /*@
6196   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6197   of a set of rows and columns of a matrix.
6198 
6199   Collective
6200 
6201   Input Parameters:
6202 + mat     - the matrix
6203 . numRows - the number of rows/columns to zero
6204 . rows    - the global row indices
6205 . diag    - value put in the diagonal of the eliminated rows
6206 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6207 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6208 
6209   Level: intermediate
6210 
6211   Notes:
6212   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6213 
6214   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6215   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
6216 
6217   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6218   Krylov method to take advantage of the known solution on the zeroed rows.
6219 
6220   For the parallel case, all processes that share the matrix (i.e.,
6221   those in the communicator used for matrix creation) MUST call this
6222   routine, regardless of whether any rows being zeroed are owned by
6223   them.
6224 
6225   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6226   removes them from the nonzero pattern. The nonzero pattern of the matrix can still change if a nonzero needs to be inserted on a diagonal entry that was previously
6227   missing.
6228 
6229   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6230   list only rows local to itself).
6231 
6232   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6233 
6234 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6235           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6236 @*/
6237 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6238 {
6239   PetscFunctionBegin;
6240   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6241   PetscValidType(mat, 1);
6242   if (numRows) PetscAssertPointer(rows, 3);
6243   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6244   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6245   MatCheckPreallocated(mat, 1);
6246 
6247   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6248   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6249   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6250   PetscFunctionReturn(PETSC_SUCCESS);
6251 }
6252 
6253 /*@
6254   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6255   of a set of rows and columns of a matrix.
6256 
6257   Collective
6258 
6259   Input Parameters:
6260 + mat  - the matrix
6261 . is   - the rows to zero
6262 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6263 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6264 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6265 
6266   Level: intermediate
6267 
6268   Note:
6269   See `MatZeroRowsColumns()` for details on how this routine operates.
6270 
6271 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6272           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6273 @*/
6274 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6275 {
6276   PetscInt        numRows;
6277   const PetscInt *rows;
6278 
6279   PetscFunctionBegin;
6280   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6281   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6282   PetscValidType(mat, 1);
6283   PetscValidType(is, 2);
6284   PetscCall(ISGetLocalSize(is, &numRows));
6285   PetscCall(ISGetIndices(is, &rows));
6286   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6287   PetscCall(ISRestoreIndices(is, &rows));
6288   PetscFunctionReturn(PETSC_SUCCESS);
6289 }
6290 
6291 /*@
6292   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6293   of a set of rows of a matrix.
6294 
6295   Collective
6296 
6297   Input Parameters:
6298 + mat     - the matrix
6299 . numRows - the number of rows to zero
6300 . rows    - the global row indices
6301 . diag    - value put in the diagonal of the zeroed rows
6302 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6303 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6304 
6305   Level: intermediate
6306 
6307   Notes:
6308   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6309 
6310   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6311 
6312   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6313   Krylov method to take advantage of the known solution on the zeroed rows.
6314 
6315   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)
6316   from the matrix.
6317 
6318   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6319   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
6320   formats this does not alter the nonzero structure.
6321 
6322   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6323   of the matrix is not changed the values are
6324   merely zeroed.
6325 
6326   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6327   formats can optionally remove the main diagonal entry from the
6328   nonzero structure as well, by passing 0.0 as the final argument).
6329 
6330   For the parallel case, all processes that share the matrix (i.e.,
6331   those in the communicator used for matrix creation) MUST call this
6332   routine, regardless of whether any rows being zeroed are owned by
6333   them.
6334 
6335   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6336   list only rows local to itself).
6337 
6338   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6339   owns that are to be zeroed. This saves a global synchronization in the implementation.
6340 
6341 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6342           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6343 @*/
6344 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6345 {
6346   PetscFunctionBegin;
6347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6348   PetscValidType(mat, 1);
6349   if (numRows) PetscAssertPointer(rows, 3);
6350   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6351   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6352   MatCheckPreallocated(mat, 1);
6353 
6354   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6355   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6356   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6357   PetscFunctionReturn(PETSC_SUCCESS);
6358 }
6359 
6360 /*@
6361   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6362   of a set of rows of a matrix.
6363 
6364   Collective
6365 
6366   Input Parameters:
6367 + mat  - the matrix
6368 . is   - index set of rows to remove (if `NULL` then no row is removed)
6369 . diag - value put in all diagonals of eliminated rows
6370 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6371 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6372 
6373   Level: intermediate
6374 
6375   Note:
6376   See `MatZeroRows()` for details on how this routine operates.
6377 
6378 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6379           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6380 @*/
6381 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6382 {
6383   PetscInt        numRows = 0;
6384   const PetscInt *rows    = NULL;
6385 
6386   PetscFunctionBegin;
6387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6388   PetscValidType(mat, 1);
6389   if (is) {
6390     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6391     PetscCall(ISGetLocalSize(is, &numRows));
6392     PetscCall(ISGetIndices(is, &rows));
6393   }
6394   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6395   if (is) PetscCall(ISRestoreIndices(is, &rows));
6396   PetscFunctionReturn(PETSC_SUCCESS);
6397 }
6398 
6399 /*@
6400   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6401   of a set of rows of a matrix. These rows must be local to the process.
6402 
6403   Collective
6404 
6405   Input Parameters:
6406 + mat     - the matrix
6407 . numRows - the number of rows to remove
6408 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6409 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6410 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6411 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6412 
6413   Level: intermediate
6414 
6415   Notes:
6416   See `MatZeroRows()` for details on how this routine operates.
6417 
6418   The grid coordinates are across the entire grid, not just the local portion
6419 
6420   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6421   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6422   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6423   `DM_BOUNDARY_PERIODIC` boundary type.
6424 
6425   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
6426   a single value per point) you can skip filling those indices.
6427 
6428   Fortran Note:
6429   `idxm` and `idxn` should be declared as
6430 $     MatStencil idxm(4, m)
6431   and the values inserted using
6432 .vb
6433     idxm(MatStencil_i, 1) = i
6434     idxm(MatStencil_j, 1) = j
6435     idxm(MatStencil_k, 1) = k
6436     idxm(MatStencil_c, 1) = c
6437    etc
6438 .ve
6439 
6440 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6441           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6442 @*/
6443 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6444 {
6445   PetscInt  dim    = mat->stencil.dim;
6446   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6447   PetscInt *dims   = mat->stencil.dims + 1;
6448   PetscInt *starts = mat->stencil.starts;
6449   PetscInt *dxm    = (PetscInt *)rows;
6450   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6451 
6452   PetscFunctionBegin;
6453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6454   PetscValidType(mat, 1);
6455   if (numRows) PetscAssertPointer(rows, 3);
6456 
6457   PetscCall(PetscMalloc1(numRows, &jdxm));
6458   for (i = 0; i < numRows; ++i) {
6459     /* Skip unused dimensions (they are ordered k, j, i, c) */
6460     for (j = 0; j < 3 - sdim; ++j) dxm++;
6461     /* Local index in X dir */
6462     tmp = *dxm++ - starts[0];
6463     /* Loop over remaining dimensions */
6464     for (j = 0; j < dim - 1; ++j) {
6465       /* If nonlocal, set index to be negative */
6466       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6467       /* Update local index */
6468       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6469     }
6470     /* Skip component slot if necessary */
6471     if (mat->stencil.noc) dxm++;
6472     /* Local row number */
6473     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6474   }
6475   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6476   PetscCall(PetscFree(jdxm));
6477   PetscFunctionReturn(PETSC_SUCCESS);
6478 }
6479 
6480 /*@
6481   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6482   of a set of rows and columns of a matrix.
6483 
6484   Collective
6485 
6486   Input Parameters:
6487 + mat     - the matrix
6488 . numRows - the number of rows/columns to remove
6489 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6490 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6491 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6492 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6493 
6494   Level: intermediate
6495 
6496   Notes:
6497   See `MatZeroRowsColumns()` for details on how this routine operates.
6498 
6499   The grid coordinates are across the entire grid, not just the local portion
6500 
6501   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6502   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6503   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6504   `DM_BOUNDARY_PERIODIC` boundary type.
6505 
6506   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
6507   a single value per point) you can skip filling those indices.
6508 
6509   Fortran Note:
6510   `idxm` and `idxn` should be declared as
6511 $     MatStencil idxm(4, m)
6512   and the values inserted using
6513 .vb
6514     idxm(MatStencil_i, 1) = i
6515     idxm(MatStencil_j, 1) = j
6516     idxm(MatStencil_k, 1) = k
6517     idxm(MatStencil_c, 1) = c
6518     etc
6519 .ve
6520 
6521 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6522           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6523 @*/
6524 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6525 {
6526   PetscInt  dim    = mat->stencil.dim;
6527   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6528   PetscInt *dims   = mat->stencil.dims + 1;
6529   PetscInt *starts = mat->stencil.starts;
6530   PetscInt *dxm    = (PetscInt *)rows;
6531   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6532 
6533   PetscFunctionBegin;
6534   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6535   PetscValidType(mat, 1);
6536   if (numRows) PetscAssertPointer(rows, 3);
6537 
6538   PetscCall(PetscMalloc1(numRows, &jdxm));
6539   for (i = 0; i < numRows; ++i) {
6540     /* Skip unused dimensions (they are ordered k, j, i, c) */
6541     for (j = 0; j < 3 - sdim; ++j) dxm++;
6542     /* Local index in X dir */
6543     tmp = *dxm++ - starts[0];
6544     /* Loop over remaining dimensions */
6545     for (j = 0; j < dim - 1; ++j) {
6546       /* If nonlocal, set index to be negative */
6547       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6548       /* Update local index */
6549       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6550     }
6551     /* Skip component slot if necessary */
6552     if (mat->stencil.noc) dxm++;
6553     /* Local row number */
6554     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6555   }
6556   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6557   PetscCall(PetscFree(jdxm));
6558   PetscFunctionReturn(PETSC_SUCCESS);
6559 }
6560 
6561 /*@C
6562   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6563   of a set of rows of a matrix; using local numbering of rows.
6564 
6565   Collective
6566 
6567   Input Parameters:
6568 + mat     - the matrix
6569 . numRows - the number of rows to remove
6570 . rows    - the local row indices
6571 . diag    - value put in all diagonals of eliminated rows
6572 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6573 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6574 
6575   Level: intermediate
6576 
6577   Notes:
6578   Before calling `MatZeroRowsLocal()`, the user must first set the
6579   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6580 
6581   See `MatZeroRows()` for details on how this routine operates.
6582 
6583 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6584           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6585 @*/
6586 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6587 {
6588   PetscFunctionBegin;
6589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6590   PetscValidType(mat, 1);
6591   if (numRows) PetscAssertPointer(rows, 3);
6592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6593   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6594   MatCheckPreallocated(mat, 1);
6595 
6596   if (mat->ops->zerorowslocal) {
6597     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6598   } else {
6599     IS              is, newis;
6600     const PetscInt *newRows;
6601 
6602     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6603     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6604     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6605     PetscCall(ISGetIndices(newis, &newRows));
6606     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6607     PetscCall(ISRestoreIndices(newis, &newRows));
6608     PetscCall(ISDestroy(&newis));
6609     PetscCall(ISDestroy(&is));
6610   }
6611   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6612   PetscFunctionReturn(PETSC_SUCCESS);
6613 }
6614 
6615 /*@
6616   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6617   of a set of rows of a matrix; using local numbering of rows.
6618 
6619   Collective
6620 
6621   Input Parameters:
6622 + mat  - the matrix
6623 . is   - index set of rows to remove
6624 . diag - value put in all diagonals of eliminated rows
6625 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6626 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6627 
6628   Level: intermediate
6629 
6630   Notes:
6631   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6632   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6633 
6634   See `MatZeroRows()` for details on how this routine operates.
6635 
6636 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6637           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6638 @*/
6639 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6640 {
6641   PetscInt        numRows;
6642   const PetscInt *rows;
6643 
6644   PetscFunctionBegin;
6645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6646   PetscValidType(mat, 1);
6647   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6648   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6649   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6650   MatCheckPreallocated(mat, 1);
6651 
6652   PetscCall(ISGetLocalSize(is, &numRows));
6653   PetscCall(ISGetIndices(is, &rows));
6654   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6655   PetscCall(ISRestoreIndices(is, &rows));
6656   PetscFunctionReturn(PETSC_SUCCESS);
6657 }
6658 
6659 /*@
6660   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6661   of a set of rows and columns of a matrix; using local numbering of rows.
6662 
6663   Collective
6664 
6665   Input Parameters:
6666 + mat     - the matrix
6667 . numRows - the number of rows to remove
6668 . rows    - the global row indices
6669 . diag    - value put in all diagonals of eliminated rows
6670 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6671 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6672 
6673   Level: intermediate
6674 
6675   Notes:
6676   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6677   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6678 
6679   See `MatZeroRowsColumns()` for details on how this routine operates.
6680 
6681 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6682           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6683 @*/
6684 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6685 {
6686   IS              is, newis;
6687   const PetscInt *newRows;
6688 
6689   PetscFunctionBegin;
6690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6691   PetscValidType(mat, 1);
6692   if (numRows) PetscAssertPointer(rows, 3);
6693   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6694   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6695   MatCheckPreallocated(mat, 1);
6696 
6697   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6698   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6699   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6700   PetscCall(ISGetIndices(newis, &newRows));
6701   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6702   PetscCall(ISRestoreIndices(newis, &newRows));
6703   PetscCall(ISDestroy(&newis));
6704   PetscCall(ISDestroy(&is));
6705   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6706   PetscFunctionReturn(PETSC_SUCCESS);
6707 }
6708 
6709 /*@
6710   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6711   of a set of rows and columns of a matrix; using local numbering of rows.
6712 
6713   Collective
6714 
6715   Input Parameters:
6716 + mat  - the matrix
6717 . is   - index set of rows to remove
6718 . diag - value put in all diagonals of eliminated rows
6719 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6720 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6721 
6722   Level: intermediate
6723 
6724   Notes:
6725   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6726   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6727 
6728   See `MatZeroRowsColumns()` for details on how this routine operates.
6729 
6730 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6731           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6732 @*/
6733 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6734 {
6735   PetscInt        numRows;
6736   const PetscInt *rows;
6737 
6738   PetscFunctionBegin;
6739   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6740   PetscValidType(mat, 1);
6741   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6742   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6743   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6744   MatCheckPreallocated(mat, 1);
6745 
6746   PetscCall(ISGetLocalSize(is, &numRows));
6747   PetscCall(ISGetIndices(is, &rows));
6748   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6749   PetscCall(ISRestoreIndices(is, &rows));
6750   PetscFunctionReturn(PETSC_SUCCESS);
6751 }
6752 
6753 /*@C
6754   MatGetSize - Returns the numbers of rows and columns in a matrix.
6755 
6756   Not Collective
6757 
6758   Input Parameter:
6759 . mat - the matrix
6760 
6761   Output Parameters:
6762 + m - the number of global rows
6763 - n - the number of global columns
6764 
6765   Level: beginner
6766 
6767   Note:
6768   Both output parameters can be `NULL` on input.
6769 
6770 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6771 @*/
6772 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6773 {
6774   PetscFunctionBegin;
6775   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6776   if (m) *m = mat->rmap->N;
6777   if (n) *n = mat->cmap->N;
6778   PetscFunctionReturn(PETSC_SUCCESS);
6779 }
6780 
6781 /*@C
6782   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6783   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6784 
6785   Not Collective
6786 
6787   Input Parameter:
6788 . mat - the matrix
6789 
6790   Output Parameters:
6791 + m - the number of local rows, use `NULL` to not obtain this value
6792 - n - the number of local columns, use `NULL` to not obtain this value
6793 
6794   Level: beginner
6795 
6796 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6797 @*/
6798 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6799 {
6800   PetscFunctionBegin;
6801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6802   if (m) PetscAssertPointer(m, 2);
6803   if (n) PetscAssertPointer(n, 3);
6804   if (m) *m = mat->rmap->n;
6805   if (n) *n = mat->cmap->n;
6806   PetscFunctionReturn(PETSC_SUCCESS);
6807 }
6808 
6809 /*@
6810   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6811   vector one multiplies this matrix by that are owned by this processor.
6812 
6813   Not Collective, unless matrix has not been allocated, then collective
6814 
6815   Input Parameter:
6816 . mat - the matrix
6817 
6818   Output Parameters:
6819 + m - the global index of the first local column, use `NULL` to not obtain this value
6820 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6821 
6822   Level: developer
6823 
6824   Notes:
6825   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6826 
6827   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6828   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6829 
6830   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6831   the local values in the matrix.
6832 
6833   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6834   Layouts](sec_matlayout) for details on matrix layouts.
6835 
6836 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6837           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6838 @*/
6839 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6840 {
6841   PetscFunctionBegin;
6842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6843   PetscValidType(mat, 1);
6844   if (m) PetscAssertPointer(m, 2);
6845   if (n) PetscAssertPointer(n, 3);
6846   MatCheckPreallocated(mat, 1);
6847   if (m) *m = mat->cmap->rstart;
6848   if (n) *n = mat->cmap->rend;
6849   PetscFunctionReturn(PETSC_SUCCESS);
6850 }
6851 
6852 /*@C
6853   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6854   this MPI process.
6855 
6856   Not Collective
6857 
6858   Input Parameter:
6859 . mat - the matrix
6860 
6861   Output Parameters:
6862 + m - the global index of the first local row, use `NULL` to not obtain this value
6863 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6864 
6865   Level: beginner
6866 
6867   Notes:
6868   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6869 
6870   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6871   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6872 
6873   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6874   the local values in the matrix.
6875 
6876   The high argument is one more than the last element stored locally.
6877 
6878   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6879   would contain the result of a matrix vector product with this matrix. See [Matrix
6880   Layouts](sec_matlayout) for details on matrix layouts.
6881 
6882 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6883           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6884 @*/
6885 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6886 {
6887   PetscFunctionBegin;
6888   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6889   PetscValidType(mat, 1);
6890   if (m) PetscAssertPointer(m, 2);
6891   if (n) PetscAssertPointer(n, 3);
6892   MatCheckPreallocated(mat, 1);
6893   if (m) *m = mat->rmap->rstart;
6894   if (n) *n = mat->rmap->rend;
6895   PetscFunctionReturn(PETSC_SUCCESS);
6896 }
6897 
6898 /*@C
6899   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6900   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6901 
6902   Not Collective, unless matrix has not been allocated
6903 
6904   Input Parameter:
6905 . mat - the matrix
6906 
6907   Output Parameter:
6908 . ranges - start of each processors portion plus one more than the total length at the end
6909 
6910   Level: beginner
6911 
6912   Notes:
6913   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6914 
6915   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6916   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6917 
6918   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6919   the local values in the matrix.
6920 
6921   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6922   would contain the result of a matrix vector product with this matrix. See [Matrix
6923   Layouts](sec_matlayout) for details on matrix layouts.
6924 
6925 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6926           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6927           `DMDAGetGhostCorners()`, `DM`
6928 @*/
6929 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6930 {
6931   PetscFunctionBegin;
6932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6933   PetscValidType(mat, 1);
6934   MatCheckPreallocated(mat, 1);
6935   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6936   PetscFunctionReturn(PETSC_SUCCESS);
6937 }
6938 
6939 /*@C
6940   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6941   vector one multiplies this vector by that are owned by each processor.
6942 
6943   Not Collective, unless matrix has not been allocated
6944 
6945   Input Parameter:
6946 . mat - the matrix
6947 
6948   Output Parameter:
6949 . ranges - start of each processors portion plus one more than the total length at the end
6950 
6951   Level: beginner
6952 
6953   Notes:
6954   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6955 
6956   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6957   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6958 
6959   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6960   the local values in the matrix.
6961 
6962   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6963   Layouts](sec_matlayout) for details on matrix layouts.
6964 
6965 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6966           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6967           `DMDAGetGhostCorners()`, `DM`
6968 @*/
6969 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6970 {
6971   PetscFunctionBegin;
6972   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6973   PetscValidType(mat, 1);
6974   MatCheckPreallocated(mat, 1);
6975   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6976   PetscFunctionReturn(PETSC_SUCCESS);
6977 }
6978 
6979 /*@C
6980   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6981 
6982   Not Collective
6983 
6984   Input Parameter:
6985 . A - matrix
6986 
6987   Output Parameters:
6988 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6989 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6990 
6991   Level: intermediate
6992 
6993   Note:
6994   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6995   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6996   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6997   details on matrix layouts.
6998 
6999 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7000 @*/
7001 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7002 {
7003   PetscErrorCode (*f)(Mat, IS *, IS *);
7004 
7005   PetscFunctionBegin;
7006   MatCheckPreallocated(A, 1);
7007   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7008   if (f) {
7009     PetscCall((*f)(A, rows, cols));
7010   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7011     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7012     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7013   }
7014   PetscFunctionReturn(PETSC_SUCCESS);
7015 }
7016 
7017 /*@C
7018   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7019   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7020   to complete the factorization.
7021 
7022   Collective
7023 
7024   Input Parameters:
7025 + fact - the factorized matrix obtained with `MatGetFactor()`
7026 . mat  - the matrix
7027 . row  - row permutation
7028 . col  - column permutation
7029 - info - structure containing
7030 .vb
7031       levels - number of levels of fill.
7032       expected fill - as ratio of original fill.
7033       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7034                 missing diagonal entries)
7035 .ve
7036 
7037   Level: developer
7038 
7039   Notes:
7040   See [Matrix Factorization](sec_matfactor) for additional information.
7041 
7042   Most users should employ the `KSP` interface for linear solvers
7043   instead of working directly with matrix algebra routines such as this.
7044   See, e.g., `KSPCreate()`.
7045 
7046   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7047 
7048   Developer Note:
7049   The Fortran interface is not autogenerated as the
7050   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7051 
7052 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7053           `MatGetOrdering()`, `MatFactorInfo`
7054 @*/
7055 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7056 {
7057   PetscFunctionBegin;
7058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7059   PetscValidType(mat, 2);
7060   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7061   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7062   PetscAssertPointer(info, 5);
7063   PetscAssertPointer(fact, 1);
7064   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7065   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7066   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7067   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7068   MatCheckPreallocated(mat, 2);
7069 
7070   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7071   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7072   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7073   PetscFunctionReturn(PETSC_SUCCESS);
7074 }
7075 
7076 /*@C
7077   MatICCFactorSymbolic - Performs symbolic incomplete
7078   Cholesky factorization for a symmetric matrix.  Use
7079   `MatCholeskyFactorNumeric()` to complete the factorization.
7080 
7081   Collective
7082 
7083   Input Parameters:
7084 + fact - the factorized matrix obtained with `MatGetFactor()`
7085 . mat  - the matrix to be factored
7086 . perm - row and column permutation
7087 - info - structure containing
7088 .vb
7089       levels - number of levels of fill.
7090       expected fill - as ratio of original fill.
7091 .ve
7092 
7093   Level: developer
7094 
7095   Notes:
7096   Most users should employ the `KSP` interface for linear solvers
7097   instead of working directly with matrix algebra routines such as this.
7098   See, e.g., `KSPCreate()`.
7099 
7100   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7101 
7102   Developer Note:
7103   The Fortran interface is not autogenerated as the
7104   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7105 
7106 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7107 @*/
7108 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7109 {
7110   PetscFunctionBegin;
7111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7112   PetscValidType(mat, 2);
7113   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7114   PetscAssertPointer(info, 4);
7115   PetscAssertPointer(fact, 1);
7116   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7117   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7118   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7119   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7120   MatCheckPreallocated(mat, 2);
7121 
7122   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7123   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7124   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7125   PetscFunctionReturn(PETSC_SUCCESS);
7126 }
7127 
7128 /*@C
7129   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7130   points to an array of valid matrices, they may be reused to store the new
7131   submatrices.
7132 
7133   Collective
7134 
7135   Input Parameters:
7136 + mat   - the matrix
7137 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7138 . irow  - index set of rows to extract
7139 . icol  - index set of columns to extract
7140 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7141 
7142   Output Parameter:
7143 . submat - the array of submatrices
7144 
7145   Level: advanced
7146 
7147   Notes:
7148   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7149   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7150   to extract a parallel submatrix.
7151 
7152   Some matrix types place restrictions on the row and column
7153   indices, such as that they be sorted or that they be equal to each other.
7154 
7155   The index sets may not have duplicate entries.
7156 
7157   When extracting submatrices from a parallel matrix, each processor can
7158   form a different submatrix by setting the rows and columns of its
7159   individual index sets according to the local submatrix desired.
7160 
7161   When finished using the submatrices, the user should destroy
7162   them with `MatDestroySubMatrices()`.
7163 
7164   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7165   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7166 
7167   This routine creates the matrices in submat; you should NOT create them before
7168   calling it. It also allocates the array of matrix pointers submat.
7169 
7170   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7171   request one row/column in a block, they must request all rows/columns that are in
7172   that block. For example, if the block size is 2 you cannot request just row 0 and
7173   column 0.
7174 
7175   Fortran Note:
7176   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7177 
7178 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7179 @*/
7180 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7181 {
7182   PetscInt  i;
7183   PetscBool eq;
7184 
7185   PetscFunctionBegin;
7186   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7187   PetscValidType(mat, 1);
7188   if (n) {
7189     PetscAssertPointer(irow, 3);
7190     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7191     PetscAssertPointer(icol, 4);
7192     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7193   }
7194   PetscAssertPointer(submat, 6);
7195   if (n && scall == MAT_REUSE_MATRIX) {
7196     PetscAssertPointer(*submat, 6);
7197     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7198   }
7199   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7200   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7201   MatCheckPreallocated(mat, 1);
7202   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7203   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7204   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7205   for (i = 0; i < n; i++) {
7206     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7207     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7208     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7209 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7210     if (mat->boundtocpu && mat->bindingpropagates) {
7211       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7212       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7213     }
7214 #endif
7215   }
7216   PetscFunctionReturn(PETSC_SUCCESS);
7217 }
7218 
7219 /*@C
7220   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7221 
7222   Collective
7223 
7224   Input Parameters:
7225 + mat   - the matrix
7226 . n     - the number of submatrixes to be extracted
7227 . irow  - index set of rows to extract
7228 . icol  - index set of columns to extract
7229 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7230 
7231   Output Parameter:
7232 . submat - the array of submatrices
7233 
7234   Level: advanced
7235 
7236   Note:
7237   This is used by `PCGASM`
7238 
7239 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7240 @*/
7241 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7242 {
7243   PetscInt  i;
7244   PetscBool eq;
7245 
7246   PetscFunctionBegin;
7247   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7248   PetscValidType(mat, 1);
7249   if (n) {
7250     PetscAssertPointer(irow, 3);
7251     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7252     PetscAssertPointer(icol, 4);
7253     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7254   }
7255   PetscAssertPointer(submat, 6);
7256   if (n && scall == MAT_REUSE_MATRIX) {
7257     PetscAssertPointer(*submat, 6);
7258     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7259   }
7260   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7261   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7262   MatCheckPreallocated(mat, 1);
7263 
7264   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7265   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7266   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7267   for (i = 0; i < n; i++) {
7268     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7269     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7270   }
7271   PetscFunctionReturn(PETSC_SUCCESS);
7272 }
7273 
7274 /*@C
7275   MatDestroyMatrices - Destroys an array of matrices.
7276 
7277   Collective
7278 
7279   Input Parameters:
7280 + n   - the number of local matrices
7281 - mat - the matrices (this is a pointer to the array of matrices)
7282 
7283   Level: advanced
7284 
7285   Note:
7286   Frees not only the matrices, but also the array that contains the matrices
7287 
7288   Fortran Note:
7289   Does not free the `mat` array.
7290 
7291 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7292 @*/
7293 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7294 {
7295   PetscInt i;
7296 
7297   PetscFunctionBegin;
7298   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7299   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7300   PetscAssertPointer(mat, 2);
7301 
7302   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7303 
7304   /* memory is allocated even if n = 0 */
7305   PetscCall(PetscFree(*mat));
7306   PetscFunctionReturn(PETSC_SUCCESS);
7307 }
7308 
7309 /*@C
7310   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7311 
7312   Collective
7313 
7314   Input Parameters:
7315 + n   - the number of local matrices
7316 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7317                        sequence of `MatCreateSubMatrices()`)
7318 
7319   Level: advanced
7320 
7321   Note:
7322   Frees not only the matrices, but also the array that contains the matrices
7323 
7324   Fortran Note:
7325   Does not free the `mat` array.
7326 
7327 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7328 @*/
7329 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7330 {
7331   Mat mat0;
7332 
7333   PetscFunctionBegin;
7334   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7335   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7336   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7337   PetscAssertPointer(mat, 2);
7338 
7339   mat0 = (*mat)[0];
7340   if (mat0 && mat0->ops->destroysubmatrices) {
7341     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7342   } else {
7343     PetscCall(MatDestroyMatrices(n, mat));
7344   }
7345   PetscFunctionReturn(PETSC_SUCCESS);
7346 }
7347 
7348 /*@
7349   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7350 
7351   Collective
7352 
7353   Input Parameter:
7354 . mat - the matrix
7355 
7356   Output Parameter:
7357 . matstruct - the sequential matrix with the nonzero structure of `mat`
7358 
7359   Level: developer
7360 
7361 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7362 @*/
7363 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7364 {
7365   PetscFunctionBegin;
7366   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7367   PetscAssertPointer(matstruct, 2);
7368 
7369   PetscValidType(mat, 1);
7370   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7371   MatCheckPreallocated(mat, 1);
7372 
7373   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7374   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7375   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7376   PetscFunctionReturn(PETSC_SUCCESS);
7377 }
7378 
7379 /*@C
7380   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7381 
7382   Collective
7383 
7384   Input Parameter:
7385 . mat - the matrix
7386 
7387   Level: advanced
7388 
7389   Note:
7390   This is not needed, one can just call `MatDestroy()`
7391 
7392 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7393 @*/
7394 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7395 {
7396   PetscFunctionBegin;
7397   PetscAssertPointer(mat, 1);
7398   PetscCall(MatDestroy(mat));
7399   PetscFunctionReturn(PETSC_SUCCESS);
7400 }
7401 
7402 /*@
7403   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7404   replaces the index sets by larger ones that represent submatrices with
7405   additional overlap.
7406 
7407   Collective
7408 
7409   Input Parameters:
7410 + mat - the matrix
7411 . n   - the number of index sets
7412 . is  - the array of index sets (these index sets will changed during the call)
7413 - ov  - the additional overlap requested
7414 
7415   Options Database Key:
7416 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7417 
7418   Level: developer
7419 
7420   Note:
7421   The computed overlap preserves the matrix block sizes when the blocks are square.
7422   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7423   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7424 
7425 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7426 @*/
7427 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7428 {
7429   PetscInt i, bs, cbs;
7430 
7431   PetscFunctionBegin;
7432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7433   PetscValidType(mat, 1);
7434   PetscValidLogicalCollectiveInt(mat, n, 2);
7435   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7436   if (n) {
7437     PetscAssertPointer(is, 3);
7438     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7439   }
7440   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7441   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7442   MatCheckPreallocated(mat, 1);
7443 
7444   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7445   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7446   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7447   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7448   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7449   if (bs == cbs) {
7450     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7451   }
7452   PetscFunctionReturn(PETSC_SUCCESS);
7453 }
7454 
7455 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7456 
7457 /*@
7458   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7459   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7460   additional overlap.
7461 
7462   Collective
7463 
7464   Input Parameters:
7465 + mat - the matrix
7466 . n   - the number of index sets
7467 . is  - the array of index sets (these index sets will changed during the call)
7468 - ov  - the additional overlap requested
7469 
7470   `   Options Database Key:
7471 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7472 
7473   Level: developer
7474 
7475 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7476 @*/
7477 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7478 {
7479   PetscInt i;
7480 
7481   PetscFunctionBegin;
7482   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7483   PetscValidType(mat, 1);
7484   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7485   if (n) {
7486     PetscAssertPointer(is, 3);
7487     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7488   }
7489   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7490   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7491   MatCheckPreallocated(mat, 1);
7492   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7493   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7494   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7495   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7496   PetscFunctionReturn(PETSC_SUCCESS);
7497 }
7498 
7499 /*@
7500   MatGetBlockSize - Returns the matrix block size.
7501 
7502   Not Collective
7503 
7504   Input Parameter:
7505 . mat - the matrix
7506 
7507   Output Parameter:
7508 . bs - block size
7509 
7510   Level: intermediate
7511 
7512   Notes:
7513   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7514 
7515   If the block size has not been set yet this routine returns 1.
7516 
7517 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7518 @*/
7519 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7520 {
7521   PetscFunctionBegin;
7522   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7523   PetscAssertPointer(bs, 2);
7524   *bs = PetscAbs(mat->rmap->bs);
7525   PetscFunctionReturn(PETSC_SUCCESS);
7526 }
7527 
7528 /*@
7529   MatGetBlockSizes - Returns the matrix block row and column sizes.
7530 
7531   Not Collective
7532 
7533   Input Parameter:
7534 . mat - the matrix
7535 
7536   Output Parameters:
7537 + rbs - row block size
7538 - cbs - column block size
7539 
7540   Level: intermediate
7541 
7542   Notes:
7543   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7544   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7545 
7546   If a block size has not been set yet this routine returns 1.
7547 
7548 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7549 @*/
7550 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7551 {
7552   PetscFunctionBegin;
7553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7554   if (rbs) PetscAssertPointer(rbs, 2);
7555   if (cbs) PetscAssertPointer(cbs, 3);
7556   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7557   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7558   PetscFunctionReturn(PETSC_SUCCESS);
7559 }
7560 
7561 /*@
7562   MatSetBlockSize - Sets the matrix block size.
7563 
7564   Logically Collective
7565 
7566   Input Parameters:
7567 + mat - the matrix
7568 - bs  - block size
7569 
7570   Level: intermediate
7571 
7572   Notes:
7573   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7574   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7575 
7576   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7577   is compatible with the matrix local sizes.
7578 
7579 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7580 @*/
7581 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7582 {
7583   PetscFunctionBegin;
7584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7585   PetscValidLogicalCollectiveInt(mat, bs, 2);
7586   PetscCall(MatSetBlockSizes(mat, bs, bs));
7587   PetscFunctionReturn(PETSC_SUCCESS);
7588 }
7589 
7590 typedef struct {
7591   PetscInt         n;
7592   IS              *is;
7593   Mat             *mat;
7594   PetscObjectState nonzerostate;
7595   Mat              C;
7596 } EnvelopeData;
7597 
7598 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7599 {
7600   EnvelopeData *edata = (EnvelopeData *)ptr;
7601 
7602   PetscFunctionBegin;
7603   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7604   PetscCall(PetscFree(edata->is));
7605   PetscCall(PetscFree(edata));
7606   PetscFunctionReturn(PETSC_SUCCESS);
7607 }
7608 
7609 /*@
7610   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7611   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7612 
7613   Collective
7614 
7615   Input Parameter:
7616 . mat - the matrix
7617 
7618   Level: intermediate
7619 
7620   Notes:
7621   There can be zeros within the blocks
7622 
7623   The blocks can overlap between processes, including laying on more than two processes
7624 
7625 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7626 @*/
7627 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7628 {
7629   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7630   PetscInt          *diag, *odiag, sc;
7631   VecScatter         scatter;
7632   PetscScalar       *seqv;
7633   const PetscScalar *parv;
7634   const PetscInt    *ia, *ja;
7635   PetscBool          set, flag, done;
7636   Mat                AA = mat, A;
7637   MPI_Comm           comm;
7638   PetscMPIInt        rank, size, tag;
7639   MPI_Status         status;
7640   PetscContainer     container;
7641   EnvelopeData      *edata;
7642   Vec                seq, par;
7643   IS                 isglobal;
7644 
7645   PetscFunctionBegin;
7646   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7647   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7648   if (!set || !flag) {
7649     /* TODO: only needs nonzero structure of transpose */
7650     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7651     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7652   }
7653   PetscCall(MatAIJGetLocalMat(AA, &A));
7654   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7655   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7656 
7657   PetscCall(MatGetLocalSize(mat, &n, NULL));
7658   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7659   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7660   PetscCallMPI(MPI_Comm_size(comm, &size));
7661   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7662 
7663   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7664 
7665   if (rank > 0) {
7666     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7667     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7668   }
7669   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7670   for (i = 0; i < n; i++) {
7671     env = PetscMax(env, ja[ia[i + 1] - 1]);
7672     II  = rstart + i;
7673     if (env == II) {
7674       starts[lblocks]  = tbs;
7675       sizes[lblocks++] = 1 + II - tbs;
7676       tbs              = 1 + II;
7677     }
7678   }
7679   if (rank < size - 1) {
7680     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7681     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7682   }
7683 
7684   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7685   if (!set || !flag) PetscCall(MatDestroy(&AA));
7686   PetscCall(MatDestroy(&A));
7687 
7688   PetscCall(PetscNew(&edata));
7689   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7690   edata->n = lblocks;
7691   /* create IS needed for extracting blocks from the original matrix */
7692   PetscCall(PetscMalloc1(lblocks, &edata->is));
7693   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7694 
7695   /* Create the resulting inverse matrix structure with preallocation information */
7696   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7697   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7698   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7699   PetscCall(MatSetType(edata->C, MATAIJ));
7700 
7701   /* Communicate the start and end of each row, from each block to the correct rank */
7702   /* TODO: Use PetscSF instead of VecScatter */
7703   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7704   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7705   PetscCall(VecGetArrayWrite(seq, &seqv));
7706   for (PetscInt i = 0; i < lblocks; i++) {
7707     for (PetscInt j = 0; j < sizes[i]; j++) {
7708       seqv[cnt]     = starts[i];
7709       seqv[cnt + 1] = starts[i] + sizes[i];
7710       cnt += 2;
7711     }
7712   }
7713   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7714   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7715   sc -= cnt;
7716   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7717   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7718   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7719   PetscCall(ISDestroy(&isglobal));
7720   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7721   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7722   PetscCall(VecScatterDestroy(&scatter));
7723   PetscCall(VecDestroy(&seq));
7724   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7725   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7726   PetscCall(VecGetArrayRead(par, &parv));
7727   cnt = 0;
7728   PetscCall(MatGetSize(mat, NULL, &n));
7729   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7730     PetscInt start, end, d = 0, od = 0;
7731 
7732     start = (PetscInt)PetscRealPart(parv[cnt]);
7733     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7734     cnt += 2;
7735 
7736     if (start < cstart) {
7737       od += cstart - start + n - cend;
7738       d += cend - cstart;
7739     } else if (start < cend) {
7740       od += n - cend;
7741       d += cend - start;
7742     } else od += n - start;
7743     if (end <= cstart) {
7744       od -= cstart - end + n - cend;
7745       d -= cend - cstart;
7746     } else if (end < cend) {
7747       od -= n - cend;
7748       d -= cend - end;
7749     } else od -= n - end;
7750 
7751     odiag[i] = od;
7752     diag[i]  = d;
7753   }
7754   PetscCall(VecRestoreArrayRead(par, &parv));
7755   PetscCall(VecDestroy(&par));
7756   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7757   PetscCall(PetscFree2(diag, odiag));
7758   PetscCall(PetscFree2(sizes, starts));
7759 
7760   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7761   PetscCall(PetscContainerSetPointer(container, edata));
7762   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7763   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7764   PetscCall(PetscObjectDereference((PetscObject)container));
7765   PetscFunctionReturn(PETSC_SUCCESS);
7766 }
7767 
7768 /*@
7769   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7770 
7771   Collective
7772 
7773   Input Parameters:
7774 + A     - the matrix
7775 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7776 
7777   Output Parameter:
7778 . C - matrix with inverted block diagonal of `A`
7779 
7780   Level: advanced
7781 
7782   Note:
7783   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7784 
7785 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7786 @*/
7787 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7788 {
7789   PetscContainer   container;
7790   EnvelopeData    *edata;
7791   PetscObjectState nonzerostate;
7792 
7793   PetscFunctionBegin;
7794   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7795   if (!container) {
7796     PetscCall(MatComputeVariableBlockEnvelope(A));
7797     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7798   }
7799   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7800   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7801   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7802   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7803 
7804   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7805   *C = edata->C;
7806 
7807   for (PetscInt i = 0; i < edata->n; i++) {
7808     Mat          D;
7809     PetscScalar *dvalues;
7810 
7811     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7812     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7813     PetscCall(MatSeqDenseInvert(D));
7814     PetscCall(MatDenseGetArray(D, &dvalues));
7815     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7816     PetscCall(MatDestroy(&D));
7817   }
7818   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7819   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7820   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7821   PetscFunctionReturn(PETSC_SUCCESS);
7822 }
7823 
7824 /*@
7825   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7826 
7827   Not Collective
7828 
7829   Input Parameters:
7830 + mat     - the matrix
7831 . nblocks - the number of blocks on this process, each block can only exist on a single process
7832 - bsizes  - the block sizes
7833 
7834   Level: intermediate
7835 
7836   Notes:
7837   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7838 
7839   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.
7840 
7841 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7842           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7843 @*/
7844 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7845 {
7846   PetscInt ncnt = 0, nlocal;
7847 
7848   PetscFunctionBegin;
7849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7850   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7851   PetscCheck(nblocks >= 0 && nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", nblocks, nlocal);
7852   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7853   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);
7854   PetscCall(PetscFree(mat->bsizes));
7855   mat->nblocks = nblocks;
7856   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7857   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7858   PetscFunctionReturn(PETSC_SUCCESS);
7859 }
7860 
7861 /*@C
7862   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7863 
7864   Not Collective; No Fortran Support
7865 
7866   Input Parameter:
7867 . mat - the matrix
7868 
7869   Output Parameters:
7870 + nblocks - the number of blocks on this process
7871 - bsizes  - the block sizes
7872 
7873   Level: intermediate
7874 
7875 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7876 @*/
7877 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7878 {
7879   PetscFunctionBegin;
7880   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7881   if (nblocks) *nblocks = mat->nblocks;
7882   if (bsizes) *bsizes = mat->bsizes;
7883   PetscFunctionReturn(PETSC_SUCCESS);
7884 }
7885 
7886 /*@
7887   MatSetBlockSizes - Sets the matrix block row and column sizes.
7888 
7889   Logically Collective
7890 
7891   Input Parameters:
7892 + mat - the matrix
7893 . rbs - row block size
7894 - cbs - column block size
7895 
7896   Level: intermediate
7897 
7898   Notes:
7899   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7900   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7901   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7902 
7903   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7904   are compatible with the matrix local sizes.
7905 
7906   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7907 
7908 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7909 @*/
7910 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7911 {
7912   PetscFunctionBegin;
7913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7914   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7915   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7916   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7917   if (mat->rmap->refcnt) {
7918     ISLocalToGlobalMapping l2g  = NULL;
7919     PetscLayout            nmap = NULL;
7920 
7921     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7922     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7923     PetscCall(PetscLayoutDestroy(&mat->rmap));
7924     mat->rmap          = nmap;
7925     mat->rmap->mapping = l2g;
7926   }
7927   if (mat->cmap->refcnt) {
7928     ISLocalToGlobalMapping l2g  = NULL;
7929     PetscLayout            nmap = NULL;
7930 
7931     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7932     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7933     PetscCall(PetscLayoutDestroy(&mat->cmap));
7934     mat->cmap          = nmap;
7935     mat->cmap->mapping = l2g;
7936   }
7937   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7938   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7939   PetscFunctionReturn(PETSC_SUCCESS);
7940 }
7941 
7942 /*@
7943   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7944 
7945   Logically Collective
7946 
7947   Input Parameters:
7948 + mat     - the matrix
7949 . fromRow - matrix from which to copy row block size
7950 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7951 
7952   Level: developer
7953 
7954 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7955 @*/
7956 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7957 {
7958   PetscFunctionBegin;
7959   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7960   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7961   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7962   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7963   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7964   PetscFunctionReturn(PETSC_SUCCESS);
7965 }
7966 
7967 /*@
7968   MatResidual - Default routine to calculate the residual r = b - Ax
7969 
7970   Collective
7971 
7972   Input Parameters:
7973 + mat - the matrix
7974 . b   - the right-hand-side
7975 - x   - the approximate solution
7976 
7977   Output Parameter:
7978 . r - location to store the residual
7979 
7980   Level: developer
7981 
7982 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7983 @*/
7984 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7985 {
7986   PetscFunctionBegin;
7987   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7988   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7989   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7990   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7991   PetscValidType(mat, 1);
7992   MatCheckPreallocated(mat, 1);
7993   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7994   if (!mat->ops->residual) {
7995     PetscCall(MatMult(mat, x, r));
7996     PetscCall(VecAYPX(r, -1.0, b));
7997   } else {
7998     PetscUseTypeMethod(mat, residual, b, x, r);
7999   }
8000   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8001   PetscFunctionReturn(PETSC_SUCCESS);
8002 }
8003 
8004 /*MC
8005     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8006 
8007     Synopsis:
8008     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8009 
8010     Not Collective
8011 
8012     Input Parameters:
8013 +   A - the matrix
8014 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8015 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8016 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8017                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8018                  always used.
8019 
8020     Output Parameters:
8021 +   n - number of local rows in the (possibly compressed) matrix
8022 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8023 .   ja - the column indices
8024 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8025            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8026 
8027     Level: developer
8028 
8029     Note:
8030     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8031 
8032 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8033 M*/
8034 
8035 /*MC
8036     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8037 
8038     Synopsis:
8039     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8040 
8041     Not Collective
8042 
8043     Input Parameters:
8044 +   A - the  matrix
8045 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8046 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8047     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8048                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8049                  always used.
8050 .   n - number of local rows in the (possibly compressed) matrix
8051 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8052 .   ja - the column indices
8053 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8054            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8055 
8056     Level: developer
8057 
8058 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8059 M*/
8060 
8061 /*@C
8062   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8063 
8064   Collective
8065 
8066   Input Parameters:
8067 + mat             - the matrix
8068 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8069 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8070 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8071                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8072                  always used.
8073 
8074   Output Parameters:
8075 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8076 . 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
8077 . ja   - the column indices, use `NULL` if not needed
8078 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8079            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8080 
8081   Level: developer
8082 
8083   Notes:
8084   You CANNOT change any of the ia[] or ja[] values.
8085 
8086   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8087 
8088   Fortran Notes:
8089   Use
8090 .vb
8091     PetscInt, pointer :: ia(:),ja(:)
8092     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8093     ! Access the ith and jth entries via ia(i) and ja(j)
8094 .ve
8095 
8096   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8097 
8098 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8099 @*/
8100 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8101 {
8102   PetscFunctionBegin;
8103   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8104   PetscValidType(mat, 1);
8105   if (n) PetscAssertPointer(n, 5);
8106   if (ia) PetscAssertPointer(ia, 6);
8107   if (ja) PetscAssertPointer(ja, 7);
8108   if (done) PetscAssertPointer(done, 8);
8109   MatCheckPreallocated(mat, 1);
8110   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8111   else {
8112     if (done) *done = PETSC_TRUE;
8113     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8114     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8115     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8116   }
8117   PetscFunctionReturn(PETSC_SUCCESS);
8118 }
8119 
8120 /*@C
8121   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8122 
8123   Collective
8124 
8125   Input Parameters:
8126 + mat             - the matrix
8127 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8128 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8129                 symmetrized
8130 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8131                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8132                  always used.
8133 . n               - number of columns in the (possibly compressed) matrix
8134 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8135 - ja              - the row indices
8136 
8137   Output Parameter:
8138 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8139 
8140   Level: developer
8141 
8142 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8143 @*/
8144 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8145 {
8146   PetscFunctionBegin;
8147   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8148   PetscValidType(mat, 1);
8149   PetscAssertPointer(n, 5);
8150   if (ia) PetscAssertPointer(ia, 6);
8151   if (ja) PetscAssertPointer(ja, 7);
8152   PetscAssertPointer(done, 8);
8153   MatCheckPreallocated(mat, 1);
8154   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8155   else {
8156     *done = PETSC_TRUE;
8157     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8158   }
8159   PetscFunctionReturn(PETSC_SUCCESS);
8160 }
8161 
8162 /*@C
8163   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8164 
8165   Collective
8166 
8167   Input Parameters:
8168 + mat             - the matrix
8169 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8170 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8171 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8172                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8173                  always used.
8174 . n               - size of (possibly compressed) matrix
8175 . ia              - the row pointers
8176 - ja              - the column indices
8177 
8178   Output Parameter:
8179 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8180 
8181   Level: developer
8182 
8183   Note:
8184   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8185   us of the array after it has been restored. If you pass `NULL`, it will
8186   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8187 
8188   Fortran Note:
8189   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8190 
8191 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8192 @*/
8193 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8194 {
8195   PetscFunctionBegin;
8196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8197   PetscValidType(mat, 1);
8198   if (ia) PetscAssertPointer(ia, 6);
8199   if (ja) PetscAssertPointer(ja, 7);
8200   if (done) PetscAssertPointer(done, 8);
8201   MatCheckPreallocated(mat, 1);
8202 
8203   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8204   else {
8205     if (done) *done = PETSC_TRUE;
8206     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8207     if (n) *n = 0;
8208     if (ia) *ia = NULL;
8209     if (ja) *ja = NULL;
8210   }
8211   PetscFunctionReturn(PETSC_SUCCESS);
8212 }
8213 
8214 /*@C
8215   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8216 
8217   Collective
8218 
8219   Input Parameters:
8220 + mat             - the matrix
8221 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8222 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8223 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8224                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8225                  always used.
8226 
8227   Output Parameters:
8228 + n    - size of (possibly compressed) matrix
8229 . ia   - the column pointers
8230 . ja   - the row indices
8231 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8232 
8233   Level: developer
8234 
8235 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8236 @*/
8237 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8238 {
8239   PetscFunctionBegin;
8240   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8241   PetscValidType(mat, 1);
8242   if (ia) PetscAssertPointer(ia, 6);
8243   if (ja) PetscAssertPointer(ja, 7);
8244   PetscAssertPointer(done, 8);
8245   MatCheckPreallocated(mat, 1);
8246 
8247   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8248   else {
8249     *done = PETSC_TRUE;
8250     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8251     if (n) *n = 0;
8252     if (ia) *ia = NULL;
8253     if (ja) *ja = NULL;
8254   }
8255   PetscFunctionReturn(PETSC_SUCCESS);
8256 }
8257 
8258 /*@
8259   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8260   `MatGetColumnIJ()`.
8261 
8262   Collective
8263 
8264   Input Parameters:
8265 + mat        - the matrix
8266 . ncolors    - maximum color value
8267 . n          - number of entries in colorarray
8268 - colorarray - array indicating color for each column
8269 
8270   Output Parameter:
8271 . iscoloring - coloring generated using colorarray information
8272 
8273   Level: developer
8274 
8275 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8276 @*/
8277 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8278 {
8279   PetscFunctionBegin;
8280   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8281   PetscValidType(mat, 1);
8282   PetscAssertPointer(colorarray, 4);
8283   PetscAssertPointer(iscoloring, 5);
8284   MatCheckPreallocated(mat, 1);
8285 
8286   if (!mat->ops->coloringpatch) {
8287     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8288   } else {
8289     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8290   }
8291   PetscFunctionReturn(PETSC_SUCCESS);
8292 }
8293 
8294 /*@
8295   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8296 
8297   Logically Collective
8298 
8299   Input Parameter:
8300 . mat - the factored matrix to be reset
8301 
8302   Level: developer
8303 
8304   Notes:
8305   This routine should be used only with factored matrices formed by in-place
8306   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8307   format).  This option can save memory, for example, when solving nonlinear
8308   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8309   ILU(0) preconditioner.
8310 
8311   One can specify in-place ILU(0) factorization by calling
8312 .vb
8313      PCType(pc,PCILU);
8314      PCFactorSeUseInPlace(pc);
8315 .ve
8316   or by using the options -pc_type ilu -pc_factor_in_place
8317 
8318   In-place factorization ILU(0) can also be used as a local
8319   solver for the blocks within the block Jacobi or additive Schwarz
8320   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8321   for details on setting local solver options.
8322 
8323   Most users should employ the `KSP` interface for linear solvers
8324   instead of working directly with matrix algebra routines such as this.
8325   See, e.g., `KSPCreate()`.
8326 
8327 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8328 @*/
8329 PetscErrorCode MatSetUnfactored(Mat mat)
8330 {
8331   PetscFunctionBegin;
8332   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8333   PetscValidType(mat, 1);
8334   MatCheckPreallocated(mat, 1);
8335   mat->factortype = MAT_FACTOR_NONE;
8336   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8337   PetscUseTypeMethod(mat, setunfactored);
8338   PetscFunctionReturn(PETSC_SUCCESS);
8339 }
8340 
8341 /*MC
8342     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8343 
8344     Synopsis:
8345     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8346 
8347     Not Collective
8348 
8349     Input Parameter:
8350 .   x - matrix
8351 
8352     Output Parameters:
8353 +   xx_v - the Fortran pointer to the array
8354 -   ierr - error code
8355 
8356     Example of Usage:
8357 .vb
8358       PetscScalar, pointer xx_v(:,:)
8359       ....
8360       call MatDenseGetArrayF90(x,xx_v,ierr)
8361       a = xx_v(3)
8362       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8363 .ve
8364 
8365     Level: advanced
8366 
8367 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8368 M*/
8369 
8370 /*MC
8371     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8372     accessed with `MatDenseGetArrayF90()`.
8373 
8374     Synopsis:
8375     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8376 
8377     Not Collective
8378 
8379     Input Parameters:
8380 +   x - matrix
8381 -   xx_v - the Fortran90 pointer to the array
8382 
8383     Output Parameter:
8384 .   ierr - error code
8385 
8386     Example of Usage:
8387 .vb
8388        PetscScalar, pointer xx_v(:,:)
8389        ....
8390        call MatDenseGetArrayF90(x,xx_v,ierr)
8391        a = xx_v(3)
8392        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8393 .ve
8394 
8395     Level: advanced
8396 
8397 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8398 M*/
8399 
8400 /*MC
8401     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8402 
8403     Synopsis:
8404     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8405 
8406     Not Collective
8407 
8408     Input Parameter:
8409 .   x - matrix
8410 
8411     Output Parameters:
8412 +   xx_v - the Fortran pointer to the array
8413 -   ierr - error code
8414 
8415     Example of Usage:
8416 .vb
8417       PetscScalar, pointer xx_v(:)
8418       ....
8419       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8420       a = xx_v(3)
8421       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8422 .ve
8423 
8424     Level: advanced
8425 
8426 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8427 M*/
8428 
8429 /*MC
8430     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8431     accessed with `MatSeqAIJGetArrayF90()`.
8432 
8433     Synopsis:
8434     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8435 
8436     Not Collective
8437 
8438     Input Parameters:
8439 +   x - matrix
8440 -   xx_v - the Fortran90 pointer to the array
8441 
8442     Output Parameter:
8443 .   ierr - error code
8444 
8445     Example of Usage:
8446 .vb
8447        PetscScalar, pointer xx_v(:)
8448        ....
8449        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8450        a = xx_v(3)
8451        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8452 .ve
8453 
8454     Level: advanced
8455 
8456 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8457 M*/
8458 
8459 /*@
8460   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8461   as the original matrix.
8462 
8463   Collective
8464 
8465   Input Parameters:
8466 + mat   - the original matrix
8467 . isrow - parallel `IS` containing the rows this processor should obtain
8468 . 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.
8469 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8470 
8471   Output Parameter:
8472 . newmat - the new submatrix, of the same type as the original matrix
8473 
8474   Level: advanced
8475 
8476   Notes:
8477   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8478 
8479   Some matrix types place restrictions on the row and column indices, such
8480   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;
8481   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8482 
8483   The index sets may not have duplicate entries.
8484 
8485   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8486   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8487   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8488   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8489   you are finished using it.
8490 
8491   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8492   the input matrix.
8493 
8494   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8495 
8496   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8497   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8498 
8499   Example usage:
8500   Consider the following 8x8 matrix with 34 non-zero values, that is
8501   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8502   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8503   as follows
8504 .vb
8505             1  2  0  |  0  3  0  |  0  4
8506     Proc0   0  5  6  |  7  0  0  |  8  0
8507             9  0 10  | 11  0  0  | 12  0
8508     -------------------------------------
8509            13  0 14  | 15 16 17  |  0  0
8510     Proc1   0 18  0  | 19 20 21  |  0  0
8511             0  0  0  | 22 23  0  | 24  0
8512     -------------------------------------
8513     Proc2  25 26 27  |  0  0 28  | 29  0
8514            30  0  0  | 31 32 33  |  0 34
8515 .ve
8516 
8517   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8518 
8519 .vb
8520             2  0  |  0  3  0  |  0
8521     Proc0   5  6  |  7  0  0  |  8
8522     -------------------------------
8523     Proc1  18  0  | 19 20 21  |  0
8524     -------------------------------
8525     Proc2  26 27  |  0  0 28  | 29
8526             0  0  | 31 32 33  |  0
8527 .ve
8528 
8529 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8530 @*/
8531 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8532 {
8533   PetscMPIInt size;
8534   Mat        *local;
8535   IS          iscoltmp;
8536   PetscBool   flg;
8537 
8538   PetscFunctionBegin;
8539   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8540   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8541   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8542   PetscAssertPointer(newmat, 5);
8543   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8544   PetscValidType(mat, 1);
8545   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8546   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8547 
8548   MatCheckPreallocated(mat, 1);
8549   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8550 
8551   if (!iscol || isrow == iscol) {
8552     PetscBool   stride;
8553     PetscMPIInt grabentirematrix = 0, grab;
8554     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8555     if (stride) {
8556       PetscInt first, step, n, rstart, rend;
8557       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8558       if (step == 1) {
8559         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8560         if (rstart == first) {
8561           PetscCall(ISGetLocalSize(isrow, &n));
8562           if (n == rend - rstart) grabentirematrix = 1;
8563         }
8564       }
8565     }
8566     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8567     if (grab) {
8568       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8569       if (cll == MAT_INITIAL_MATRIX) {
8570         *newmat = mat;
8571         PetscCall(PetscObjectReference((PetscObject)mat));
8572       }
8573       PetscFunctionReturn(PETSC_SUCCESS);
8574     }
8575   }
8576 
8577   if (!iscol) {
8578     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8579   } else {
8580     iscoltmp = iscol;
8581   }
8582 
8583   /* if original matrix is on just one processor then use submatrix generated */
8584   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8585     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8586     goto setproperties;
8587   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8588     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8589     *newmat = *local;
8590     PetscCall(PetscFree(local));
8591     goto setproperties;
8592   } else if (!mat->ops->createsubmatrix) {
8593     /* Create a new matrix type that implements the operation using the full matrix */
8594     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8595     switch (cll) {
8596     case MAT_INITIAL_MATRIX:
8597       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8598       break;
8599     case MAT_REUSE_MATRIX:
8600       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8601       break;
8602     default:
8603       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8604     }
8605     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8606     goto setproperties;
8607   }
8608 
8609   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8610   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8611   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8612 
8613 setproperties:
8614   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8615   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8616   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8617   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8618   PetscFunctionReturn(PETSC_SUCCESS);
8619 }
8620 
8621 /*@
8622   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8623 
8624   Not Collective
8625 
8626   Input Parameters:
8627 + A - the matrix we wish to propagate options from
8628 - B - the matrix we wish to propagate options to
8629 
8630   Level: beginner
8631 
8632   Note:
8633   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8634 
8635 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8636 @*/
8637 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8638 {
8639   PetscFunctionBegin;
8640   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8641   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8642   B->symmetry_eternal            = A->symmetry_eternal;
8643   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8644   B->symmetric                   = A->symmetric;
8645   B->structurally_symmetric      = A->structurally_symmetric;
8646   B->spd                         = A->spd;
8647   B->hermitian                   = A->hermitian;
8648   PetscFunctionReturn(PETSC_SUCCESS);
8649 }
8650 
8651 /*@
8652   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8653   used during the assembly process to store values that belong to
8654   other processors.
8655 
8656   Not Collective
8657 
8658   Input Parameters:
8659 + mat   - the matrix
8660 . size  - the initial size of the stash.
8661 - bsize - the initial size of the block-stash(if used).
8662 
8663   Options Database Keys:
8664 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8665 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8666 
8667   Level: intermediate
8668 
8669   Notes:
8670   The block-stash is used for values set with `MatSetValuesBlocked()` while
8671   the stash is used for values set with `MatSetValues()`
8672 
8673   Run with the option -info and look for output of the form
8674   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8675   to determine the appropriate value, MM, to use for size and
8676   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8677   to determine the value, BMM to use for bsize
8678 
8679 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8680 @*/
8681 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8682 {
8683   PetscFunctionBegin;
8684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8685   PetscValidType(mat, 1);
8686   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8687   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8688   PetscFunctionReturn(PETSC_SUCCESS);
8689 }
8690 
8691 /*@
8692   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8693   the matrix
8694 
8695   Neighbor-wise Collective
8696 
8697   Input Parameters:
8698 + A - the matrix
8699 . x - the vector to be multiplied by the interpolation operator
8700 - y - the vector to be added to the result
8701 
8702   Output Parameter:
8703 . w - the resulting vector
8704 
8705   Level: intermediate
8706 
8707   Notes:
8708   `w` may be the same vector as `y`.
8709 
8710   This allows one to use either the restriction or interpolation (its transpose)
8711   matrix to do the interpolation
8712 
8713 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8714 @*/
8715 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8716 {
8717   PetscInt M, N, Ny;
8718 
8719   PetscFunctionBegin;
8720   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8721   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8722   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8723   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8724   PetscCall(MatGetSize(A, &M, &N));
8725   PetscCall(VecGetSize(y, &Ny));
8726   if (M == Ny) {
8727     PetscCall(MatMultAdd(A, x, y, w));
8728   } else {
8729     PetscCall(MatMultTransposeAdd(A, x, y, w));
8730   }
8731   PetscFunctionReturn(PETSC_SUCCESS);
8732 }
8733 
8734 /*@
8735   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8736   the matrix
8737 
8738   Neighbor-wise Collective
8739 
8740   Input Parameters:
8741 + A - the matrix
8742 - x - the vector to be interpolated
8743 
8744   Output Parameter:
8745 . y - the resulting vector
8746 
8747   Level: intermediate
8748 
8749   Note:
8750   This allows one to use either the restriction or interpolation (its transpose)
8751   matrix to do the interpolation
8752 
8753 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8754 @*/
8755 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8756 {
8757   PetscInt M, N, Ny;
8758 
8759   PetscFunctionBegin;
8760   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8761   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8762   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8763   PetscCall(MatGetSize(A, &M, &N));
8764   PetscCall(VecGetSize(y, &Ny));
8765   if (M == Ny) {
8766     PetscCall(MatMult(A, x, y));
8767   } else {
8768     PetscCall(MatMultTranspose(A, x, y));
8769   }
8770   PetscFunctionReturn(PETSC_SUCCESS);
8771 }
8772 
8773 /*@
8774   MatRestrict - $y = A*x$ or $A^T*x$
8775 
8776   Neighbor-wise Collective
8777 
8778   Input Parameters:
8779 + A - the matrix
8780 - x - the vector to be restricted
8781 
8782   Output Parameter:
8783 . y - the resulting vector
8784 
8785   Level: intermediate
8786 
8787   Note:
8788   This allows one to use either the restriction or interpolation (its transpose)
8789   matrix to do the restriction
8790 
8791 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8792 @*/
8793 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8794 {
8795   PetscInt M, N, Nx;
8796 
8797   PetscFunctionBegin;
8798   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8799   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8800   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8801   PetscCall(MatGetSize(A, &M, &N));
8802   PetscCall(VecGetSize(x, &Nx));
8803   if (M == Nx) {
8804     PetscCall(MatMultTranspose(A, x, y));
8805   } else {
8806     PetscCall(MatMult(A, x, y));
8807   }
8808   PetscFunctionReturn(PETSC_SUCCESS);
8809 }
8810 
8811 /*@
8812   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8813 
8814   Neighbor-wise Collective
8815 
8816   Input Parameters:
8817 + A - the matrix
8818 . x - the input dense matrix to be multiplied
8819 - w - the input dense matrix to be added to the result
8820 
8821   Output Parameter:
8822 . y - the output dense matrix
8823 
8824   Level: intermediate
8825 
8826   Note:
8827   This allows one to use either the restriction or interpolation (its transpose)
8828   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8829   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8830 
8831 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8832 @*/
8833 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8834 {
8835   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8836   PetscBool trans = PETSC_TRUE;
8837   MatReuse  reuse = MAT_INITIAL_MATRIX;
8838 
8839   PetscFunctionBegin;
8840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8841   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8842   PetscValidType(x, 2);
8843   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8844   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8845   PetscCall(MatGetSize(A, &M, &N));
8846   PetscCall(MatGetSize(x, &Mx, &Nx));
8847   if (N == Mx) trans = PETSC_FALSE;
8848   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);
8849   Mo = trans ? N : M;
8850   if (*y) {
8851     PetscCall(MatGetSize(*y, &My, &Ny));
8852     if (Mo == My && Nx == Ny) {
8853       reuse = MAT_REUSE_MATRIX;
8854     } else {
8855       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);
8856       PetscCall(MatDestroy(y));
8857     }
8858   }
8859 
8860   if (w && *y == w) { /* this is to minimize changes in PCMG */
8861     PetscBool flg;
8862 
8863     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8864     if (w) {
8865       PetscInt My, Ny, Mw, Nw;
8866 
8867       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8868       PetscCall(MatGetSize(*y, &My, &Ny));
8869       PetscCall(MatGetSize(w, &Mw, &Nw));
8870       if (!flg || My != Mw || Ny != Nw) w = NULL;
8871     }
8872     if (!w) {
8873       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8874       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8875       PetscCall(PetscObjectDereference((PetscObject)w));
8876     } else {
8877       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8878     }
8879   }
8880   if (!trans) {
8881     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8882   } else {
8883     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8884   }
8885   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8886   PetscFunctionReturn(PETSC_SUCCESS);
8887 }
8888 
8889 /*@
8890   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8891 
8892   Neighbor-wise Collective
8893 
8894   Input Parameters:
8895 + A - the matrix
8896 - x - the input dense matrix
8897 
8898   Output Parameter:
8899 . y - the output dense matrix
8900 
8901   Level: intermediate
8902 
8903   Note:
8904   This allows one to use either the restriction or interpolation (its transpose)
8905   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8906   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8907 
8908 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8909 @*/
8910 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8911 {
8912   PetscFunctionBegin;
8913   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8914   PetscFunctionReturn(PETSC_SUCCESS);
8915 }
8916 
8917 /*@
8918   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8919 
8920   Neighbor-wise Collective
8921 
8922   Input Parameters:
8923 + A - the matrix
8924 - x - the input dense matrix
8925 
8926   Output Parameter:
8927 . y - the output dense matrix
8928 
8929   Level: intermediate
8930 
8931   Note:
8932   This allows one to use either the restriction or interpolation (its transpose)
8933   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8934   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8935 
8936 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8937 @*/
8938 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8939 {
8940   PetscFunctionBegin;
8941   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8942   PetscFunctionReturn(PETSC_SUCCESS);
8943 }
8944 
8945 /*@
8946   MatGetNullSpace - retrieves the null space of a matrix.
8947 
8948   Logically Collective
8949 
8950   Input Parameters:
8951 + mat    - the matrix
8952 - nullsp - the null space object
8953 
8954   Level: developer
8955 
8956 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8957 @*/
8958 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8959 {
8960   PetscFunctionBegin;
8961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8962   PetscAssertPointer(nullsp, 2);
8963   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8964   PetscFunctionReturn(PETSC_SUCCESS);
8965 }
8966 
8967 /*@C
8968   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8969 
8970   Logically Collective
8971 
8972   Input Parameters:
8973 + n   - the number of matrices
8974 - mat - the array of matrices
8975 
8976   Output Parameters:
8977 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space
8978 
8979   Level: developer
8980 
8981   Note:
8982   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8983 
8984 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8985           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8986 @*/
8987 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8988 {
8989   PetscFunctionBegin;
8990   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8991   PetscAssertPointer(mat, 2);
8992   PetscAssertPointer(nullsp, 3);
8993 
8994   PetscCall(PetscCalloc1(3 * n, nullsp));
8995   for (PetscInt i = 0; i < n; i++) {
8996     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8997     (*nullsp)[i] = mat[i]->nullsp;
8998     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8999     (*nullsp)[n + i] = mat[i]->nearnullsp;
9000     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9001     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9002     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9003   }
9004   PetscFunctionReturn(PETSC_SUCCESS);
9005 }
9006 
9007 /*@C
9008   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9009 
9010   Logically Collective
9011 
9012   Input Parameters:
9013 + n      - the number of matrices
9014 . mat    - the array of matrices
9015 - nullsp - an array of null spaces, `NULL` if the null space does not exist
9016 
9017   Level: developer
9018 
9019   Note:
9020   Call `MatGetNullSpaces()` to create `nullsp`
9021 
9022 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9023           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9024 @*/
9025 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9026 {
9027   PetscFunctionBegin;
9028   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9029   PetscAssertPointer(mat, 2);
9030   PetscAssertPointer(nullsp, 3);
9031   PetscAssertPointer(*nullsp, 3);
9032 
9033   for (PetscInt i = 0; i < n; i++) {
9034     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9035     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9036     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9037     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9038     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9039     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9040     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9041   }
9042   PetscCall(PetscFree(*nullsp));
9043   PetscFunctionReturn(PETSC_SUCCESS);
9044 }
9045 
9046 /*@
9047   MatSetNullSpace - attaches a null space to a matrix.
9048 
9049   Logically Collective
9050 
9051   Input Parameters:
9052 + mat    - the matrix
9053 - nullsp - the null space object
9054 
9055   Level: advanced
9056 
9057   Notes:
9058   This null space is used by the `KSP` linear solvers to solve singular systems.
9059 
9060   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`
9061 
9062   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
9063   to zero but the linear system will still be solved in a least squares sense.
9064 
9065   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9066   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)$.
9067   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
9068   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
9069   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$).
9070   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9071 
9072   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9073   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9074   routine also automatically calls `MatSetTransposeNullSpace()`.
9075 
9076   The user should call `MatNullSpaceDestroy()`.
9077 
9078 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9079           `KSPSetPCSide()`
9080 @*/
9081 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9082 {
9083   PetscFunctionBegin;
9084   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9085   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9086   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9087   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9088   mat->nullsp = nullsp;
9089   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9090   PetscFunctionReturn(PETSC_SUCCESS);
9091 }
9092 
9093 /*@
9094   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9095 
9096   Logically Collective
9097 
9098   Input Parameters:
9099 + mat    - the matrix
9100 - nullsp - the null space object
9101 
9102   Level: developer
9103 
9104 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9105 @*/
9106 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9107 {
9108   PetscFunctionBegin;
9109   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9110   PetscValidType(mat, 1);
9111   PetscAssertPointer(nullsp, 2);
9112   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9113   PetscFunctionReturn(PETSC_SUCCESS);
9114 }
9115 
9116 /*@
9117   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9118 
9119   Logically Collective
9120 
9121   Input Parameters:
9122 + mat    - the matrix
9123 - nullsp - the null space object
9124 
9125   Level: advanced
9126 
9127   Notes:
9128   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9129 
9130   See `MatSetNullSpace()`
9131 
9132 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9133 @*/
9134 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9135 {
9136   PetscFunctionBegin;
9137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9138   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9139   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9140   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9141   mat->transnullsp = nullsp;
9142   PetscFunctionReturn(PETSC_SUCCESS);
9143 }
9144 
9145 /*@
9146   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9147   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9148 
9149   Logically Collective
9150 
9151   Input Parameters:
9152 + mat    - the matrix
9153 - nullsp - the null space object
9154 
9155   Level: advanced
9156 
9157   Notes:
9158   Overwrites any previous near null space that may have been attached
9159 
9160   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9161 
9162 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9163 @*/
9164 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9165 {
9166   PetscFunctionBegin;
9167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9168   PetscValidType(mat, 1);
9169   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9170   MatCheckPreallocated(mat, 1);
9171   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9172   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9173   mat->nearnullsp = nullsp;
9174   PetscFunctionReturn(PETSC_SUCCESS);
9175 }
9176 
9177 /*@
9178   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9179 
9180   Not Collective
9181 
9182   Input Parameter:
9183 . mat - the matrix
9184 
9185   Output Parameter:
9186 . nullsp - the null space object, `NULL` if not set
9187 
9188   Level: advanced
9189 
9190 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9191 @*/
9192 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9193 {
9194   PetscFunctionBegin;
9195   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9196   PetscValidType(mat, 1);
9197   PetscAssertPointer(nullsp, 2);
9198   MatCheckPreallocated(mat, 1);
9199   *nullsp = mat->nearnullsp;
9200   PetscFunctionReturn(PETSC_SUCCESS);
9201 }
9202 
9203 /*@C
9204   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9205 
9206   Collective
9207 
9208   Input Parameters:
9209 + mat  - the matrix
9210 . row  - row/column permutation
9211 - info - information on desired factorization process
9212 
9213   Level: developer
9214 
9215   Notes:
9216   Probably really in-place only when level of fill is zero, otherwise allocates
9217   new space to store factored matrix and deletes previous memory.
9218 
9219   Most users should employ the `KSP` interface for linear solvers
9220   instead of working directly with matrix algebra routines such as this.
9221   See, e.g., `KSPCreate()`.
9222 
9223   Developer Note:
9224   The Fortran interface is not autogenerated as the
9225   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9226 
9227 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9228 @*/
9229 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9230 {
9231   PetscFunctionBegin;
9232   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9233   PetscValidType(mat, 1);
9234   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9235   PetscAssertPointer(info, 3);
9236   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9237   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9238   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9239   MatCheckPreallocated(mat, 1);
9240   PetscUseTypeMethod(mat, iccfactor, row, info);
9241   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9242   PetscFunctionReturn(PETSC_SUCCESS);
9243 }
9244 
9245 /*@
9246   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9247   ghosted ones.
9248 
9249   Not Collective
9250 
9251   Input Parameters:
9252 + mat  - the matrix
9253 - diag - the diagonal values, including ghost ones
9254 
9255   Level: developer
9256 
9257   Notes:
9258   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9259 
9260   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9261 
9262 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9263 @*/
9264 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9265 {
9266   PetscMPIInt size;
9267 
9268   PetscFunctionBegin;
9269   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9270   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9271   PetscValidType(mat, 1);
9272 
9273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9274   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9275   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9276   if (size == 1) {
9277     PetscInt n, m;
9278     PetscCall(VecGetSize(diag, &n));
9279     PetscCall(MatGetSize(mat, NULL, &m));
9280     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9281     PetscCall(MatDiagonalScale(mat, NULL, diag));
9282   } else {
9283     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9284   }
9285   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9286   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9287   PetscFunctionReturn(PETSC_SUCCESS);
9288 }
9289 
9290 /*@
9291   MatGetInertia - Gets the inertia from a factored matrix
9292 
9293   Collective
9294 
9295   Input Parameter:
9296 . mat - the matrix
9297 
9298   Output Parameters:
9299 + nneg  - number of negative eigenvalues
9300 . nzero - number of zero eigenvalues
9301 - npos  - number of positive eigenvalues
9302 
9303   Level: advanced
9304 
9305   Note:
9306   Matrix must have been factored by `MatCholeskyFactor()`
9307 
9308 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9309 @*/
9310 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9311 {
9312   PetscFunctionBegin;
9313   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9314   PetscValidType(mat, 1);
9315   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9316   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9317   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9318   PetscFunctionReturn(PETSC_SUCCESS);
9319 }
9320 
9321 /*@C
9322   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9323 
9324   Neighbor-wise Collective
9325 
9326   Input Parameters:
9327 + mat - the factored matrix obtained with `MatGetFactor()`
9328 - b   - the right-hand-side vectors
9329 
9330   Output Parameter:
9331 . x - the result vectors
9332 
9333   Level: developer
9334 
9335   Note:
9336   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9337   call `MatSolves`(A,x,x).
9338 
9339 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9340 @*/
9341 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9342 {
9343   PetscFunctionBegin;
9344   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9345   PetscValidType(mat, 1);
9346   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9347   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9348   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9349 
9350   MatCheckPreallocated(mat, 1);
9351   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9352   PetscUseTypeMethod(mat, solves, b, x);
9353   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9354   PetscFunctionReturn(PETSC_SUCCESS);
9355 }
9356 
9357 /*@
9358   MatIsSymmetric - Test whether a matrix is symmetric
9359 
9360   Collective
9361 
9362   Input Parameters:
9363 + A   - the matrix to test
9364 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9365 
9366   Output Parameter:
9367 . flg - the result
9368 
9369   Level: intermediate
9370 
9371   Notes:
9372   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9373 
9374   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9375 
9376   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9377   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9378 
9379 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9380           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9381 @*/
9382 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9383 {
9384   PetscFunctionBegin;
9385   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9386   PetscAssertPointer(flg, 3);
9387   if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric);
9388   else {
9389     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9390     else PetscCall(MatIsTranspose(A, A, tol, flg));
9391     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9392   }
9393   PetscFunctionReturn(PETSC_SUCCESS);
9394 }
9395 
9396 /*@
9397   MatIsHermitian - Test whether a matrix is Hermitian
9398 
9399   Collective
9400 
9401   Input Parameters:
9402 + A   - the matrix to test
9403 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9404 
9405   Output Parameter:
9406 . flg - the result
9407 
9408   Level: intermediate
9409 
9410   Notes:
9411   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9412 
9413   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9414 
9415   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9416   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9417 
9418 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9419           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9420 @*/
9421 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9422 {
9423   PetscFunctionBegin;
9424   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9425   PetscAssertPointer(flg, 3);
9426   if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian);
9427   else {
9428     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9429     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9430     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9431   }
9432   PetscFunctionReturn(PETSC_SUCCESS);
9433 }
9434 
9435 /*@
9436   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9437 
9438   Not Collective
9439 
9440   Input Parameter:
9441 . A - the matrix to check
9442 
9443   Output Parameters:
9444 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9445 - flg - the result (only valid if set is `PETSC_TRUE`)
9446 
9447   Level: advanced
9448 
9449   Notes:
9450   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9451   if you want it explicitly checked
9452 
9453   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9454   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9455 
9456 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9457 @*/
9458 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9459 {
9460   PetscFunctionBegin;
9461   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9462   PetscAssertPointer(set, 2);
9463   PetscAssertPointer(flg, 3);
9464   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9465     *set = PETSC_TRUE;
9466     *flg = PetscBool3ToBool(A->symmetric);
9467   } else {
9468     *set = PETSC_FALSE;
9469   }
9470   PetscFunctionReturn(PETSC_SUCCESS);
9471 }
9472 
9473 /*@
9474   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9475 
9476   Not Collective
9477 
9478   Input Parameter:
9479 . A - the matrix to check
9480 
9481   Output Parameters:
9482 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9483 - flg - the result (only valid if set is `PETSC_TRUE`)
9484 
9485   Level: advanced
9486 
9487   Notes:
9488   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9489 
9490   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9491   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9492 
9493 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9494 @*/
9495 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9496 {
9497   PetscFunctionBegin;
9498   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9499   PetscAssertPointer(set, 2);
9500   PetscAssertPointer(flg, 3);
9501   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9502     *set = PETSC_TRUE;
9503     *flg = PetscBool3ToBool(A->spd);
9504   } else {
9505     *set = PETSC_FALSE;
9506   }
9507   PetscFunctionReturn(PETSC_SUCCESS);
9508 }
9509 
9510 /*@
9511   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9512 
9513   Not Collective
9514 
9515   Input Parameter:
9516 . A - the matrix to check
9517 
9518   Output Parameters:
9519 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9520 - flg - the result (only valid if set is `PETSC_TRUE`)
9521 
9522   Level: advanced
9523 
9524   Notes:
9525   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9526   if you want it explicitly checked
9527 
9528   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9529   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9530 
9531 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9532 @*/
9533 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9534 {
9535   PetscFunctionBegin;
9536   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9537   PetscAssertPointer(set, 2);
9538   PetscAssertPointer(flg, 3);
9539   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9540     *set = PETSC_TRUE;
9541     *flg = PetscBool3ToBool(A->hermitian);
9542   } else {
9543     *set = PETSC_FALSE;
9544   }
9545   PetscFunctionReturn(PETSC_SUCCESS);
9546 }
9547 
9548 /*@
9549   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9550 
9551   Collective
9552 
9553   Input Parameter:
9554 . A - the matrix to test
9555 
9556   Output Parameter:
9557 . flg - the result
9558 
9559   Level: intermediate
9560 
9561   Notes:
9562   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9563 
9564   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
9565   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9566 
9567 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9568 @*/
9569 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9570 {
9571   PetscFunctionBegin;
9572   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9573   PetscAssertPointer(flg, 2);
9574   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9575     *flg = PetscBool3ToBool(A->structurally_symmetric);
9576   } else {
9577     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9578     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9579   }
9580   PetscFunctionReturn(PETSC_SUCCESS);
9581 }
9582 
9583 /*@
9584   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9585 
9586   Not Collective
9587 
9588   Input Parameter:
9589 . A - the matrix to check
9590 
9591   Output Parameters:
9592 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9593 - flg - the result (only valid if set is PETSC_TRUE)
9594 
9595   Level: advanced
9596 
9597   Notes:
9598   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
9599   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9600 
9601   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9602 
9603 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9604 @*/
9605 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9606 {
9607   PetscFunctionBegin;
9608   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9609   PetscAssertPointer(set, 2);
9610   PetscAssertPointer(flg, 3);
9611   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9612     *set = PETSC_TRUE;
9613     *flg = PetscBool3ToBool(A->structurally_symmetric);
9614   } else {
9615     *set = PETSC_FALSE;
9616   }
9617   PetscFunctionReturn(PETSC_SUCCESS);
9618 }
9619 
9620 /*@
9621   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9622   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9623 
9624   Not Collective
9625 
9626   Input Parameter:
9627 . mat - the matrix
9628 
9629   Output Parameters:
9630 + nstash    - the size of the stash
9631 . reallocs  - the number of additional mallocs incurred.
9632 . bnstash   - the size of the block stash
9633 - breallocs - the number of additional mallocs incurred.in the block stash
9634 
9635   Level: advanced
9636 
9637 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9638 @*/
9639 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9640 {
9641   PetscFunctionBegin;
9642   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9643   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9644   PetscFunctionReturn(PETSC_SUCCESS);
9645 }
9646 
9647 /*@C
9648   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9649   parallel layout, `PetscLayout` for rows and columns
9650 
9651   Collective
9652 
9653   Input Parameter:
9654 . mat - the matrix
9655 
9656   Output Parameters:
9657 + right - (optional) vector that the matrix can be multiplied against
9658 - left  - (optional) vector that the matrix vector product can be stored in
9659 
9660   Level: advanced
9661 
9662   Notes:
9663   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()`.
9664 
9665   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9666 
9667 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9668 @*/
9669 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9670 {
9671   PetscFunctionBegin;
9672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9673   PetscValidType(mat, 1);
9674   if (mat->ops->getvecs) {
9675     PetscUseTypeMethod(mat, getvecs, right, left);
9676   } else {
9677     if (right) {
9678       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9679       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9680       PetscCall(VecSetType(*right, mat->defaultvectype));
9681 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9682       if (mat->boundtocpu && mat->bindingpropagates) {
9683         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9684         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9685       }
9686 #endif
9687     }
9688     if (left) {
9689       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9690       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9691       PetscCall(VecSetType(*left, mat->defaultvectype));
9692 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9693       if (mat->boundtocpu && mat->bindingpropagates) {
9694         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9695         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9696       }
9697 #endif
9698     }
9699   }
9700   PetscFunctionReturn(PETSC_SUCCESS);
9701 }
9702 
9703 /*@C
9704   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9705   with default values.
9706 
9707   Not Collective
9708 
9709   Input Parameter:
9710 . info - the `MatFactorInfo` data structure
9711 
9712   Level: developer
9713 
9714   Notes:
9715   The solvers are generally used through the `KSP` and `PC` objects, for example
9716   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9717 
9718   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9719 
9720   Developer Note:
9721   The Fortran interface is not autogenerated as the
9722   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9723 
9724 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9725 @*/
9726 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9727 {
9728   PetscFunctionBegin;
9729   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9730   PetscFunctionReturn(PETSC_SUCCESS);
9731 }
9732 
9733 /*@
9734   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9735 
9736   Collective
9737 
9738   Input Parameters:
9739 + mat - the factored matrix
9740 - is  - the index set defining the Schur indices (0-based)
9741 
9742   Level: advanced
9743 
9744   Notes:
9745   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9746 
9747   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9748 
9749   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9750 
9751 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9752           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9753 @*/
9754 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9755 {
9756   PetscErrorCode (*f)(Mat, IS);
9757 
9758   PetscFunctionBegin;
9759   PetscValidType(mat, 1);
9760   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9761   PetscValidType(is, 2);
9762   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9763   PetscCheckSameComm(mat, 1, is, 2);
9764   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9765   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9766   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9767   PetscCall(MatDestroy(&mat->schur));
9768   PetscCall((*f)(mat, is));
9769   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9770   PetscFunctionReturn(PETSC_SUCCESS);
9771 }
9772 
9773 /*@
9774   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9775 
9776   Logically Collective
9777 
9778   Input Parameters:
9779 + F      - the factored matrix obtained by calling `MatGetFactor()`
9780 . S      - location where to return the Schur complement, can be `NULL`
9781 - status - the status of the Schur complement matrix, can be `NULL`
9782 
9783   Level: advanced
9784 
9785   Notes:
9786   You must call `MatFactorSetSchurIS()` before calling this routine.
9787 
9788   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9789 
9790   The routine provides a copy of the Schur matrix stored within the solver data structures.
9791   The caller must destroy the object when it is no longer needed.
9792   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9793 
9794   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)
9795 
9796   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9797 
9798   Developer Note:
9799   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9800   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9801 
9802 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9803 @*/
9804 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9805 {
9806   PetscFunctionBegin;
9807   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9808   if (S) PetscAssertPointer(S, 2);
9809   if (status) PetscAssertPointer(status, 3);
9810   if (S) {
9811     PetscErrorCode (*f)(Mat, Mat *);
9812 
9813     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9814     if (f) {
9815       PetscCall((*f)(F, S));
9816     } else {
9817       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9818     }
9819   }
9820   if (status) *status = F->schur_status;
9821   PetscFunctionReturn(PETSC_SUCCESS);
9822 }
9823 
9824 /*@
9825   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9826 
9827   Logically Collective
9828 
9829   Input Parameters:
9830 + F      - the factored matrix obtained by calling `MatGetFactor()`
9831 . S      - location where to return the Schur complement, can be `NULL`
9832 - status - the status of the Schur complement matrix, can be `NULL`
9833 
9834   Level: advanced
9835 
9836   Notes:
9837   You must call `MatFactorSetSchurIS()` before calling this routine.
9838 
9839   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9840 
9841   The routine returns a the Schur Complement stored within the data structures of the solver.
9842 
9843   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9844 
9845   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9846 
9847   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9848 
9849   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9850 
9851 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9852 @*/
9853 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9854 {
9855   PetscFunctionBegin;
9856   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9857   if (S) {
9858     PetscAssertPointer(S, 2);
9859     *S = F->schur;
9860   }
9861   if (status) {
9862     PetscAssertPointer(status, 3);
9863     *status = F->schur_status;
9864   }
9865   PetscFunctionReturn(PETSC_SUCCESS);
9866 }
9867 
9868 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9869 {
9870   Mat S = F->schur;
9871 
9872   PetscFunctionBegin;
9873   switch (F->schur_status) {
9874   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9875   case MAT_FACTOR_SCHUR_INVERTED:
9876     if (S) {
9877       S->ops->solve             = NULL;
9878       S->ops->matsolve          = NULL;
9879       S->ops->solvetranspose    = NULL;
9880       S->ops->matsolvetranspose = NULL;
9881       S->ops->solveadd          = NULL;
9882       S->ops->solvetransposeadd = NULL;
9883       S->factortype             = MAT_FACTOR_NONE;
9884       PetscCall(PetscFree(S->solvertype));
9885     }
9886   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9887     break;
9888   default:
9889     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9890   }
9891   PetscFunctionReturn(PETSC_SUCCESS);
9892 }
9893 
9894 /*@
9895   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9896 
9897   Logically Collective
9898 
9899   Input Parameters:
9900 + F      - the factored matrix obtained by calling `MatGetFactor()`
9901 . S      - location where the Schur complement is stored
9902 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9903 
9904   Level: advanced
9905 
9906 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9907 @*/
9908 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9909 {
9910   PetscFunctionBegin;
9911   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9912   if (S) {
9913     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9914     *S = NULL;
9915   }
9916   F->schur_status = status;
9917   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9918   PetscFunctionReturn(PETSC_SUCCESS);
9919 }
9920 
9921 /*@
9922   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9923 
9924   Logically Collective
9925 
9926   Input Parameters:
9927 + F   - the factored matrix obtained by calling `MatGetFactor()`
9928 . rhs - location where the right-hand side of the Schur complement system is stored
9929 - sol - location where the solution of the Schur complement system has to be returned
9930 
9931   Level: advanced
9932 
9933   Notes:
9934   The sizes of the vectors should match the size of the Schur complement
9935 
9936   Must be called after `MatFactorSetSchurIS()`
9937 
9938 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9939 @*/
9940 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9941 {
9942   PetscFunctionBegin;
9943   PetscValidType(F, 1);
9944   PetscValidType(rhs, 2);
9945   PetscValidType(sol, 3);
9946   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9947   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9948   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9949   PetscCheckSameComm(F, 1, rhs, 2);
9950   PetscCheckSameComm(F, 1, sol, 3);
9951   PetscCall(MatFactorFactorizeSchurComplement(F));
9952   switch (F->schur_status) {
9953   case MAT_FACTOR_SCHUR_FACTORED:
9954     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9955     break;
9956   case MAT_FACTOR_SCHUR_INVERTED:
9957     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9958     break;
9959   default:
9960     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9961   }
9962   PetscFunctionReturn(PETSC_SUCCESS);
9963 }
9964 
9965 /*@
9966   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9967 
9968   Logically Collective
9969 
9970   Input Parameters:
9971 + F   - the factored matrix obtained by calling `MatGetFactor()`
9972 . rhs - location where the right-hand side of the Schur complement system is stored
9973 - sol - location where the solution of the Schur complement system has to be returned
9974 
9975   Level: advanced
9976 
9977   Notes:
9978   The sizes of the vectors should match the size of the Schur complement
9979 
9980   Must be called after `MatFactorSetSchurIS()`
9981 
9982 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9983 @*/
9984 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9985 {
9986   PetscFunctionBegin;
9987   PetscValidType(F, 1);
9988   PetscValidType(rhs, 2);
9989   PetscValidType(sol, 3);
9990   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9991   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9992   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9993   PetscCheckSameComm(F, 1, rhs, 2);
9994   PetscCheckSameComm(F, 1, sol, 3);
9995   PetscCall(MatFactorFactorizeSchurComplement(F));
9996   switch (F->schur_status) {
9997   case MAT_FACTOR_SCHUR_FACTORED:
9998     PetscCall(MatSolve(F->schur, rhs, sol));
9999     break;
10000   case MAT_FACTOR_SCHUR_INVERTED:
10001     PetscCall(MatMult(F->schur, rhs, sol));
10002     break;
10003   default:
10004     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10005   }
10006   PetscFunctionReturn(PETSC_SUCCESS);
10007 }
10008 
10009 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10010 #if PetscDefined(HAVE_CUDA)
10011 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10012 #endif
10013 
10014 /* Schur status updated in the interface */
10015 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10016 {
10017   Mat S = F->schur;
10018 
10019   PetscFunctionBegin;
10020   if (S) {
10021     PetscMPIInt size;
10022     PetscBool   isdense, isdensecuda;
10023 
10024     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10025     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10026     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10027     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10028     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10029     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10030     if (isdense) {
10031       PetscCall(MatSeqDenseInvertFactors_Private(S));
10032     } else if (isdensecuda) {
10033 #if defined(PETSC_HAVE_CUDA)
10034       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10035 #endif
10036     }
10037     // HIP??????????????
10038     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10039   }
10040   PetscFunctionReturn(PETSC_SUCCESS);
10041 }
10042 
10043 /*@
10044   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10045 
10046   Logically Collective
10047 
10048   Input Parameter:
10049 . F - the factored matrix obtained by calling `MatGetFactor()`
10050 
10051   Level: advanced
10052 
10053   Notes:
10054   Must be called after `MatFactorSetSchurIS()`.
10055 
10056   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10057 
10058 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10059 @*/
10060 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10061 {
10062   PetscFunctionBegin;
10063   PetscValidType(F, 1);
10064   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10065   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10066   PetscCall(MatFactorFactorizeSchurComplement(F));
10067   PetscCall(MatFactorInvertSchurComplement_Private(F));
10068   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10069   PetscFunctionReturn(PETSC_SUCCESS);
10070 }
10071 
10072 /*@
10073   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10074 
10075   Logically Collective
10076 
10077   Input Parameter:
10078 . F - the factored matrix obtained by calling `MatGetFactor()`
10079 
10080   Level: advanced
10081 
10082   Note:
10083   Must be called after `MatFactorSetSchurIS()`
10084 
10085 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10086 @*/
10087 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10088 {
10089   MatFactorInfo info;
10090 
10091   PetscFunctionBegin;
10092   PetscValidType(F, 1);
10093   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10094   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10095   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10096   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10097   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10098     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10099   } else {
10100     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10101   }
10102   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10103   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10104   PetscFunctionReturn(PETSC_SUCCESS);
10105 }
10106 
10107 /*@
10108   MatPtAP - Creates the matrix product $C = P^T * A * P$
10109 
10110   Neighbor-wise Collective
10111 
10112   Input Parameters:
10113 + A     - the matrix
10114 . P     - the projection matrix
10115 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10116 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
10117           if the result is a dense matrix this is irrelevant
10118 
10119   Output Parameter:
10120 . C - the product matrix
10121 
10122   Level: intermediate
10123 
10124   Notes:
10125   C will be created and must be destroyed by the user with `MatDestroy()`.
10126 
10127   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10128 
10129   Developer Note:
10130   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10131 
10132 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10133 @*/
10134 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10135 {
10136   PetscFunctionBegin;
10137   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10138   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10139 
10140   if (scall == MAT_INITIAL_MATRIX) {
10141     PetscCall(MatProductCreate(A, P, NULL, C));
10142     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10143     PetscCall(MatProductSetAlgorithm(*C, "default"));
10144     PetscCall(MatProductSetFill(*C, fill));
10145 
10146     (*C)->product->api_user = PETSC_TRUE;
10147     PetscCall(MatProductSetFromOptions(*C));
10148     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);
10149     PetscCall(MatProductSymbolic(*C));
10150   } else { /* scall == MAT_REUSE_MATRIX */
10151     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10152   }
10153 
10154   PetscCall(MatProductNumeric(*C));
10155   (*C)->symmetric = A->symmetric;
10156   (*C)->spd       = A->spd;
10157   PetscFunctionReturn(PETSC_SUCCESS);
10158 }
10159 
10160 /*@
10161   MatRARt - Creates the matrix product $C = R * A * R^T$
10162 
10163   Neighbor-wise Collective
10164 
10165   Input Parameters:
10166 + A     - the matrix
10167 . R     - the projection matrix
10168 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10169 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
10170           if the result is a dense matrix this is irrelevant
10171 
10172   Output Parameter:
10173 . C - the product matrix
10174 
10175   Level: intermediate
10176 
10177   Notes:
10178   C will be created and must be destroyed by the user with `MatDestroy()`.
10179 
10180   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10181 
10182   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10183   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10184   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
10185   We recommend using MatPtAP().
10186 
10187 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10188 @*/
10189 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10190 {
10191   PetscFunctionBegin;
10192   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10193   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10194 
10195   if (scall == MAT_INITIAL_MATRIX) {
10196     PetscCall(MatProductCreate(A, R, NULL, C));
10197     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10198     PetscCall(MatProductSetAlgorithm(*C, "default"));
10199     PetscCall(MatProductSetFill(*C, fill));
10200 
10201     (*C)->product->api_user = PETSC_TRUE;
10202     PetscCall(MatProductSetFromOptions(*C));
10203     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);
10204     PetscCall(MatProductSymbolic(*C));
10205   } else { /* scall == MAT_REUSE_MATRIX */
10206     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10207   }
10208 
10209   PetscCall(MatProductNumeric(*C));
10210   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10211   PetscFunctionReturn(PETSC_SUCCESS);
10212 }
10213 
10214 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10215 {
10216   PetscBool flg = PETSC_TRUE;
10217 
10218   PetscFunctionBegin;
10219   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10220   if (scall == MAT_INITIAL_MATRIX) {
10221     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10222     PetscCall(MatProductCreate(A, B, NULL, C));
10223     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10224     PetscCall(MatProductSetFill(*C, fill));
10225   } else { /* scall == MAT_REUSE_MATRIX */
10226     Mat_Product *product = (*C)->product;
10227 
10228     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10229     if (flg && product && product->type != ptype) {
10230       PetscCall(MatProductClear(*C));
10231       product = NULL;
10232     }
10233     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10234     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10235       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10236       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10237       product        = (*C)->product;
10238       product->fill  = fill;
10239       product->clear = PETSC_TRUE;
10240     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10241       flg = PETSC_FALSE;
10242       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10243     }
10244   }
10245   if (flg) {
10246     (*C)->product->api_user = PETSC_TRUE;
10247     PetscCall(MatProductSetType(*C, ptype));
10248     PetscCall(MatProductSetFromOptions(*C));
10249     PetscCall(MatProductSymbolic(*C));
10250   }
10251   PetscCall(MatProductNumeric(*C));
10252   PetscFunctionReturn(PETSC_SUCCESS);
10253 }
10254 
10255 /*@
10256   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10257 
10258   Neighbor-wise Collective
10259 
10260   Input Parameters:
10261 + A     - the left matrix
10262 . B     - the right matrix
10263 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10264 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10265           if the result is a dense matrix this is irrelevant
10266 
10267   Output Parameter:
10268 . C - the product matrix
10269 
10270   Notes:
10271   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10272 
10273   `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
10274   call to this function with `MAT_INITIAL_MATRIX`.
10275 
10276   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10277 
10278   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`,
10279   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10280 
10281   Example of Usage:
10282 .vb
10283      MatProductCreate(A,B,NULL,&C);
10284      MatProductSetType(C,MATPRODUCT_AB);
10285      MatProductSymbolic(C);
10286      MatProductNumeric(C); // compute C=A * B
10287      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10288      MatProductNumeric(C);
10289      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10290      MatProductNumeric(C);
10291 .ve
10292 
10293   Level: intermediate
10294 
10295 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10296 @*/
10297 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10298 {
10299   PetscFunctionBegin;
10300   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10301   PetscFunctionReturn(PETSC_SUCCESS);
10302 }
10303 
10304 /*@
10305   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10306 
10307   Neighbor-wise Collective
10308 
10309   Input Parameters:
10310 + A     - the left matrix
10311 . B     - the right matrix
10312 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10313 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10314 
10315   Output Parameter:
10316 . C - the product matrix
10317 
10318   Options Database Key:
10319 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10320               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10321               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10322 
10323   Level: intermediate
10324 
10325   Notes:
10326   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10327 
10328   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10329 
10330   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10331   actually needed.
10332 
10333   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10334   and for pairs of `MATMPIDENSE` matrices.
10335 
10336   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10337 
10338 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10339 @*/
10340 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10341 {
10342   PetscFunctionBegin;
10343   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10344   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10345   PetscFunctionReturn(PETSC_SUCCESS);
10346 }
10347 
10348 /*@
10349   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10350 
10351   Neighbor-wise Collective
10352 
10353   Input Parameters:
10354 + A     - the left matrix
10355 . B     - the right matrix
10356 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10357 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10358 
10359   Output Parameter:
10360 . C - the product matrix
10361 
10362   Level: intermediate
10363 
10364   Notes:
10365   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10366 
10367   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10368 
10369   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10370 
10371   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10372   actually needed.
10373 
10374   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10375   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10376 
10377 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10378 @*/
10379 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10380 {
10381   PetscFunctionBegin;
10382   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10383   PetscFunctionReturn(PETSC_SUCCESS);
10384 }
10385 
10386 /*@
10387   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10388 
10389   Neighbor-wise Collective
10390 
10391   Input Parameters:
10392 + A     - the left matrix
10393 . B     - the middle matrix
10394 . C     - the right matrix
10395 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10396 - 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
10397           if the result is a dense matrix this is irrelevant
10398 
10399   Output Parameter:
10400 . D - the product matrix
10401 
10402   Level: intermediate
10403 
10404   Notes:
10405   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10406 
10407   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10408 
10409   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10410 
10411   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10412   actually needed.
10413 
10414   If you have many matrices with the same non-zero structure to multiply, you
10415   should use `MAT_REUSE_MATRIX` in all calls but the first
10416 
10417 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10418 @*/
10419 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10420 {
10421   PetscFunctionBegin;
10422   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10423   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10424 
10425   if (scall == MAT_INITIAL_MATRIX) {
10426     PetscCall(MatProductCreate(A, B, C, D));
10427     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10428     PetscCall(MatProductSetAlgorithm(*D, "default"));
10429     PetscCall(MatProductSetFill(*D, fill));
10430 
10431     (*D)->product->api_user = PETSC_TRUE;
10432     PetscCall(MatProductSetFromOptions(*D));
10433     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,
10434                ((PetscObject)C)->type_name);
10435     PetscCall(MatProductSymbolic(*D));
10436   } else { /* user may change input matrices when REUSE */
10437     PetscCall(MatProductReplaceMats(A, B, C, *D));
10438   }
10439   PetscCall(MatProductNumeric(*D));
10440   PetscFunctionReturn(PETSC_SUCCESS);
10441 }
10442 
10443 /*@
10444   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10445 
10446   Collective
10447 
10448   Input Parameters:
10449 + mat      - the matrix
10450 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10451 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10452 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10453 
10454   Output Parameter:
10455 . matredundant - redundant matrix
10456 
10457   Level: advanced
10458 
10459   Notes:
10460   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10461   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10462 
10463   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10464   calling it.
10465 
10466   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10467 
10468 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10469 @*/
10470 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10471 {
10472   MPI_Comm       comm;
10473   PetscMPIInt    size;
10474   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10475   Mat_Redundant *redund     = NULL;
10476   PetscSubcomm   psubcomm   = NULL;
10477   MPI_Comm       subcomm_in = subcomm;
10478   Mat           *matseq;
10479   IS             isrow, iscol;
10480   PetscBool      newsubcomm = PETSC_FALSE;
10481 
10482   PetscFunctionBegin;
10483   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10484   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10485     PetscAssertPointer(*matredundant, 5);
10486     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10487   }
10488 
10489   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10490   if (size == 1 || nsubcomm == 1) {
10491     if (reuse == MAT_INITIAL_MATRIX) {
10492       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10493     } else {
10494       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");
10495       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10496     }
10497     PetscFunctionReturn(PETSC_SUCCESS);
10498   }
10499 
10500   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10501   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10502   MatCheckPreallocated(mat, 1);
10503 
10504   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10505   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10506     /* create psubcomm, then get subcomm */
10507     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10508     PetscCallMPI(MPI_Comm_size(comm, &size));
10509     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10510 
10511     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10512     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10513     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10514     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10515     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10516     newsubcomm = PETSC_TRUE;
10517     PetscCall(PetscSubcommDestroy(&psubcomm));
10518   }
10519 
10520   /* get isrow, iscol and a local sequential matrix matseq[0] */
10521   if (reuse == MAT_INITIAL_MATRIX) {
10522     mloc_sub = PETSC_DECIDE;
10523     nloc_sub = PETSC_DECIDE;
10524     if (bs < 1) {
10525       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10526       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10527     } else {
10528       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10529       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10530     }
10531     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10532     rstart = rend - mloc_sub;
10533     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10534     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10535     PetscCall(ISSetIdentity(iscol));
10536   } else { /* reuse == MAT_REUSE_MATRIX */
10537     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");
10538     /* retrieve subcomm */
10539     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10540     redund = (*matredundant)->redundant;
10541     isrow  = redund->isrow;
10542     iscol  = redund->iscol;
10543     matseq = redund->matseq;
10544   }
10545   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10546 
10547   /* get matredundant over subcomm */
10548   if (reuse == MAT_INITIAL_MATRIX) {
10549     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10550 
10551     /* create a supporting struct and attach it to C for reuse */
10552     PetscCall(PetscNew(&redund));
10553     (*matredundant)->redundant = redund;
10554     redund->isrow              = isrow;
10555     redund->iscol              = iscol;
10556     redund->matseq             = matseq;
10557     if (newsubcomm) {
10558       redund->subcomm = subcomm;
10559     } else {
10560       redund->subcomm = MPI_COMM_NULL;
10561     }
10562   } else {
10563     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10564   }
10565 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10566   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10567     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10568     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10569   }
10570 #endif
10571   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10572   PetscFunctionReturn(PETSC_SUCCESS);
10573 }
10574 
10575 /*@C
10576   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10577   a given `Mat`. Each submatrix can span multiple procs.
10578 
10579   Collective
10580 
10581   Input Parameters:
10582 + mat     - the matrix
10583 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10584 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10585 
10586   Output Parameter:
10587 . subMat - parallel sub-matrices each spanning a given `subcomm`
10588 
10589   Level: advanced
10590 
10591   Notes:
10592   The submatrix partition across processors is dictated by `subComm` a
10593   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10594   is not restricted to be grouped with consecutive original MPI processes.
10595 
10596   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10597   map directly to the layout of the original matrix [wrt the local
10598   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10599   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10600   the `subMat`. However the offDiagMat looses some columns - and this is
10601   reconstructed with `MatSetValues()`
10602 
10603   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10604 
10605 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10606 @*/
10607 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10608 {
10609   PetscMPIInt commsize, subCommSize;
10610 
10611   PetscFunctionBegin;
10612   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10613   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10614   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10615 
10616   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");
10617   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10618   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10619   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10620   PetscFunctionReturn(PETSC_SUCCESS);
10621 }
10622 
10623 /*@
10624   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10625 
10626   Not Collective
10627 
10628   Input Parameters:
10629 + mat   - matrix to extract local submatrix from
10630 . isrow - local row indices for submatrix
10631 - iscol - local column indices for submatrix
10632 
10633   Output Parameter:
10634 . submat - the submatrix
10635 
10636   Level: intermediate
10637 
10638   Notes:
10639   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10640 
10641   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10642   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10643 
10644   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10645   `MatSetValuesBlockedLocal()` will also be implemented.
10646 
10647   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10648   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10649 
10650 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10651 @*/
10652 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10653 {
10654   PetscFunctionBegin;
10655   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10656   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10657   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10658   PetscCheckSameComm(isrow, 2, iscol, 3);
10659   PetscAssertPointer(submat, 4);
10660   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10661 
10662   if (mat->ops->getlocalsubmatrix) {
10663     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10664   } else {
10665     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10666   }
10667   PetscFunctionReturn(PETSC_SUCCESS);
10668 }
10669 
10670 /*@
10671   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10672 
10673   Not Collective
10674 
10675   Input Parameters:
10676 + mat    - matrix to extract local submatrix from
10677 . isrow  - local row indices for submatrix
10678 . iscol  - local column indices for submatrix
10679 - submat - the submatrix
10680 
10681   Level: intermediate
10682 
10683 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10684 @*/
10685 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10686 {
10687   PetscFunctionBegin;
10688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10689   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10690   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10691   PetscCheckSameComm(isrow, 2, iscol, 3);
10692   PetscAssertPointer(submat, 4);
10693   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10694 
10695   if (mat->ops->restorelocalsubmatrix) {
10696     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10697   } else {
10698     PetscCall(MatDestroy(submat));
10699   }
10700   *submat = NULL;
10701   PetscFunctionReturn(PETSC_SUCCESS);
10702 }
10703 
10704 /*@
10705   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10706 
10707   Collective
10708 
10709   Input Parameter:
10710 . mat - the matrix
10711 
10712   Output Parameter:
10713 . is - if any rows have zero diagonals this contains the list of them
10714 
10715   Level: developer
10716 
10717 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10718 @*/
10719 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10720 {
10721   PetscFunctionBegin;
10722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10723   PetscValidType(mat, 1);
10724   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10725   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10726 
10727   if (!mat->ops->findzerodiagonals) {
10728     Vec                diag;
10729     const PetscScalar *a;
10730     PetscInt          *rows;
10731     PetscInt           rStart, rEnd, r, nrow = 0;
10732 
10733     PetscCall(MatCreateVecs(mat, &diag, NULL));
10734     PetscCall(MatGetDiagonal(mat, diag));
10735     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10736     PetscCall(VecGetArrayRead(diag, &a));
10737     for (r = 0; r < rEnd - rStart; ++r)
10738       if (a[r] == 0.0) ++nrow;
10739     PetscCall(PetscMalloc1(nrow, &rows));
10740     nrow = 0;
10741     for (r = 0; r < rEnd - rStart; ++r)
10742       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10743     PetscCall(VecRestoreArrayRead(diag, &a));
10744     PetscCall(VecDestroy(&diag));
10745     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10746   } else {
10747     PetscUseTypeMethod(mat, findzerodiagonals, is);
10748   }
10749   PetscFunctionReturn(PETSC_SUCCESS);
10750 }
10751 
10752 /*@
10753   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10754 
10755   Collective
10756 
10757   Input Parameter:
10758 . mat - the matrix
10759 
10760   Output Parameter:
10761 . is - contains the list of rows with off block diagonal entries
10762 
10763   Level: developer
10764 
10765 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10766 @*/
10767 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10768 {
10769   PetscFunctionBegin;
10770   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10771   PetscValidType(mat, 1);
10772   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10773   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10774 
10775   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10776   PetscFunctionReturn(PETSC_SUCCESS);
10777 }
10778 
10779 /*@C
10780   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10781 
10782   Collective; No Fortran Support
10783 
10784   Input Parameter:
10785 . mat - the matrix
10786 
10787   Output Parameter:
10788 . values - the block inverses in column major order (FORTRAN-like)
10789 
10790   Level: advanced
10791 
10792   Notes:
10793   The size of the blocks is determined by the block size of the matrix.
10794 
10795   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10796 
10797   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10798 
10799 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10800 @*/
10801 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10802 {
10803   PetscFunctionBegin;
10804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10805   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10806   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10807   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10808   PetscFunctionReturn(PETSC_SUCCESS);
10809 }
10810 
10811 /*@
10812   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10813 
10814   Collective; No Fortran Support
10815 
10816   Input Parameters:
10817 + mat     - the matrix
10818 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10819 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10820 
10821   Output Parameter:
10822 . values - the block inverses in column major order (FORTRAN-like)
10823 
10824   Level: advanced
10825 
10826   Notes:
10827   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10828 
10829   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10830 
10831 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10832 @*/
10833 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10834 {
10835   PetscFunctionBegin;
10836   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10837   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10838   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10839   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10840   PetscFunctionReturn(PETSC_SUCCESS);
10841 }
10842 
10843 /*@
10844   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10845 
10846   Collective
10847 
10848   Input Parameters:
10849 + A - the matrix
10850 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10851 
10852   Level: advanced
10853 
10854   Note:
10855   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10856 
10857 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10858 @*/
10859 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10860 {
10861   const PetscScalar *vals;
10862   PetscInt          *dnnz;
10863   PetscInt           m, rstart, rend, bs, i, j;
10864 
10865   PetscFunctionBegin;
10866   PetscCall(MatInvertBlockDiagonal(A, &vals));
10867   PetscCall(MatGetBlockSize(A, &bs));
10868   PetscCall(MatGetLocalSize(A, &m, NULL));
10869   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10870   PetscCall(PetscMalloc1(m / bs, &dnnz));
10871   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10872   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10873   PetscCall(PetscFree(dnnz));
10874   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10875   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10876   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10877   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10878   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10879   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10880   PetscFunctionReturn(PETSC_SUCCESS);
10881 }
10882 
10883 /*@C
10884   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10885   via `MatTransposeColoringCreate()`.
10886 
10887   Collective
10888 
10889   Input Parameter:
10890 . c - coloring context
10891 
10892   Level: intermediate
10893 
10894 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10895 @*/
10896 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10897 {
10898   MatTransposeColoring matcolor = *c;
10899 
10900   PetscFunctionBegin;
10901   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10902   if (--((PetscObject)matcolor)->refct > 0) {
10903     matcolor = NULL;
10904     PetscFunctionReturn(PETSC_SUCCESS);
10905   }
10906 
10907   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10908   PetscCall(PetscFree(matcolor->rows));
10909   PetscCall(PetscFree(matcolor->den2sp));
10910   PetscCall(PetscFree(matcolor->colorforcol));
10911   PetscCall(PetscFree(matcolor->columns));
10912   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10913   PetscCall(PetscHeaderDestroy(c));
10914   PetscFunctionReturn(PETSC_SUCCESS);
10915 }
10916 
10917 /*@
10918   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10919   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10920   `MatTransposeColoring` to sparse `B`.
10921 
10922   Collective
10923 
10924   Input Parameters:
10925 + coloring - coloring context created with `MatTransposeColoringCreate()`
10926 - B        - sparse matrix
10927 
10928   Output Parameter:
10929 . Btdense - dense matrix $B^T$
10930 
10931   Level: developer
10932 
10933   Note:
10934   These are used internally for some implementations of `MatRARt()`
10935 
10936 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10937 @*/
10938 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10939 {
10940   PetscFunctionBegin;
10941   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10942   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10943   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10944 
10945   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10946   PetscFunctionReturn(PETSC_SUCCESS);
10947 }
10948 
10949 /*@
10950   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10951   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10952   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10953   $C_{sp}$ from $C_{den}$.
10954 
10955   Collective
10956 
10957   Input Parameters:
10958 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10959 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10960 
10961   Output Parameter:
10962 . Csp - sparse matrix
10963 
10964   Level: developer
10965 
10966   Note:
10967   These are used internally for some implementations of `MatRARt()`
10968 
10969 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10970 @*/
10971 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10972 {
10973   PetscFunctionBegin;
10974   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10975   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10976   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10977 
10978   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10979   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10980   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10981   PetscFunctionReturn(PETSC_SUCCESS);
10982 }
10983 
10984 /*@
10985   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10986 
10987   Collective
10988 
10989   Input Parameters:
10990 + mat        - the matrix product C
10991 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10992 
10993   Output Parameter:
10994 . color - the new coloring context
10995 
10996   Level: intermediate
10997 
10998 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10999           `MatTransColoringApplyDenToSp()`
11000 @*/
11001 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11002 {
11003   MatTransposeColoring c;
11004   MPI_Comm             comm;
11005 
11006   PetscFunctionBegin;
11007   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11008   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11009   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11010 
11011   c->ctype = iscoloring->ctype;
11012   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11013 
11014   *color = c;
11015   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11016   PetscFunctionReturn(PETSC_SUCCESS);
11017 }
11018 
11019 /*@
11020   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11021   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11022 
11023   Not Collective
11024 
11025   Input Parameter:
11026 . mat - the matrix
11027 
11028   Output Parameter:
11029 . state - the current state
11030 
11031   Level: intermediate
11032 
11033   Notes:
11034   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11035   different matrices
11036 
11037   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11038 
11039   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11040 
11041 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11042 @*/
11043 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11044 {
11045   PetscFunctionBegin;
11046   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11047   *state = mat->nonzerostate;
11048   PetscFunctionReturn(PETSC_SUCCESS);
11049 }
11050 
11051 /*@
11052   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11053   matrices from each processor
11054 
11055   Collective
11056 
11057   Input Parameters:
11058 + comm   - the communicators the parallel matrix will live on
11059 . seqmat - the input sequential matrices
11060 . n      - number of local columns (or `PETSC_DECIDE`)
11061 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11062 
11063   Output Parameter:
11064 . mpimat - the parallel matrix generated
11065 
11066   Level: developer
11067 
11068   Note:
11069   The number of columns of the matrix in EACH processor MUST be the same.
11070 
11071 .seealso: [](ch_matrices), `Mat`
11072 @*/
11073 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11074 {
11075   PetscMPIInt size;
11076 
11077   PetscFunctionBegin;
11078   PetscCallMPI(MPI_Comm_size(comm, &size));
11079   if (size == 1) {
11080     if (reuse == MAT_INITIAL_MATRIX) {
11081       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11082     } else {
11083       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11084     }
11085     PetscFunctionReturn(PETSC_SUCCESS);
11086   }
11087 
11088   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");
11089 
11090   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11091   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11092   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11093   PetscFunctionReturn(PETSC_SUCCESS);
11094 }
11095 
11096 /*@
11097   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11098 
11099   Collective
11100 
11101   Input Parameters:
11102 + A - the matrix to create subdomains from
11103 - N - requested number of subdomains
11104 
11105   Output Parameters:
11106 + n   - number of subdomains resulting on this MPI process
11107 - iss - `IS` list with indices of subdomains on this MPI process
11108 
11109   Level: advanced
11110 
11111   Note:
11112   The number of subdomains must be smaller than the communicator size
11113 
11114 .seealso: [](ch_matrices), `Mat`, `IS`
11115 @*/
11116 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11117 {
11118   MPI_Comm    comm, subcomm;
11119   PetscMPIInt size, rank, color;
11120   PetscInt    rstart, rend, k;
11121 
11122   PetscFunctionBegin;
11123   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11124   PetscCallMPI(MPI_Comm_size(comm, &size));
11125   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11126   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);
11127   *n    = 1;
11128   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11129   color = rank / k;
11130   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11131   PetscCall(PetscMalloc1(1, iss));
11132   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11133   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11134   PetscCallMPI(MPI_Comm_free(&subcomm));
11135   PetscFunctionReturn(PETSC_SUCCESS);
11136 }
11137 
11138 /*@
11139   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11140 
11141   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11142   If they are not the same, uses `MatMatMatMult()`.
11143 
11144   Once the coarse grid problem is constructed, correct for interpolation operators
11145   that are not of full rank, which can legitimately happen in the case of non-nested
11146   geometric multigrid.
11147 
11148   Input Parameters:
11149 + restrct     - restriction operator
11150 . dA          - fine grid matrix
11151 . interpolate - interpolation operator
11152 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11153 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
11154 
11155   Output Parameter:
11156 . A - the Galerkin coarse matrix
11157 
11158   Options Database Key:
11159 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11160 
11161   Level: developer
11162 
11163 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11164 @*/
11165 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11166 {
11167   IS  zerorows;
11168   Vec diag;
11169 
11170   PetscFunctionBegin;
11171   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11172   /* Construct the coarse grid matrix */
11173   if (interpolate == restrct) {
11174     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11175   } else {
11176     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11177   }
11178 
11179   /* If the interpolation matrix is not of full rank, A will have zero rows.
11180      This can legitimately happen in the case of non-nested geometric multigrid.
11181      In that event, we set the rows of the matrix to the rows of the identity,
11182      ignoring the equations (as the RHS will also be zero). */
11183 
11184   PetscCall(MatFindZeroRows(*A, &zerorows));
11185 
11186   if (zerorows != NULL) { /* if there are any zero rows */
11187     PetscCall(MatCreateVecs(*A, &diag, NULL));
11188     PetscCall(MatGetDiagonal(*A, diag));
11189     PetscCall(VecISSet(diag, zerorows, 1.0));
11190     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11191     PetscCall(VecDestroy(&diag));
11192     PetscCall(ISDestroy(&zerorows));
11193   }
11194   PetscFunctionReturn(PETSC_SUCCESS);
11195 }
11196 
11197 /*@C
11198   MatSetOperation - Allows user to set a matrix operation for any matrix type
11199 
11200   Logically Collective
11201 
11202   Input Parameters:
11203 + mat - the matrix
11204 . op  - the name of the operation
11205 - f   - the function that provides the operation
11206 
11207   Level: developer
11208 
11209   Example Usage:
11210 .vb
11211   extern PetscErrorCode usermult(Mat, Vec, Vec);
11212 
11213   PetscCall(MatCreateXXX(comm, ..., &A));
11214   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11215 .ve
11216 
11217   Notes:
11218   See the file `include/petscmat.h` for a complete list of matrix
11219   operations, which all have the form MATOP_<OPERATION>, where
11220   <OPERATION> is the name (in all capital letters) of the
11221   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11222 
11223   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11224   sequence as the usual matrix interface routines, since they
11225   are intended to be accessed via the usual matrix interface
11226   routines, e.g.,
11227 .vb
11228   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11229 .ve
11230 
11231   In particular each function MUST return `PETSC_SUCCESS` on success and
11232   nonzero on failure.
11233 
11234   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11235 
11236 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11237 @*/
11238 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11239 {
11240   PetscFunctionBegin;
11241   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11242   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11243   (((void (**)(void))mat->ops)[op]) = f;
11244   PetscFunctionReturn(PETSC_SUCCESS);
11245 }
11246 
11247 /*@C
11248   MatGetOperation - Gets a matrix operation for any matrix type.
11249 
11250   Not Collective
11251 
11252   Input Parameters:
11253 + mat - the matrix
11254 - op  - the name of the operation
11255 
11256   Output Parameter:
11257 . f - the function that provides the operation
11258 
11259   Level: developer
11260 
11261   Example Usage:
11262 .vb
11263   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11264 
11265   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11266 .ve
11267 
11268   Notes:
11269   See the file include/petscmat.h for a complete list of matrix
11270   operations, which all have the form MATOP_<OPERATION>, where
11271   <OPERATION> is the name (in all capital letters) of the
11272   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11273 
11274   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11275 
11276 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11277 @*/
11278 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11279 {
11280   PetscFunctionBegin;
11281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11282   *f = (((void (**)(void))mat->ops)[op]);
11283   PetscFunctionReturn(PETSC_SUCCESS);
11284 }
11285 
11286 /*@
11287   MatHasOperation - Determines whether the given matrix supports the particular operation.
11288 
11289   Not Collective
11290 
11291   Input Parameters:
11292 + mat - the matrix
11293 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11294 
11295   Output Parameter:
11296 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11297 
11298   Level: advanced
11299 
11300   Note:
11301   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11302 
11303 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11304 @*/
11305 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11306 {
11307   PetscFunctionBegin;
11308   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11309   PetscAssertPointer(has, 3);
11310   if (mat->ops->hasoperation) {
11311     PetscUseTypeMethod(mat, hasoperation, op, has);
11312   } else {
11313     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11314     else {
11315       *has = PETSC_FALSE;
11316       if (op == MATOP_CREATE_SUBMATRIX) {
11317         PetscMPIInt size;
11318 
11319         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11320         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11321       }
11322     }
11323   }
11324   PetscFunctionReturn(PETSC_SUCCESS);
11325 }
11326 
11327 /*@
11328   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11329 
11330   Collective
11331 
11332   Input Parameter:
11333 . mat - the matrix
11334 
11335   Output Parameter:
11336 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11337 
11338   Level: beginner
11339 
11340 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11341 @*/
11342 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11343 {
11344   PetscFunctionBegin;
11345   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11346   PetscValidType(mat, 1);
11347   PetscAssertPointer(cong, 2);
11348   if (!mat->rmap || !mat->cmap) {
11349     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11350     PetscFunctionReturn(PETSC_SUCCESS);
11351   }
11352   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11353     PetscCall(PetscLayoutSetUp(mat->rmap));
11354     PetscCall(PetscLayoutSetUp(mat->cmap));
11355     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11356     if (*cong) mat->congruentlayouts = 1;
11357     else mat->congruentlayouts = 0;
11358   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11359   PetscFunctionReturn(PETSC_SUCCESS);
11360 }
11361 
11362 PetscErrorCode MatSetInf(Mat A)
11363 {
11364   PetscFunctionBegin;
11365   PetscUseTypeMethod(A, setinf);
11366   PetscFunctionReturn(PETSC_SUCCESS);
11367 }
11368 
11369 /*@
11370   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
11371   and possibly removes small values from the graph structure.
11372 
11373   Collective
11374 
11375   Input Parameters:
11376 + A       - the matrix
11377 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11378 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11379 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11380 . num_idx - size of 'index' array
11381 - index   - array of block indices to use for graph strength of connection weight
11382 
11383   Output Parameter:
11384 . graph - the resulting graph
11385 
11386   Level: advanced
11387 
11388 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11389 @*/
11390 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11391 {
11392   PetscFunctionBegin;
11393   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11394   PetscValidType(A, 1);
11395   PetscValidLogicalCollectiveBool(A, scale, 3);
11396   PetscAssertPointer(graph, 7);
11397   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11398   PetscFunctionReturn(PETSC_SUCCESS);
11399 }
11400 
11401 /*@
11402   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11403   meaning the same memory is used for the matrix, and no new memory is allocated.
11404 
11405   Collective
11406 
11407   Input Parameters:
11408 + A    - the matrix
11409 - keep - if for a given row of `A`, the diagonal coefficient is zero, indicates whether it should be left in the structure or eliminated as well
11410 
11411   Level: intermediate
11412 
11413   Developer Note:
11414   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11415   of the arrays in the data structure are unneeded.
11416 
11417 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11418 @*/
11419 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11420 {
11421   PetscFunctionBegin;
11422   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11423   PetscUseTypeMethod(A, eliminatezeros, keep);
11424   PetscFunctionReturn(PETSC_SUCCESS);
11425 }
11426