xref: /petsc/src/mat/interface/matrix.c (revision f5bab676488eab7ccb90dc895dfba268b72c04e0)
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, shell, hasop = PETSC_FALSE;
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(MatIsShell(mat, &shell));
4829   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4830   if (hasop) {
4831     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4832     PetscFunctionReturn(PETSC_SUCCESS);
4833   }
4834 
4835   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4836   if (!foundtype) {
4837     if (type) {
4838       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],
4839               ((PetscObject)mat)->type_name, type);
4840     } else {
4841       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);
4842     }
4843   }
4844   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4845   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);
4846 
4847   PetscCall((*conv)(mat, ftype, f));
4848   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4849   PetscFunctionReturn(PETSC_SUCCESS);
4850 }
4851 
4852 /*@
4853   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4854 
4855   Not Collective
4856 
4857   Input Parameters:
4858 + mat   - the matrix
4859 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4860 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4861 
4862   Output Parameter:
4863 . flg - PETSC_TRUE if the factorization is available
4864 
4865   Level: intermediate
4866 
4867   Notes:
4868   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4869   such as pastix, superlu, mumps etc.
4870 
4871   PETSc must have been ./configure to use the external solver, using the option --download-package
4872 
4873   Developer Note:
4874   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4875 
4876 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4877           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4878 @*/
4879 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4880 {
4881   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4882 
4883   PetscFunctionBegin;
4884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4885   PetscAssertPointer(flg, 4);
4886 
4887   *flg = PETSC_FALSE;
4888   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4889 
4890   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4891   MatCheckPreallocated(mat, 1);
4892 
4893   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4894   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4895   PetscFunctionReturn(PETSC_SUCCESS);
4896 }
4897 
4898 /*@
4899   MatDuplicate - Duplicates a matrix including the non-zero structure.
4900 
4901   Collective
4902 
4903   Input Parameters:
4904 + mat - the matrix
4905 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4906         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4907 
4908   Output Parameter:
4909 . M - pointer to place new matrix
4910 
4911   Level: intermediate
4912 
4913   Notes:
4914   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4915 
4916   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4917 
4918   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.
4919 
4920   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4921   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4922   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4923 
4924 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4925 @*/
4926 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4927 {
4928   Mat         B;
4929   VecType     vtype;
4930   PetscInt    i;
4931   PetscObject dm, container_h, container_d;
4932   void (*viewf)(void);
4933 
4934   PetscFunctionBegin;
4935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4936   PetscValidType(mat, 1);
4937   PetscAssertPointer(M, 3);
4938   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4939   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4940   MatCheckPreallocated(mat, 1);
4941 
4942   *M = NULL;
4943   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4944   PetscUseTypeMethod(mat, duplicate, op, M);
4945   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4946   B = *M;
4947 
4948   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4949   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4950   PetscCall(MatGetVecType(mat, &vtype));
4951   PetscCall(MatSetVecType(B, vtype));
4952 
4953   B->stencil.dim = mat->stencil.dim;
4954   B->stencil.noc = mat->stencil.noc;
4955   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4956     B->stencil.dims[i]   = mat->stencil.dims[i];
4957     B->stencil.starts[i] = mat->stencil.starts[i];
4958   }
4959 
4960   B->nooffproczerorows = mat->nooffproczerorows;
4961   B->nooffprocentries  = mat->nooffprocentries;
4962 
4963   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4964   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4965   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4966   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4967   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4968   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4969   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4970   PetscFunctionReturn(PETSC_SUCCESS);
4971 }
4972 
4973 /*@
4974   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4975 
4976   Logically Collective
4977 
4978   Input Parameter:
4979 . mat - the matrix
4980 
4981   Output Parameter:
4982 . v - the diagonal of the matrix
4983 
4984   Level: intermediate
4985 
4986   Note:
4987   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4988   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4989   is larger than `ndiag`, the values of the remaining entries are unspecified.
4990 
4991   Currently only correct in parallel for square matrices.
4992 
4993 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4994 @*/
4995 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4996 {
4997   PetscFunctionBegin;
4998   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4999   PetscValidType(mat, 1);
5000   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5001   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5002   MatCheckPreallocated(mat, 1);
5003   if (PetscDefined(USE_DEBUG)) {
5004     PetscInt nv, row, col, ndiag;
5005 
5006     PetscCall(VecGetLocalSize(v, &nv));
5007     PetscCall(MatGetLocalSize(mat, &row, &col));
5008     ndiag = PetscMin(row, col);
5009     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);
5010   }
5011 
5012   PetscUseTypeMethod(mat, getdiagonal, v);
5013   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5014   PetscFunctionReturn(PETSC_SUCCESS);
5015 }
5016 
5017 /*@
5018   MatGetRowMin - Gets the minimum value (of the real part) of each
5019   row of the matrix
5020 
5021   Logically Collective
5022 
5023   Input Parameter:
5024 . mat - the matrix
5025 
5026   Output Parameters:
5027 + v   - the vector for storing the maximums
5028 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5029 
5030   Level: intermediate
5031 
5032   Note:
5033   The result of this call are the same as if one converted the matrix to dense format
5034   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5035 
5036   This code is only implemented for a couple of matrix formats.
5037 
5038 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5039           `MatGetRowMax()`
5040 @*/
5041 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5042 {
5043   PetscFunctionBegin;
5044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5045   PetscValidType(mat, 1);
5046   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5047   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5048 
5049   if (!mat->cmap->N) {
5050     PetscCall(VecSet(v, PETSC_MAX_REAL));
5051     if (idx) {
5052       PetscInt i, m = mat->rmap->n;
5053       for (i = 0; i < m; i++) idx[i] = -1;
5054     }
5055   } else {
5056     MatCheckPreallocated(mat, 1);
5057   }
5058   PetscUseTypeMethod(mat, getrowmin, v, idx);
5059   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5060   PetscFunctionReturn(PETSC_SUCCESS);
5061 }
5062 
5063 /*@
5064   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5065   row of the matrix
5066 
5067   Logically Collective
5068 
5069   Input Parameter:
5070 . mat - the matrix
5071 
5072   Output Parameters:
5073 + v   - the vector for storing the minimums
5074 - idx - the indices of the column found for each row (or `NULL` if not needed)
5075 
5076   Level: intermediate
5077 
5078   Notes:
5079   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5080   row is 0 (the first column).
5081 
5082   This code is only implemented for a couple of matrix formats.
5083 
5084 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5085 @*/
5086 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5087 {
5088   PetscFunctionBegin;
5089   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5090   PetscValidType(mat, 1);
5091   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5092   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5093   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5094 
5095   if (!mat->cmap->N) {
5096     PetscCall(VecSet(v, 0.0));
5097     if (idx) {
5098       PetscInt i, m = mat->rmap->n;
5099       for (i = 0; i < m; i++) idx[i] = -1;
5100     }
5101   } else {
5102     MatCheckPreallocated(mat, 1);
5103     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5104     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5105   }
5106   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5107   PetscFunctionReturn(PETSC_SUCCESS);
5108 }
5109 
5110 /*@
5111   MatGetRowMax - Gets the maximum value (of the real part) of each
5112   row of the matrix
5113 
5114   Logically Collective
5115 
5116   Input Parameter:
5117 . mat - the matrix
5118 
5119   Output Parameters:
5120 + v   - the vector for storing the maximums
5121 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5122 
5123   Level: intermediate
5124 
5125   Notes:
5126   The result of this call are the same as if one converted the matrix to dense format
5127   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5128 
5129   This code is only implemented for a couple of matrix formats.
5130 
5131 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5132 @*/
5133 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5134 {
5135   PetscFunctionBegin;
5136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5137   PetscValidType(mat, 1);
5138   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5139   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5140 
5141   if (!mat->cmap->N) {
5142     PetscCall(VecSet(v, PETSC_MIN_REAL));
5143     if (idx) {
5144       PetscInt i, m = mat->rmap->n;
5145       for (i = 0; i < m; i++) idx[i] = -1;
5146     }
5147   } else {
5148     MatCheckPreallocated(mat, 1);
5149     PetscUseTypeMethod(mat, getrowmax, v, idx);
5150   }
5151   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5152   PetscFunctionReturn(PETSC_SUCCESS);
5153 }
5154 
5155 /*@
5156   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5157   row of the matrix
5158 
5159   Logically Collective
5160 
5161   Input Parameter:
5162 . mat - the matrix
5163 
5164   Output Parameters:
5165 + v   - the vector for storing the maximums
5166 - idx - the indices of the column found for each row (or `NULL` if not needed)
5167 
5168   Level: intermediate
5169 
5170   Notes:
5171   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5172   row is 0 (the first column).
5173 
5174   This code is only implemented for a couple of matrix formats.
5175 
5176 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5177 @*/
5178 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5179 {
5180   PetscFunctionBegin;
5181   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5182   PetscValidType(mat, 1);
5183   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5184   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5185 
5186   if (!mat->cmap->N) {
5187     PetscCall(VecSet(v, 0.0));
5188     if (idx) {
5189       PetscInt i, m = mat->rmap->n;
5190       for (i = 0; i < m; i++) idx[i] = -1;
5191     }
5192   } else {
5193     MatCheckPreallocated(mat, 1);
5194     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5195     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5196   }
5197   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5198   PetscFunctionReturn(PETSC_SUCCESS);
5199 }
5200 
5201 /*@
5202   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5203 
5204   Logically Collective
5205 
5206   Input Parameter:
5207 . mat - the matrix
5208 
5209   Output Parameter:
5210 . v - the vector for storing the sum
5211 
5212   Level: intermediate
5213 
5214   This code is only implemented for a couple of matrix formats.
5215 
5216 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5217 @*/
5218 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5219 {
5220   PetscFunctionBegin;
5221   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5222   PetscValidType(mat, 1);
5223   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5224   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5225 
5226   if (!mat->cmap->N) {
5227     PetscCall(VecSet(v, 0.0));
5228   } else {
5229     MatCheckPreallocated(mat, 1);
5230     PetscUseTypeMethod(mat, getrowsumabs, v);
5231   }
5232   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5233   PetscFunctionReturn(PETSC_SUCCESS);
5234 }
5235 
5236 /*@
5237   MatGetRowSum - Gets the sum of each row of the matrix
5238 
5239   Logically or Neighborhood Collective
5240 
5241   Input Parameter:
5242 . mat - the matrix
5243 
5244   Output Parameter:
5245 . v - the vector for storing the sum of rows
5246 
5247   Level: intermediate
5248 
5249   Note:
5250   This code is slow since it is not currently specialized for different formats
5251 
5252 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5253 @*/
5254 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5255 {
5256   Vec ones;
5257 
5258   PetscFunctionBegin;
5259   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5260   PetscValidType(mat, 1);
5261   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5262   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5263   MatCheckPreallocated(mat, 1);
5264   PetscCall(MatCreateVecs(mat, &ones, NULL));
5265   PetscCall(VecSet(ones, 1.));
5266   PetscCall(MatMult(mat, ones, v));
5267   PetscCall(VecDestroy(&ones));
5268   PetscFunctionReturn(PETSC_SUCCESS);
5269 }
5270 
5271 /*@
5272   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5273   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5274 
5275   Collective
5276 
5277   Input Parameter:
5278 . mat - the matrix to provide the transpose
5279 
5280   Output Parameter:
5281 . 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
5282 
5283   Level: advanced
5284 
5285   Note:
5286   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
5287   routine allows bypassing that call.
5288 
5289 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5290 @*/
5291 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5292 {
5293   PetscContainer  rB = NULL;
5294   MatParentState *rb = NULL;
5295 
5296   PetscFunctionBegin;
5297   PetscCall(PetscNew(&rb));
5298   rb->id    = ((PetscObject)mat)->id;
5299   rb->state = 0;
5300   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5301   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5302   PetscCall(PetscContainerSetPointer(rB, rb));
5303   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5304   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5305   PetscCall(PetscObjectDereference((PetscObject)rB));
5306   PetscFunctionReturn(PETSC_SUCCESS);
5307 }
5308 
5309 /*@
5310   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5311 
5312   Collective
5313 
5314   Input Parameters:
5315 + mat   - the matrix to transpose
5316 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5317 
5318   Output Parameter:
5319 . B - the transpose
5320 
5321   Level: intermediate
5322 
5323   Notes:
5324   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5325 
5326   `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
5327   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5328 
5329   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.
5330 
5331   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5332 
5333   If mat is unchanged from the last call this function returns immediately without recomputing the result
5334 
5335   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5336 
5337 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5338           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5339 @*/
5340 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5341 {
5342   PetscContainer  rB = NULL;
5343   MatParentState *rb = NULL;
5344 
5345   PetscFunctionBegin;
5346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5347   PetscValidType(mat, 1);
5348   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5349   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5350   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5351   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5352   MatCheckPreallocated(mat, 1);
5353   if (reuse == MAT_REUSE_MATRIX) {
5354     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5355     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5356     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5357     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5358     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5359   }
5360 
5361   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5362   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5363     PetscUseTypeMethod(mat, transpose, reuse, B);
5364     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5365   }
5366   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5367 
5368   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5369   if (reuse != MAT_INPLACE_MATRIX) {
5370     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5371     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5372     rb->state        = ((PetscObject)mat)->state;
5373     rb->nonzerostate = mat->nonzerostate;
5374   }
5375   PetscFunctionReturn(PETSC_SUCCESS);
5376 }
5377 
5378 /*@
5379   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5380 
5381   Collective
5382 
5383   Input Parameter:
5384 . A - the matrix to transpose
5385 
5386   Output Parameter:
5387 . 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
5388       numerical portion.
5389 
5390   Level: intermediate
5391 
5392   Note:
5393   This is not supported for many matrix types, use `MatTranspose()` in those cases
5394 
5395 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5396 @*/
5397 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5398 {
5399   PetscFunctionBegin;
5400   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5401   PetscValidType(A, 1);
5402   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5403   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5404   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5405   PetscUseTypeMethod(A, transposesymbolic, B);
5406   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5407 
5408   PetscCall(MatTransposeSetPrecursor(A, *B));
5409   PetscFunctionReturn(PETSC_SUCCESS);
5410 }
5411 
5412 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5413 {
5414   PetscContainer  rB;
5415   MatParentState *rb;
5416 
5417   PetscFunctionBegin;
5418   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5419   PetscValidType(A, 1);
5420   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5421   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5422   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5423   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5424   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5425   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5426   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5427   PetscFunctionReturn(PETSC_SUCCESS);
5428 }
5429 
5430 /*@
5431   MatIsTranspose - Test whether a matrix is another one's transpose,
5432   or its own, in which case it tests symmetry.
5433 
5434   Collective
5435 
5436   Input Parameters:
5437 + A   - the matrix to test
5438 . B   - the matrix to test against, this can equal the first parameter
5439 - tol - tolerance, differences between entries smaller than this are counted as zero
5440 
5441   Output Parameter:
5442 . flg - the result
5443 
5444   Level: intermediate
5445 
5446   Notes:
5447   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5448   test involves parallel copies of the block off-diagonal parts of the matrix.
5449 
5450 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5451 @*/
5452 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5453 {
5454   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5455 
5456   PetscFunctionBegin;
5457   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5458   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5459   PetscAssertPointer(flg, 4);
5460   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5461   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5462   *flg = PETSC_FALSE;
5463   if (f && g) {
5464     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5465     PetscCall((*f)(A, B, tol, flg));
5466   } else {
5467     MatType mattype;
5468 
5469     PetscCall(MatGetType(f ? B : A, &mattype));
5470     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5471   }
5472   PetscFunctionReturn(PETSC_SUCCESS);
5473 }
5474 
5475 /*@
5476   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5477 
5478   Collective
5479 
5480   Input Parameters:
5481 + mat   - the matrix to transpose and complex conjugate
5482 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5483 
5484   Output Parameter:
5485 . B - the Hermitian transpose
5486 
5487   Level: intermediate
5488 
5489 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5490 @*/
5491 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5492 {
5493   PetscFunctionBegin;
5494   PetscCall(MatTranspose(mat, reuse, B));
5495 #if defined(PETSC_USE_COMPLEX)
5496   PetscCall(MatConjugate(*B));
5497 #endif
5498   PetscFunctionReturn(PETSC_SUCCESS);
5499 }
5500 
5501 /*@
5502   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5503 
5504   Collective
5505 
5506   Input Parameters:
5507 + A   - the matrix to test
5508 . B   - the matrix to test against, this can equal the first parameter
5509 - tol - tolerance, differences between entries smaller than this are counted as zero
5510 
5511   Output Parameter:
5512 . flg - the result
5513 
5514   Level: intermediate
5515 
5516   Notes:
5517   Only available for `MATAIJ` matrices.
5518 
5519   The sequential algorithm
5520   has a running time of the order of the number of nonzeros; the parallel
5521   test involves parallel copies of the block off-diagonal parts of the matrix.
5522 
5523 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5524 @*/
5525 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5526 {
5527   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5528 
5529   PetscFunctionBegin;
5530   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5531   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5532   PetscAssertPointer(flg, 4);
5533   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5534   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5535   if (f && g) {
5536     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5537     PetscCall((*f)(A, B, tol, flg));
5538   }
5539   PetscFunctionReturn(PETSC_SUCCESS);
5540 }
5541 
5542 /*@
5543   MatPermute - Creates a new matrix with rows and columns permuted from the
5544   original.
5545 
5546   Collective
5547 
5548   Input Parameters:
5549 + mat - the matrix to permute
5550 . row - row permutation, each processor supplies only the permutation for its rows
5551 - col - column permutation, each processor supplies only the permutation for its columns
5552 
5553   Output Parameter:
5554 . B - the permuted matrix
5555 
5556   Level: advanced
5557 
5558   Note:
5559   The index sets map from row/col of permuted matrix to row/col of original matrix.
5560   The index sets should be on the same communicator as mat and have the same local sizes.
5561 
5562   Developer Note:
5563   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5564   exploit the fact that row and col are permutations, consider implementing the
5565   more general `MatCreateSubMatrix()` instead.
5566 
5567 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5568 @*/
5569 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5570 {
5571   PetscFunctionBegin;
5572   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5573   PetscValidType(mat, 1);
5574   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5575   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5576   PetscAssertPointer(B, 4);
5577   PetscCheckSameComm(mat, 1, row, 2);
5578   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5579   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5580   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5581   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5582   MatCheckPreallocated(mat, 1);
5583 
5584   if (mat->ops->permute) {
5585     PetscUseTypeMethod(mat, permute, row, col, B);
5586     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5587   } else {
5588     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5589   }
5590   PetscFunctionReturn(PETSC_SUCCESS);
5591 }
5592 
5593 /*@
5594   MatEqual - Compares two matrices.
5595 
5596   Collective
5597 
5598   Input Parameters:
5599 + A - the first matrix
5600 - B - the second matrix
5601 
5602   Output Parameter:
5603 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5604 
5605   Level: intermediate
5606 
5607 .seealso: [](ch_matrices), `Mat`
5608 @*/
5609 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5610 {
5611   PetscFunctionBegin;
5612   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5613   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5614   PetscValidType(A, 1);
5615   PetscValidType(B, 2);
5616   PetscAssertPointer(flg, 3);
5617   PetscCheckSameComm(A, 1, B, 2);
5618   MatCheckPreallocated(A, 1);
5619   MatCheckPreallocated(B, 2);
5620   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5621   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5622   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,
5623              B->cmap->N);
5624   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5625     PetscUseTypeMethod(A, equal, B, flg);
5626   } else {
5627     PetscCall(MatMultEqual(A, B, 10, flg));
5628   }
5629   PetscFunctionReturn(PETSC_SUCCESS);
5630 }
5631 
5632 /*@
5633   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5634   matrices that are stored as vectors.  Either of the two scaling
5635   matrices can be `NULL`.
5636 
5637   Collective
5638 
5639   Input Parameters:
5640 + mat - the matrix to be scaled
5641 . l   - the left scaling vector (or `NULL`)
5642 - r   - the right scaling vector (or `NULL`)
5643 
5644   Level: intermediate
5645 
5646   Note:
5647   `MatDiagonalScale()` computes $A = LAR$, where
5648   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5649   The L scales the rows of the matrix, the R scales the columns of the matrix.
5650 
5651 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5652 @*/
5653 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5654 {
5655   PetscFunctionBegin;
5656   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5657   PetscValidType(mat, 1);
5658   if (l) {
5659     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5660     PetscCheckSameComm(mat, 1, l, 2);
5661   }
5662   if (r) {
5663     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5664     PetscCheckSameComm(mat, 1, r, 3);
5665   }
5666   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5667   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5668   MatCheckPreallocated(mat, 1);
5669   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5670 
5671   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5672   PetscUseTypeMethod(mat, diagonalscale, l, r);
5673   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5674   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5675   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5676   PetscFunctionReturn(PETSC_SUCCESS);
5677 }
5678 
5679 /*@
5680   MatScale - Scales all elements of a matrix by a given number.
5681 
5682   Logically Collective
5683 
5684   Input Parameters:
5685 + mat - the matrix to be scaled
5686 - a   - the scaling value
5687 
5688   Level: intermediate
5689 
5690 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5691 @*/
5692 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5693 {
5694   PetscFunctionBegin;
5695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5696   PetscValidType(mat, 1);
5697   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5698   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5699   PetscValidLogicalCollectiveScalar(mat, a, 2);
5700   MatCheckPreallocated(mat, 1);
5701 
5702   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5703   if (a != (PetscScalar)1.0) {
5704     PetscUseTypeMethod(mat, scale, a);
5705     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5706   }
5707   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5708   PetscFunctionReturn(PETSC_SUCCESS);
5709 }
5710 
5711 /*@
5712   MatNorm - Calculates various norms of a matrix.
5713 
5714   Collective
5715 
5716   Input Parameters:
5717 + mat  - the matrix
5718 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5719 
5720   Output Parameter:
5721 . nrm - the resulting norm
5722 
5723   Level: intermediate
5724 
5725 .seealso: [](ch_matrices), `Mat`
5726 @*/
5727 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5728 {
5729   PetscFunctionBegin;
5730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5731   PetscValidType(mat, 1);
5732   PetscAssertPointer(nrm, 3);
5733 
5734   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5735   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5736   MatCheckPreallocated(mat, 1);
5737 
5738   PetscUseTypeMethod(mat, norm, type, nrm);
5739   PetscFunctionReturn(PETSC_SUCCESS);
5740 }
5741 
5742 /*
5743      This variable is used to prevent counting of MatAssemblyBegin() that
5744    are called from within a MatAssemblyEnd().
5745 */
5746 static PetscInt MatAssemblyEnd_InUse = 0;
5747 /*@
5748   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5749   be called after completing all calls to `MatSetValues()`.
5750 
5751   Collective
5752 
5753   Input Parameters:
5754 + mat  - the matrix
5755 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5756 
5757   Level: beginner
5758 
5759   Notes:
5760   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5761   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5762 
5763   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5764   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5765   using the matrix.
5766 
5767   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5768   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
5769   a global collective operation requiring all processes that share the matrix.
5770 
5771   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5772   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5773   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5774 
5775 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5776 @*/
5777 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5778 {
5779   PetscFunctionBegin;
5780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5781   PetscValidType(mat, 1);
5782   MatCheckPreallocated(mat, 1);
5783   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5784   if (mat->assembled) {
5785     mat->was_assembled = PETSC_TRUE;
5786     mat->assembled     = PETSC_FALSE;
5787   }
5788 
5789   if (!MatAssemblyEnd_InUse) {
5790     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5791     PetscTryTypeMethod(mat, assemblybegin, type);
5792     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5793   } else PetscTryTypeMethod(mat, assemblybegin, type);
5794   PetscFunctionReturn(PETSC_SUCCESS);
5795 }
5796 
5797 /*@
5798   MatAssembled - Indicates if a matrix has been assembled and is ready for
5799   use; for example, in matrix-vector product.
5800 
5801   Not Collective
5802 
5803   Input Parameter:
5804 . mat - the matrix
5805 
5806   Output Parameter:
5807 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5808 
5809   Level: advanced
5810 
5811 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5812 @*/
5813 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5814 {
5815   PetscFunctionBegin;
5816   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5817   PetscAssertPointer(assembled, 2);
5818   *assembled = mat->assembled;
5819   PetscFunctionReturn(PETSC_SUCCESS);
5820 }
5821 
5822 /*@
5823   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5824   be called after `MatAssemblyBegin()`.
5825 
5826   Collective
5827 
5828   Input Parameters:
5829 + mat  - the matrix
5830 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5831 
5832   Options Database Keys:
5833 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5834 . -mat_view ::ascii_info_detail      - Prints more detailed info
5835 . -mat_view                          - Prints matrix in ASCII format
5836 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5837 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5838 . -display <name>                    - Sets display name (default is host)
5839 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5840 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5841 . -viewer_socket_machine <machine>   - Machine to use for socket
5842 . -viewer_socket_port <port>         - Port number to use for socket
5843 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5844 
5845   Level: beginner
5846 
5847 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5848 @*/
5849 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5850 {
5851   static PetscInt inassm = 0;
5852   PetscBool       flg    = PETSC_FALSE;
5853 
5854   PetscFunctionBegin;
5855   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5856   PetscValidType(mat, 1);
5857 
5858   inassm++;
5859   MatAssemblyEnd_InUse++;
5860   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5861     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5862     PetscTryTypeMethod(mat, assemblyend, type);
5863     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5864   } else PetscTryTypeMethod(mat, assemblyend, type);
5865 
5866   /* Flush assembly is not a true assembly */
5867   if (type != MAT_FLUSH_ASSEMBLY) {
5868     if (mat->num_ass) {
5869       if (!mat->symmetry_eternal) {
5870         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5871         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5872       }
5873       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5874       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5875     }
5876     mat->num_ass++;
5877     mat->assembled        = PETSC_TRUE;
5878     mat->ass_nonzerostate = mat->nonzerostate;
5879   }
5880 
5881   mat->insertmode = NOT_SET_VALUES;
5882   MatAssemblyEnd_InUse--;
5883   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5884   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5885     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5886 
5887     if (mat->checksymmetryonassembly) {
5888       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5889       if (flg) {
5890         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5891       } else {
5892         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5893       }
5894     }
5895     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5896   }
5897   inassm--;
5898   PetscFunctionReturn(PETSC_SUCCESS);
5899 }
5900 
5901 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5902 /*@
5903   MatSetOption - Sets a parameter option for a matrix. Some options
5904   may be specific to certain storage formats.  Some options
5905   determine how values will be inserted (or added). Sorted,
5906   row-oriented input will generally assemble the fastest. The default
5907   is row-oriented.
5908 
5909   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5910 
5911   Input Parameters:
5912 + mat - the matrix
5913 . op  - the option, one of those listed below (and possibly others),
5914 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5915 
5916   Options Describing Matrix Structure:
5917 + `MAT_SPD`                         - symmetric positive definite
5918 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5919 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5920 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5921 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5922 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5923 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5924 
5925    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5926    do not need to be computed (usually at a high cost)
5927 
5928    Options For Use with `MatSetValues()`:
5929    Insert a logically dense subblock, which can be
5930 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5931 
5932    These options reflect the data you pass in with `MatSetValues()`; it has
5933    nothing to do with how the data is stored internally in the matrix
5934    data structure.
5935 
5936    When (re)assembling a matrix, we can restrict the input for
5937    efficiency/debugging purposes.  These options include
5938 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5939 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5940 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5941 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5942 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5943 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5944         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5945         performance for very large process counts.
5946 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5947         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5948         functions, instead sending only neighbor messages.
5949 
5950   Level: intermediate
5951 
5952   Notes:
5953   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5954 
5955   Some options are relevant only for particular matrix types and
5956   are thus ignored by others.  Other options are not supported by
5957   certain matrix types and will generate an error message if set.
5958 
5959   If using Fortran to compute a matrix, one may need to
5960   use the column-oriented option (or convert to the row-oriented
5961   format).
5962 
5963   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5964   that would generate a new entry in the nonzero structure is instead
5965   ignored.  Thus, if memory has not already been allocated for this particular
5966   data, then the insertion is ignored. For dense matrices, in which
5967   the entire array is allocated, no entries are ever ignored.
5968   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5969 
5970   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5971   that would generate a new entry in the nonzero structure instead produces
5972   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
5973 
5974   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5975   that would generate a new entry that has not been preallocated will
5976   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5977   only.) This is a useful flag when debugging matrix memory preallocation.
5978   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5979 
5980   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5981   other processors should be dropped, rather than stashed.
5982   This is useful if you know that the "owning" processor is also
5983   always generating the correct matrix entries, so that PETSc need
5984   not transfer duplicate entries generated on another processor.
5985 
5986   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5987   searches during matrix assembly. When this flag is set, the hash table
5988   is created during the first matrix assembly. This hash table is
5989   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5990   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5991   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5992   supported by `MATMPIBAIJ` format only.
5993 
5994   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5995   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
5996 
5997   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5998   a zero location in the matrix
5999 
6000   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6001 
6002   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6003   zero row routines and thus improves performance for very large process counts.
6004 
6005   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6006   part of the matrix (since they should match the upper triangular part).
6007 
6008   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6009   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6010   with finite difference schemes with non-periodic boundary conditions.
6011 
6012   Developer Note:
6013   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6014   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6015   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6016   not changed.
6017 
6018 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6019 @*/
6020 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6021 {
6022   PetscFunctionBegin;
6023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6024   if (op > 0) {
6025     PetscValidLogicalCollectiveEnum(mat, op, 2);
6026     PetscValidLogicalCollectiveBool(mat, flg, 3);
6027   }
6028 
6029   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);
6030 
6031   switch (op) {
6032   case MAT_FORCE_DIAGONAL_ENTRIES:
6033     mat->force_diagonals = flg;
6034     PetscFunctionReturn(PETSC_SUCCESS);
6035   case MAT_NO_OFF_PROC_ENTRIES:
6036     mat->nooffprocentries = flg;
6037     PetscFunctionReturn(PETSC_SUCCESS);
6038   case MAT_SUBSET_OFF_PROC_ENTRIES:
6039     mat->assembly_subset = flg;
6040     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6041 #if !defined(PETSC_HAVE_MPIUNI)
6042       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6043 #endif
6044       mat->stash.first_assembly_done = PETSC_FALSE;
6045     }
6046     PetscFunctionReturn(PETSC_SUCCESS);
6047   case MAT_NO_OFF_PROC_ZERO_ROWS:
6048     mat->nooffproczerorows = flg;
6049     PetscFunctionReturn(PETSC_SUCCESS);
6050   case MAT_SPD:
6051     if (flg) {
6052       mat->spd                    = PETSC_BOOL3_TRUE;
6053       mat->symmetric              = PETSC_BOOL3_TRUE;
6054       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6055     } else {
6056       mat->spd = PETSC_BOOL3_FALSE;
6057     }
6058     break;
6059   case MAT_SYMMETRIC:
6060     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6061     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6062 #if !defined(PETSC_USE_COMPLEX)
6063     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6064 #endif
6065     break;
6066   case MAT_HERMITIAN:
6067     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6068     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6069 #if !defined(PETSC_USE_COMPLEX)
6070     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6071 #endif
6072     break;
6073   case MAT_STRUCTURALLY_SYMMETRIC:
6074     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6075     break;
6076   case MAT_SYMMETRY_ETERNAL:
6077     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");
6078     mat->symmetry_eternal = flg;
6079     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6080     break;
6081   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6082     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");
6083     mat->structural_symmetry_eternal = flg;
6084     break;
6085   case MAT_SPD_ETERNAL:
6086     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");
6087     mat->spd_eternal = flg;
6088     if (flg) {
6089       mat->structural_symmetry_eternal = PETSC_TRUE;
6090       mat->symmetry_eternal            = PETSC_TRUE;
6091     }
6092     break;
6093   case MAT_STRUCTURE_ONLY:
6094     mat->structure_only = flg;
6095     break;
6096   case MAT_SORTED_FULL:
6097     mat->sortedfull = flg;
6098     break;
6099   default:
6100     break;
6101   }
6102   PetscTryTypeMethod(mat, setoption, op, flg);
6103   PetscFunctionReturn(PETSC_SUCCESS);
6104 }
6105 
6106 /*@
6107   MatGetOption - Gets a parameter option that has been set for a matrix.
6108 
6109   Logically Collective
6110 
6111   Input Parameters:
6112 + mat - the matrix
6113 - op  - the option, this only responds to certain options, check the code for which ones
6114 
6115   Output Parameter:
6116 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6117 
6118   Level: intermediate
6119 
6120   Notes:
6121   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6122 
6123   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6124   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6125 
6126 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6127     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6128 @*/
6129 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6130 {
6131   PetscFunctionBegin;
6132   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6133   PetscValidType(mat, 1);
6134 
6135   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);
6136   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()");
6137 
6138   switch (op) {
6139   case MAT_NO_OFF_PROC_ENTRIES:
6140     *flg = mat->nooffprocentries;
6141     break;
6142   case MAT_NO_OFF_PROC_ZERO_ROWS:
6143     *flg = mat->nooffproczerorows;
6144     break;
6145   case MAT_SYMMETRIC:
6146     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6147     break;
6148   case MAT_HERMITIAN:
6149     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6150     break;
6151   case MAT_STRUCTURALLY_SYMMETRIC:
6152     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6153     break;
6154   case MAT_SPD:
6155     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6156     break;
6157   case MAT_SYMMETRY_ETERNAL:
6158     *flg = mat->symmetry_eternal;
6159     break;
6160   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6161     *flg = mat->symmetry_eternal;
6162     break;
6163   default:
6164     break;
6165   }
6166   PetscFunctionReturn(PETSC_SUCCESS);
6167 }
6168 
6169 /*@
6170   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6171   this routine retains the old nonzero structure.
6172 
6173   Logically Collective
6174 
6175   Input Parameter:
6176 . mat - the matrix
6177 
6178   Level: intermediate
6179 
6180   Note:
6181   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.
6182   See the Performance chapter of the users manual for information on preallocating matrices.
6183 
6184 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6185 @*/
6186 PetscErrorCode MatZeroEntries(Mat mat)
6187 {
6188   PetscFunctionBegin;
6189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6190   PetscValidType(mat, 1);
6191   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6192   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");
6193   MatCheckPreallocated(mat, 1);
6194 
6195   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6196   PetscUseTypeMethod(mat, zeroentries);
6197   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6198   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6199   PetscFunctionReturn(PETSC_SUCCESS);
6200 }
6201 
6202 /*@
6203   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6204   of a set of rows and columns of a matrix.
6205 
6206   Collective
6207 
6208   Input Parameters:
6209 + mat     - the matrix
6210 . numRows - the number of rows/columns to zero
6211 . rows    - the global row indices
6212 . diag    - value put in the diagonal of the eliminated rows
6213 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6214 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6215 
6216   Level: intermediate
6217 
6218   Notes:
6219   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6220 
6221   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6222   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
6223 
6224   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6225   Krylov method to take advantage of the known solution on the zeroed rows.
6226 
6227   For the parallel case, all processes that share the matrix (i.e.,
6228   those in the communicator used for matrix creation) MUST call this
6229   routine, regardless of whether any rows being zeroed are owned by
6230   them.
6231 
6232   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6233   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
6234   missing.
6235 
6236   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6237   list only rows local to itself).
6238 
6239   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6240 
6241 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6242           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6243 @*/
6244 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6245 {
6246   PetscFunctionBegin;
6247   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6248   PetscValidType(mat, 1);
6249   if (numRows) PetscAssertPointer(rows, 3);
6250   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6251   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6252   MatCheckPreallocated(mat, 1);
6253 
6254   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6255   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6256   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6257   PetscFunctionReturn(PETSC_SUCCESS);
6258 }
6259 
6260 /*@
6261   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6262   of a set of rows and columns of a matrix.
6263 
6264   Collective
6265 
6266   Input Parameters:
6267 + mat  - the matrix
6268 . is   - the rows to zero
6269 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6270 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6271 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6272 
6273   Level: intermediate
6274 
6275   Note:
6276   See `MatZeroRowsColumns()` for details on how this routine operates.
6277 
6278 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6279           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6280 @*/
6281 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6282 {
6283   PetscInt        numRows;
6284   const PetscInt *rows;
6285 
6286   PetscFunctionBegin;
6287   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6288   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6289   PetscValidType(mat, 1);
6290   PetscValidType(is, 2);
6291   PetscCall(ISGetLocalSize(is, &numRows));
6292   PetscCall(ISGetIndices(is, &rows));
6293   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6294   PetscCall(ISRestoreIndices(is, &rows));
6295   PetscFunctionReturn(PETSC_SUCCESS);
6296 }
6297 
6298 /*@
6299   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6300   of a set of rows of a matrix.
6301 
6302   Collective
6303 
6304   Input Parameters:
6305 + mat     - the matrix
6306 . numRows - the number of rows to zero
6307 . rows    - the global row indices
6308 . diag    - value put in the diagonal of the zeroed rows
6309 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6310 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6311 
6312   Level: intermediate
6313 
6314   Notes:
6315   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6316 
6317   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6318 
6319   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6320   Krylov method to take advantage of the known solution on the zeroed rows.
6321 
6322   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)
6323   from the matrix.
6324 
6325   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6326   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
6327   formats this does not alter the nonzero structure.
6328 
6329   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6330   of the matrix is not changed the values are
6331   merely zeroed.
6332 
6333   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6334   formats can optionally remove the main diagonal entry from the
6335   nonzero structure as well, by passing 0.0 as the final argument).
6336 
6337   For the parallel case, all processes that share the matrix (i.e.,
6338   those in the communicator used for matrix creation) MUST call this
6339   routine, regardless of whether any rows being zeroed are owned by
6340   them.
6341 
6342   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6343   list only rows local to itself).
6344 
6345   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6346   owns that are to be zeroed. This saves a global synchronization in the implementation.
6347 
6348 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6349           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6350 @*/
6351 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6352 {
6353   PetscFunctionBegin;
6354   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6355   PetscValidType(mat, 1);
6356   if (numRows) PetscAssertPointer(rows, 3);
6357   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6358   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6359   MatCheckPreallocated(mat, 1);
6360 
6361   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6362   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6363   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6364   PetscFunctionReturn(PETSC_SUCCESS);
6365 }
6366 
6367 /*@
6368   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6369   of a set of rows of a matrix.
6370 
6371   Collective
6372 
6373   Input Parameters:
6374 + mat  - the matrix
6375 . is   - index set of rows to remove (if `NULL` then no row is removed)
6376 . diag - value put in all diagonals of eliminated rows
6377 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6378 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6379 
6380   Level: intermediate
6381 
6382   Note:
6383   See `MatZeroRows()` for details on how this routine operates.
6384 
6385 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6386           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6387 @*/
6388 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6389 {
6390   PetscInt        numRows = 0;
6391   const PetscInt *rows    = NULL;
6392 
6393   PetscFunctionBegin;
6394   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6395   PetscValidType(mat, 1);
6396   if (is) {
6397     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6398     PetscCall(ISGetLocalSize(is, &numRows));
6399     PetscCall(ISGetIndices(is, &rows));
6400   }
6401   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6402   if (is) PetscCall(ISRestoreIndices(is, &rows));
6403   PetscFunctionReturn(PETSC_SUCCESS);
6404 }
6405 
6406 /*@
6407   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6408   of a set of rows of a matrix. These rows must be local to the process.
6409 
6410   Collective
6411 
6412   Input Parameters:
6413 + mat     - the matrix
6414 . numRows - the number of rows to remove
6415 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6416 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6417 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6418 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6419 
6420   Level: intermediate
6421 
6422   Notes:
6423   See `MatZeroRows()` for details on how this routine operates.
6424 
6425   The grid coordinates are across the entire grid, not just the local portion
6426 
6427   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6428   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6429   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6430   `DM_BOUNDARY_PERIODIC` boundary type.
6431 
6432   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
6433   a single value per point) you can skip filling those indices.
6434 
6435   Fortran Note:
6436   `idxm` and `idxn` should be declared as
6437 $     MatStencil idxm(4, m)
6438   and the values inserted using
6439 .vb
6440     idxm(MatStencil_i, 1) = i
6441     idxm(MatStencil_j, 1) = j
6442     idxm(MatStencil_k, 1) = k
6443     idxm(MatStencil_c, 1) = c
6444    etc
6445 .ve
6446 
6447 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6448           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6449 @*/
6450 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6451 {
6452   PetscInt  dim    = mat->stencil.dim;
6453   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6454   PetscInt *dims   = mat->stencil.dims + 1;
6455   PetscInt *starts = mat->stencil.starts;
6456   PetscInt *dxm    = (PetscInt *)rows;
6457   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6458 
6459   PetscFunctionBegin;
6460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6461   PetscValidType(mat, 1);
6462   if (numRows) PetscAssertPointer(rows, 3);
6463 
6464   PetscCall(PetscMalloc1(numRows, &jdxm));
6465   for (i = 0; i < numRows; ++i) {
6466     /* Skip unused dimensions (they are ordered k, j, i, c) */
6467     for (j = 0; j < 3 - sdim; ++j) dxm++;
6468     /* Local index in X dir */
6469     tmp = *dxm++ - starts[0];
6470     /* Loop over remaining dimensions */
6471     for (j = 0; j < dim - 1; ++j) {
6472       /* If nonlocal, set index to be negative */
6473       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6474       /* Update local index */
6475       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6476     }
6477     /* Skip component slot if necessary */
6478     if (mat->stencil.noc) dxm++;
6479     /* Local row number */
6480     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6481   }
6482   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6483   PetscCall(PetscFree(jdxm));
6484   PetscFunctionReturn(PETSC_SUCCESS);
6485 }
6486 
6487 /*@
6488   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6489   of a set of rows and columns of a matrix.
6490 
6491   Collective
6492 
6493   Input Parameters:
6494 + mat     - the matrix
6495 . numRows - the number of rows/columns to remove
6496 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6497 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6498 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6499 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6500 
6501   Level: intermediate
6502 
6503   Notes:
6504   See `MatZeroRowsColumns()` for details on how this routine operates.
6505 
6506   The grid coordinates are across the entire grid, not just the local portion
6507 
6508   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6509   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6510   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6511   `DM_BOUNDARY_PERIODIC` boundary type.
6512 
6513   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
6514   a single value per point) you can skip filling those indices.
6515 
6516   Fortran Note:
6517   `idxm` and `idxn` should be declared as
6518 $     MatStencil idxm(4, m)
6519   and the values inserted using
6520 .vb
6521     idxm(MatStencil_i, 1) = i
6522     idxm(MatStencil_j, 1) = j
6523     idxm(MatStencil_k, 1) = k
6524     idxm(MatStencil_c, 1) = c
6525     etc
6526 .ve
6527 
6528 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6529           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6530 @*/
6531 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6532 {
6533   PetscInt  dim    = mat->stencil.dim;
6534   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6535   PetscInt *dims   = mat->stencil.dims + 1;
6536   PetscInt *starts = mat->stencil.starts;
6537   PetscInt *dxm    = (PetscInt *)rows;
6538   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6539 
6540   PetscFunctionBegin;
6541   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6542   PetscValidType(mat, 1);
6543   if (numRows) PetscAssertPointer(rows, 3);
6544 
6545   PetscCall(PetscMalloc1(numRows, &jdxm));
6546   for (i = 0; i < numRows; ++i) {
6547     /* Skip unused dimensions (they are ordered k, j, i, c) */
6548     for (j = 0; j < 3 - sdim; ++j) dxm++;
6549     /* Local index in X dir */
6550     tmp = *dxm++ - starts[0];
6551     /* Loop over remaining dimensions */
6552     for (j = 0; j < dim - 1; ++j) {
6553       /* If nonlocal, set index to be negative */
6554       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6555       /* Update local index */
6556       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6557     }
6558     /* Skip component slot if necessary */
6559     if (mat->stencil.noc) dxm++;
6560     /* Local row number */
6561     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6562   }
6563   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6564   PetscCall(PetscFree(jdxm));
6565   PetscFunctionReturn(PETSC_SUCCESS);
6566 }
6567 
6568 /*@C
6569   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6570   of a set of rows of a matrix; using local numbering of rows.
6571 
6572   Collective
6573 
6574   Input Parameters:
6575 + mat     - the matrix
6576 . numRows - the number of rows to remove
6577 . rows    - the local row indices
6578 . diag    - value put in all diagonals of eliminated rows
6579 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6580 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6581 
6582   Level: intermediate
6583 
6584   Notes:
6585   Before calling `MatZeroRowsLocal()`, the user must first set the
6586   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6587 
6588   See `MatZeroRows()` for details on how this routine operates.
6589 
6590 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6591           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6592 @*/
6593 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6594 {
6595   PetscFunctionBegin;
6596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6597   PetscValidType(mat, 1);
6598   if (numRows) PetscAssertPointer(rows, 3);
6599   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6600   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6601   MatCheckPreallocated(mat, 1);
6602 
6603   if (mat->ops->zerorowslocal) {
6604     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6605   } else {
6606     IS              is, newis;
6607     const PetscInt *newRows;
6608 
6609     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6610     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6611     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6612     PetscCall(ISGetIndices(newis, &newRows));
6613     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6614     PetscCall(ISRestoreIndices(newis, &newRows));
6615     PetscCall(ISDestroy(&newis));
6616     PetscCall(ISDestroy(&is));
6617   }
6618   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6619   PetscFunctionReturn(PETSC_SUCCESS);
6620 }
6621 
6622 /*@
6623   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6624   of a set of rows of a matrix; using local numbering of rows.
6625 
6626   Collective
6627 
6628   Input Parameters:
6629 + mat  - the matrix
6630 . is   - index set of rows to remove
6631 . diag - value put in all diagonals of eliminated rows
6632 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6633 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6634 
6635   Level: intermediate
6636 
6637   Notes:
6638   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6639   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6640 
6641   See `MatZeroRows()` for details on how this routine operates.
6642 
6643 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6644           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6645 @*/
6646 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6647 {
6648   PetscInt        numRows;
6649   const PetscInt *rows;
6650 
6651   PetscFunctionBegin;
6652   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6653   PetscValidType(mat, 1);
6654   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6655   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6656   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6657   MatCheckPreallocated(mat, 1);
6658 
6659   PetscCall(ISGetLocalSize(is, &numRows));
6660   PetscCall(ISGetIndices(is, &rows));
6661   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6662   PetscCall(ISRestoreIndices(is, &rows));
6663   PetscFunctionReturn(PETSC_SUCCESS);
6664 }
6665 
6666 /*@
6667   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6668   of a set of rows and columns of a matrix; using local numbering of rows.
6669 
6670   Collective
6671 
6672   Input Parameters:
6673 + mat     - the matrix
6674 . numRows - the number of rows to remove
6675 . rows    - the global row indices
6676 . diag    - value put in all diagonals of eliminated rows
6677 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6678 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6679 
6680   Level: intermediate
6681 
6682   Notes:
6683   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6684   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6685 
6686   See `MatZeroRowsColumns()` for details on how this routine operates.
6687 
6688 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6689           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6690 @*/
6691 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6692 {
6693   IS              is, newis;
6694   const PetscInt *newRows;
6695 
6696   PetscFunctionBegin;
6697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6698   PetscValidType(mat, 1);
6699   if (numRows) PetscAssertPointer(rows, 3);
6700   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6701   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6702   MatCheckPreallocated(mat, 1);
6703 
6704   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6705   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6706   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6707   PetscCall(ISGetIndices(newis, &newRows));
6708   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6709   PetscCall(ISRestoreIndices(newis, &newRows));
6710   PetscCall(ISDestroy(&newis));
6711   PetscCall(ISDestroy(&is));
6712   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6713   PetscFunctionReturn(PETSC_SUCCESS);
6714 }
6715 
6716 /*@
6717   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6718   of a set of rows and columns of a matrix; using local numbering of rows.
6719 
6720   Collective
6721 
6722   Input Parameters:
6723 + mat  - the matrix
6724 . is   - index set of rows to remove
6725 . diag - value put in all diagonals of eliminated rows
6726 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6727 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6728 
6729   Level: intermediate
6730 
6731   Notes:
6732   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6733   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6734 
6735   See `MatZeroRowsColumns()` for details on how this routine operates.
6736 
6737 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6738           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6739 @*/
6740 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6741 {
6742   PetscInt        numRows;
6743   const PetscInt *rows;
6744 
6745   PetscFunctionBegin;
6746   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6747   PetscValidType(mat, 1);
6748   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6749   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6750   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6751   MatCheckPreallocated(mat, 1);
6752 
6753   PetscCall(ISGetLocalSize(is, &numRows));
6754   PetscCall(ISGetIndices(is, &rows));
6755   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6756   PetscCall(ISRestoreIndices(is, &rows));
6757   PetscFunctionReturn(PETSC_SUCCESS);
6758 }
6759 
6760 /*@C
6761   MatGetSize - Returns the numbers of rows and columns in a matrix.
6762 
6763   Not Collective
6764 
6765   Input Parameter:
6766 . mat - the matrix
6767 
6768   Output Parameters:
6769 + m - the number of global rows
6770 - n - the number of global columns
6771 
6772   Level: beginner
6773 
6774   Note:
6775   Both output parameters can be `NULL` on input.
6776 
6777 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6778 @*/
6779 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6780 {
6781   PetscFunctionBegin;
6782   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6783   if (m) *m = mat->rmap->N;
6784   if (n) *n = mat->cmap->N;
6785   PetscFunctionReturn(PETSC_SUCCESS);
6786 }
6787 
6788 /*@C
6789   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6790   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6791 
6792   Not Collective
6793 
6794   Input Parameter:
6795 . mat - the matrix
6796 
6797   Output Parameters:
6798 + m - the number of local rows, use `NULL` to not obtain this value
6799 - n - the number of local columns, use `NULL` to not obtain this value
6800 
6801   Level: beginner
6802 
6803 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6804 @*/
6805 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6806 {
6807   PetscFunctionBegin;
6808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6809   if (m) PetscAssertPointer(m, 2);
6810   if (n) PetscAssertPointer(n, 3);
6811   if (m) *m = mat->rmap->n;
6812   if (n) *n = mat->cmap->n;
6813   PetscFunctionReturn(PETSC_SUCCESS);
6814 }
6815 
6816 /*@
6817   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6818   vector one multiplies this matrix by that are owned by this processor.
6819 
6820   Not Collective, unless matrix has not been allocated, then collective
6821 
6822   Input Parameter:
6823 . mat - the matrix
6824 
6825   Output Parameters:
6826 + m - the global index of the first local column, use `NULL` to not obtain this value
6827 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6828 
6829   Level: developer
6830 
6831   Notes:
6832   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6833 
6834   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6835   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6836 
6837   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6838   the local values in the matrix.
6839 
6840   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6841   Layouts](sec_matlayout) for details on matrix layouts.
6842 
6843 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6844           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6845 @*/
6846 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6847 {
6848   PetscFunctionBegin;
6849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6850   PetscValidType(mat, 1);
6851   if (m) PetscAssertPointer(m, 2);
6852   if (n) PetscAssertPointer(n, 3);
6853   MatCheckPreallocated(mat, 1);
6854   if (m) *m = mat->cmap->rstart;
6855   if (n) *n = mat->cmap->rend;
6856   PetscFunctionReturn(PETSC_SUCCESS);
6857 }
6858 
6859 /*@C
6860   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6861   this MPI process.
6862 
6863   Not Collective
6864 
6865   Input Parameter:
6866 . mat - the matrix
6867 
6868   Output Parameters:
6869 + m - the global index of the first local row, use `NULL` to not obtain this value
6870 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6871 
6872   Level: beginner
6873 
6874   Notes:
6875   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6876 
6877   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6878   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6879 
6880   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6881   the local values in the matrix.
6882 
6883   The high argument is one more than the last element stored locally.
6884 
6885   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6886   would contain the result of a matrix vector product with this matrix. See [Matrix
6887   Layouts](sec_matlayout) for details on matrix layouts.
6888 
6889 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6890           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6891 @*/
6892 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6893 {
6894   PetscFunctionBegin;
6895   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6896   PetscValidType(mat, 1);
6897   if (m) PetscAssertPointer(m, 2);
6898   if (n) PetscAssertPointer(n, 3);
6899   MatCheckPreallocated(mat, 1);
6900   if (m) *m = mat->rmap->rstart;
6901   if (n) *n = mat->rmap->rend;
6902   PetscFunctionReturn(PETSC_SUCCESS);
6903 }
6904 
6905 /*@C
6906   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6907   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6908 
6909   Not Collective, unless matrix has not been allocated
6910 
6911   Input Parameter:
6912 . mat - the matrix
6913 
6914   Output Parameter:
6915 . ranges - start of each processors portion plus one more than the total length at the end
6916 
6917   Level: beginner
6918 
6919   Notes:
6920   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6921 
6922   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6923   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6924 
6925   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6926   the local values in the matrix.
6927 
6928   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6929   would contain the result of a matrix vector product with this matrix. See [Matrix
6930   Layouts](sec_matlayout) for details on matrix layouts.
6931 
6932 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6933           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6934           `DMDAGetGhostCorners()`, `DM`
6935 @*/
6936 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6937 {
6938   PetscFunctionBegin;
6939   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6940   PetscValidType(mat, 1);
6941   MatCheckPreallocated(mat, 1);
6942   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6943   PetscFunctionReturn(PETSC_SUCCESS);
6944 }
6945 
6946 /*@C
6947   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6948   vector one multiplies this vector by that are owned by each processor.
6949 
6950   Not Collective, unless matrix has not been allocated
6951 
6952   Input Parameter:
6953 . mat - the matrix
6954 
6955   Output Parameter:
6956 . ranges - start of each processors portion plus one more than the total length at the end
6957 
6958   Level: beginner
6959 
6960   Notes:
6961   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6962 
6963   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6964   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6965 
6966   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6967   the local values in the matrix.
6968 
6969   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6970   Layouts](sec_matlayout) for details on matrix layouts.
6971 
6972 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6973           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6974           `DMDAGetGhostCorners()`, `DM`
6975 @*/
6976 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6977 {
6978   PetscFunctionBegin;
6979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6980   PetscValidType(mat, 1);
6981   MatCheckPreallocated(mat, 1);
6982   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6983   PetscFunctionReturn(PETSC_SUCCESS);
6984 }
6985 
6986 /*@C
6987   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6988 
6989   Not Collective
6990 
6991   Input Parameter:
6992 . A - matrix
6993 
6994   Output Parameters:
6995 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6996 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6997 
6998   Level: intermediate
6999 
7000   Note:
7001   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7002   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7003   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7004   details on matrix layouts.
7005 
7006 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7007 @*/
7008 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7009 {
7010   PetscErrorCode (*f)(Mat, IS *, IS *);
7011 
7012   PetscFunctionBegin;
7013   MatCheckPreallocated(A, 1);
7014   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7015   if (f) {
7016     PetscCall((*f)(A, rows, cols));
7017   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7018     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7019     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7020   }
7021   PetscFunctionReturn(PETSC_SUCCESS);
7022 }
7023 
7024 /*@C
7025   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7026   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7027   to complete the factorization.
7028 
7029   Collective
7030 
7031   Input Parameters:
7032 + fact - the factorized matrix obtained with `MatGetFactor()`
7033 . mat  - the matrix
7034 . row  - row permutation
7035 . col  - column permutation
7036 - info - structure containing
7037 .vb
7038       levels - number of levels of fill.
7039       expected fill - as ratio of original fill.
7040       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7041                 missing diagonal entries)
7042 .ve
7043 
7044   Level: developer
7045 
7046   Notes:
7047   See [Matrix Factorization](sec_matfactor) for additional information.
7048 
7049   Most users should employ the `KSP` interface for linear solvers
7050   instead of working directly with matrix algebra routines such as this.
7051   See, e.g., `KSPCreate()`.
7052 
7053   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7054 
7055   Developer Note:
7056   The Fortran interface is not autogenerated as the
7057   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7058 
7059 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7060           `MatGetOrdering()`, `MatFactorInfo`
7061 @*/
7062 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7063 {
7064   PetscFunctionBegin;
7065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7066   PetscValidType(mat, 2);
7067   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7068   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7069   PetscAssertPointer(info, 5);
7070   PetscAssertPointer(fact, 1);
7071   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7072   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7073   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7074   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7075   MatCheckPreallocated(mat, 2);
7076 
7077   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7078   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7079   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7080   PetscFunctionReturn(PETSC_SUCCESS);
7081 }
7082 
7083 /*@C
7084   MatICCFactorSymbolic - Performs symbolic incomplete
7085   Cholesky factorization for a symmetric matrix.  Use
7086   `MatCholeskyFactorNumeric()` to complete the factorization.
7087 
7088   Collective
7089 
7090   Input Parameters:
7091 + fact - the factorized matrix obtained with `MatGetFactor()`
7092 . mat  - the matrix to be factored
7093 . perm - row and column permutation
7094 - info - structure containing
7095 .vb
7096       levels - number of levels of fill.
7097       expected fill - as ratio of original fill.
7098 .ve
7099 
7100   Level: developer
7101 
7102   Notes:
7103   Most users should employ the `KSP` interface for linear solvers
7104   instead of working directly with matrix algebra routines such as this.
7105   See, e.g., `KSPCreate()`.
7106 
7107   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7108 
7109   Developer Note:
7110   The Fortran interface is not autogenerated as the
7111   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7112 
7113 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7114 @*/
7115 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7116 {
7117   PetscFunctionBegin;
7118   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7119   PetscValidType(mat, 2);
7120   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7121   PetscAssertPointer(info, 4);
7122   PetscAssertPointer(fact, 1);
7123   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7124   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7125   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7126   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7127   MatCheckPreallocated(mat, 2);
7128 
7129   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7130   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7131   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7132   PetscFunctionReturn(PETSC_SUCCESS);
7133 }
7134 
7135 /*@C
7136   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7137   points to an array of valid matrices, they may be reused to store the new
7138   submatrices.
7139 
7140   Collective
7141 
7142   Input Parameters:
7143 + mat   - the matrix
7144 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7145 . irow  - index set of rows to extract
7146 . icol  - index set of columns to extract
7147 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7148 
7149   Output Parameter:
7150 . submat - the array of submatrices
7151 
7152   Level: advanced
7153 
7154   Notes:
7155   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7156   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7157   to extract a parallel submatrix.
7158 
7159   Some matrix types place restrictions on the row and column
7160   indices, such as that they be sorted or that they be equal to each other.
7161 
7162   The index sets may not have duplicate entries.
7163 
7164   When extracting submatrices from a parallel matrix, each processor can
7165   form a different submatrix by setting the rows and columns of its
7166   individual index sets according to the local submatrix desired.
7167 
7168   When finished using the submatrices, the user should destroy
7169   them with `MatDestroySubMatrices()`.
7170 
7171   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7172   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7173 
7174   This routine creates the matrices in submat; you should NOT create them before
7175   calling it. It also allocates the array of matrix pointers submat.
7176 
7177   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7178   request one row/column in a block, they must request all rows/columns that are in
7179   that block. For example, if the block size is 2 you cannot request just row 0 and
7180   column 0.
7181 
7182   Fortran Note:
7183   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7184 
7185 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7186 @*/
7187 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7188 {
7189   PetscInt  i;
7190   PetscBool eq;
7191 
7192   PetscFunctionBegin;
7193   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7194   PetscValidType(mat, 1);
7195   if (n) {
7196     PetscAssertPointer(irow, 3);
7197     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7198     PetscAssertPointer(icol, 4);
7199     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7200   }
7201   PetscAssertPointer(submat, 6);
7202   if (n && scall == MAT_REUSE_MATRIX) {
7203     PetscAssertPointer(*submat, 6);
7204     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7205   }
7206   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7207   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7208   MatCheckPreallocated(mat, 1);
7209   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7210   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7211   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7212   for (i = 0; i < n; i++) {
7213     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7214     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7215     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7216 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7217     if (mat->boundtocpu && mat->bindingpropagates) {
7218       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7219       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7220     }
7221 #endif
7222   }
7223   PetscFunctionReturn(PETSC_SUCCESS);
7224 }
7225 
7226 /*@C
7227   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7228 
7229   Collective
7230 
7231   Input Parameters:
7232 + mat   - the matrix
7233 . n     - the number of submatrixes to be extracted
7234 . irow  - index set of rows to extract
7235 . icol  - index set of columns to extract
7236 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7237 
7238   Output Parameter:
7239 . submat - the array of submatrices
7240 
7241   Level: advanced
7242 
7243   Note:
7244   This is used by `PCGASM`
7245 
7246 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7247 @*/
7248 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7249 {
7250   PetscInt  i;
7251   PetscBool eq;
7252 
7253   PetscFunctionBegin;
7254   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7255   PetscValidType(mat, 1);
7256   if (n) {
7257     PetscAssertPointer(irow, 3);
7258     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7259     PetscAssertPointer(icol, 4);
7260     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7261   }
7262   PetscAssertPointer(submat, 6);
7263   if (n && scall == MAT_REUSE_MATRIX) {
7264     PetscAssertPointer(*submat, 6);
7265     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7266   }
7267   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7268   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7269   MatCheckPreallocated(mat, 1);
7270 
7271   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7272   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7273   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7274   for (i = 0; i < n; i++) {
7275     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7276     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7277   }
7278   PetscFunctionReturn(PETSC_SUCCESS);
7279 }
7280 
7281 /*@C
7282   MatDestroyMatrices - Destroys an array of matrices.
7283 
7284   Collective
7285 
7286   Input Parameters:
7287 + n   - the number of local matrices
7288 - mat - the matrices (this is a pointer to the array of matrices)
7289 
7290   Level: advanced
7291 
7292   Note:
7293   Frees not only the matrices, but also the array that contains the matrices
7294 
7295   Fortran Note:
7296   Does not free the `mat` array.
7297 
7298 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7299 @*/
7300 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7301 {
7302   PetscInt i;
7303 
7304   PetscFunctionBegin;
7305   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7306   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7307   PetscAssertPointer(mat, 2);
7308 
7309   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7310 
7311   /* memory is allocated even if n = 0 */
7312   PetscCall(PetscFree(*mat));
7313   PetscFunctionReturn(PETSC_SUCCESS);
7314 }
7315 
7316 /*@C
7317   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7318 
7319   Collective
7320 
7321   Input Parameters:
7322 + n   - the number of local matrices
7323 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7324                        sequence of `MatCreateSubMatrices()`)
7325 
7326   Level: advanced
7327 
7328   Note:
7329   Frees not only the matrices, but also the array that contains the matrices
7330 
7331   Fortran Note:
7332   Does not free the `mat` array.
7333 
7334 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7335 @*/
7336 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7337 {
7338   Mat mat0;
7339 
7340   PetscFunctionBegin;
7341   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7342   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7343   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7344   PetscAssertPointer(mat, 2);
7345 
7346   mat0 = (*mat)[0];
7347   if (mat0 && mat0->ops->destroysubmatrices) {
7348     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7349   } else {
7350     PetscCall(MatDestroyMatrices(n, mat));
7351   }
7352   PetscFunctionReturn(PETSC_SUCCESS);
7353 }
7354 
7355 /*@
7356   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7357 
7358   Collective
7359 
7360   Input Parameter:
7361 . mat - the matrix
7362 
7363   Output Parameter:
7364 . matstruct - the sequential matrix with the nonzero structure of `mat`
7365 
7366   Level: developer
7367 
7368 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7369 @*/
7370 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7371 {
7372   PetscFunctionBegin;
7373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7374   PetscAssertPointer(matstruct, 2);
7375 
7376   PetscValidType(mat, 1);
7377   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7378   MatCheckPreallocated(mat, 1);
7379 
7380   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7381   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7382   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7383   PetscFunctionReturn(PETSC_SUCCESS);
7384 }
7385 
7386 /*@C
7387   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7388 
7389   Collective
7390 
7391   Input Parameter:
7392 . mat - the matrix
7393 
7394   Level: advanced
7395 
7396   Note:
7397   This is not needed, one can just call `MatDestroy()`
7398 
7399 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7400 @*/
7401 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7402 {
7403   PetscFunctionBegin;
7404   PetscAssertPointer(mat, 1);
7405   PetscCall(MatDestroy(mat));
7406   PetscFunctionReturn(PETSC_SUCCESS);
7407 }
7408 
7409 /*@
7410   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7411   replaces the index sets by larger ones that represent submatrices with
7412   additional overlap.
7413 
7414   Collective
7415 
7416   Input Parameters:
7417 + mat - the matrix
7418 . n   - the number of index sets
7419 . is  - the array of index sets (these index sets will changed during the call)
7420 - ov  - the additional overlap requested
7421 
7422   Options Database Key:
7423 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7424 
7425   Level: developer
7426 
7427   Note:
7428   The computed overlap preserves the matrix block sizes when the blocks are square.
7429   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7430   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7431 
7432 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7433 @*/
7434 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7435 {
7436   PetscInt i, bs, cbs;
7437 
7438   PetscFunctionBegin;
7439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7440   PetscValidType(mat, 1);
7441   PetscValidLogicalCollectiveInt(mat, n, 2);
7442   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7443   if (n) {
7444     PetscAssertPointer(is, 3);
7445     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7446   }
7447   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7448   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7449   MatCheckPreallocated(mat, 1);
7450 
7451   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7452   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7453   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7454   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7455   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7456   if (bs == cbs) {
7457     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7458   }
7459   PetscFunctionReturn(PETSC_SUCCESS);
7460 }
7461 
7462 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7463 
7464 /*@
7465   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7466   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7467   additional overlap.
7468 
7469   Collective
7470 
7471   Input Parameters:
7472 + mat - the matrix
7473 . n   - the number of index sets
7474 . is  - the array of index sets (these index sets will changed during the call)
7475 - ov  - the additional overlap requested
7476 
7477   `   Options Database Key:
7478 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7479 
7480   Level: developer
7481 
7482 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7483 @*/
7484 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7485 {
7486   PetscInt i;
7487 
7488   PetscFunctionBegin;
7489   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7490   PetscValidType(mat, 1);
7491   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7492   if (n) {
7493     PetscAssertPointer(is, 3);
7494     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7495   }
7496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7498   MatCheckPreallocated(mat, 1);
7499   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7500   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7501   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7502   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7503   PetscFunctionReturn(PETSC_SUCCESS);
7504 }
7505 
7506 /*@
7507   MatGetBlockSize - Returns the matrix block size.
7508 
7509   Not Collective
7510 
7511   Input Parameter:
7512 . mat - the matrix
7513 
7514   Output Parameter:
7515 . bs - block size
7516 
7517   Level: intermediate
7518 
7519   Notes:
7520   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7521 
7522   If the block size has not been set yet this routine returns 1.
7523 
7524 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7525 @*/
7526 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7527 {
7528   PetscFunctionBegin;
7529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7530   PetscAssertPointer(bs, 2);
7531   *bs = PetscAbs(mat->rmap->bs);
7532   PetscFunctionReturn(PETSC_SUCCESS);
7533 }
7534 
7535 /*@
7536   MatGetBlockSizes - Returns the matrix block row and column sizes.
7537 
7538   Not Collective
7539 
7540   Input Parameter:
7541 . mat - the matrix
7542 
7543   Output Parameters:
7544 + rbs - row block size
7545 - cbs - column block size
7546 
7547   Level: intermediate
7548 
7549   Notes:
7550   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7551   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7552 
7553   If a block size has not been set yet this routine returns 1.
7554 
7555 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7556 @*/
7557 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7558 {
7559   PetscFunctionBegin;
7560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7561   if (rbs) PetscAssertPointer(rbs, 2);
7562   if (cbs) PetscAssertPointer(cbs, 3);
7563   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7564   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7565   PetscFunctionReturn(PETSC_SUCCESS);
7566 }
7567 
7568 /*@
7569   MatSetBlockSize - Sets the matrix block size.
7570 
7571   Logically Collective
7572 
7573   Input Parameters:
7574 + mat - the matrix
7575 - bs  - block size
7576 
7577   Level: intermediate
7578 
7579   Notes:
7580   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7581   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7582 
7583   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7584   is compatible with the matrix local sizes.
7585 
7586 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7587 @*/
7588 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7589 {
7590   PetscFunctionBegin;
7591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7592   PetscValidLogicalCollectiveInt(mat, bs, 2);
7593   PetscCall(MatSetBlockSizes(mat, bs, bs));
7594   PetscFunctionReturn(PETSC_SUCCESS);
7595 }
7596 
7597 typedef struct {
7598   PetscInt         n;
7599   IS              *is;
7600   Mat             *mat;
7601   PetscObjectState nonzerostate;
7602   Mat              C;
7603 } EnvelopeData;
7604 
7605 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7606 {
7607   EnvelopeData *edata = (EnvelopeData *)ptr;
7608 
7609   PetscFunctionBegin;
7610   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7611   PetscCall(PetscFree(edata->is));
7612   PetscCall(PetscFree(edata));
7613   PetscFunctionReturn(PETSC_SUCCESS);
7614 }
7615 
7616 /*@
7617   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7618   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7619 
7620   Collective
7621 
7622   Input Parameter:
7623 . mat - the matrix
7624 
7625   Level: intermediate
7626 
7627   Notes:
7628   There can be zeros within the blocks
7629 
7630   The blocks can overlap between processes, including laying on more than two processes
7631 
7632 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7633 @*/
7634 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7635 {
7636   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7637   PetscInt          *diag, *odiag, sc;
7638   VecScatter         scatter;
7639   PetscScalar       *seqv;
7640   const PetscScalar *parv;
7641   const PetscInt    *ia, *ja;
7642   PetscBool          set, flag, done;
7643   Mat                AA = mat, A;
7644   MPI_Comm           comm;
7645   PetscMPIInt        rank, size, tag;
7646   MPI_Status         status;
7647   PetscContainer     container;
7648   EnvelopeData      *edata;
7649   Vec                seq, par;
7650   IS                 isglobal;
7651 
7652   PetscFunctionBegin;
7653   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7654   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7655   if (!set || !flag) {
7656     /* TODO: only needs nonzero structure of transpose */
7657     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7658     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7659   }
7660   PetscCall(MatAIJGetLocalMat(AA, &A));
7661   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7662   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7663 
7664   PetscCall(MatGetLocalSize(mat, &n, NULL));
7665   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7666   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7667   PetscCallMPI(MPI_Comm_size(comm, &size));
7668   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7669 
7670   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7671 
7672   if (rank > 0) {
7673     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7674     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7675   }
7676   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7677   for (i = 0; i < n; i++) {
7678     env = PetscMax(env, ja[ia[i + 1] - 1]);
7679     II  = rstart + i;
7680     if (env == II) {
7681       starts[lblocks]  = tbs;
7682       sizes[lblocks++] = 1 + II - tbs;
7683       tbs              = 1 + II;
7684     }
7685   }
7686   if (rank < size - 1) {
7687     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7688     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7689   }
7690 
7691   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7692   if (!set || !flag) PetscCall(MatDestroy(&AA));
7693   PetscCall(MatDestroy(&A));
7694 
7695   PetscCall(PetscNew(&edata));
7696   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7697   edata->n = lblocks;
7698   /* create IS needed for extracting blocks from the original matrix */
7699   PetscCall(PetscMalloc1(lblocks, &edata->is));
7700   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7701 
7702   /* Create the resulting inverse matrix structure with preallocation information */
7703   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7704   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7705   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7706   PetscCall(MatSetType(edata->C, MATAIJ));
7707 
7708   /* Communicate the start and end of each row, from each block to the correct rank */
7709   /* TODO: Use PetscSF instead of VecScatter */
7710   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7711   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7712   PetscCall(VecGetArrayWrite(seq, &seqv));
7713   for (PetscInt i = 0; i < lblocks; i++) {
7714     for (PetscInt j = 0; j < sizes[i]; j++) {
7715       seqv[cnt]     = starts[i];
7716       seqv[cnt + 1] = starts[i] + sizes[i];
7717       cnt += 2;
7718     }
7719   }
7720   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7721   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7722   sc -= cnt;
7723   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7724   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7725   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7726   PetscCall(ISDestroy(&isglobal));
7727   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7728   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7729   PetscCall(VecScatterDestroy(&scatter));
7730   PetscCall(VecDestroy(&seq));
7731   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7732   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7733   PetscCall(VecGetArrayRead(par, &parv));
7734   cnt = 0;
7735   PetscCall(MatGetSize(mat, NULL, &n));
7736   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7737     PetscInt start, end, d = 0, od = 0;
7738 
7739     start = (PetscInt)PetscRealPart(parv[cnt]);
7740     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7741     cnt += 2;
7742 
7743     if (start < cstart) {
7744       od += cstart - start + n - cend;
7745       d += cend - cstart;
7746     } else if (start < cend) {
7747       od += n - cend;
7748       d += cend - start;
7749     } else od += n - start;
7750     if (end <= cstart) {
7751       od -= cstart - end + n - cend;
7752       d -= cend - cstart;
7753     } else if (end < cend) {
7754       od -= n - cend;
7755       d -= cend - end;
7756     } else od -= n - end;
7757 
7758     odiag[i] = od;
7759     diag[i]  = d;
7760   }
7761   PetscCall(VecRestoreArrayRead(par, &parv));
7762   PetscCall(VecDestroy(&par));
7763   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7764   PetscCall(PetscFree2(diag, odiag));
7765   PetscCall(PetscFree2(sizes, starts));
7766 
7767   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7768   PetscCall(PetscContainerSetPointer(container, edata));
7769   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7770   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7771   PetscCall(PetscObjectDereference((PetscObject)container));
7772   PetscFunctionReturn(PETSC_SUCCESS);
7773 }
7774 
7775 /*@
7776   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7777 
7778   Collective
7779 
7780   Input Parameters:
7781 + A     - the matrix
7782 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7783 
7784   Output Parameter:
7785 . C - matrix with inverted block diagonal of `A`
7786 
7787   Level: advanced
7788 
7789   Note:
7790   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7791 
7792 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7793 @*/
7794 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7795 {
7796   PetscContainer   container;
7797   EnvelopeData    *edata;
7798   PetscObjectState nonzerostate;
7799 
7800   PetscFunctionBegin;
7801   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7802   if (!container) {
7803     PetscCall(MatComputeVariableBlockEnvelope(A));
7804     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7805   }
7806   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7807   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7808   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7809   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7810 
7811   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7812   *C = edata->C;
7813 
7814   for (PetscInt i = 0; i < edata->n; i++) {
7815     Mat          D;
7816     PetscScalar *dvalues;
7817 
7818     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7819     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7820     PetscCall(MatSeqDenseInvert(D));
7821     PetscCall(MatDenseGetArray(D, &dvalues));
7822     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7823     PetscCall(MatDestroy(&D));
7824   }
7825   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7826   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7827   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7828   PetscFunctionReturn(PETSC_SUCCESS);
7829 }
7830 
7831 /*@
7832   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7833 
7834   Not Collective
7835 
7836   Input Parameters:
7837 + mat     - the matrix
7838 . nblocks - the number of blocks on this process, each block can only exist on a single process
7839 - bsizes  - the block sizes
7840 
7841   Level: intermediate
7842 
7843   Notes:
7844   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7845 
7846   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.
7847 
7848 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7849           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7850 @*/
7851 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7852 {
7853   PetscInt ncnt = 0, nlocal;
7854 
7855   PetscFunctionBegin;
7856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7857   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7858   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);
7859   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7860   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);
7861   PetscCall(PetscFree(mat->bsizes));
7862   mat->nblocks = nblocks;
7863   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7864   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7865   PetscFunctionReturn(PETSC_SUCCESS);
7866 }
7867 
7868 /*@C
7869   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7870 
7871   Not Collective; No Fortran Support
7872 
7873   Input Parameter:
7874 . mat - the matrix
7875 
7876   Output Parameters:
7877 + nblocks - the number of blocks on this process
7878 - bsizes  - the block sizes
7879 
7880   Level: intermediate
7881 
7882 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7883 @*/
7884 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7885 {
7886   PetscFunctionBegin;
7887   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7888   if (nblocks) *nblocks = mat->nblocks;
7889   if (bsizes) *bsizes = mat->bsizes;
7890   PetscFunctionReturn(PETSC_SUCCESS);
7891 }
7892 
7893 /*@
7894   MatSetBlockSizes - Sets the matrix block row and column sizes.
7895 
7896   Logically Collective
7897 
7898   Input Parameters:
7899 + mat - the matrix
7900 . rbs - row block size
7901 - cbs - column block size
7902 
7903   Level: intermediate
7904 
7905   Notes:
7906   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7907   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7908   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7909 
7910   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7911   are compatible with the matrix local sizes.
7912 
7913   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7914 
7915 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7916 @*/
7917 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7918 {
7919   PetscFunctionBegin;
7920   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7921   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7922   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7923   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7924   if (mat->rmap->refcnt) {
7925     ISLocalToGlobalMapping l2g  = NULL;
7926     PetscLayout            nmap = NULL;
7927 
7928     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7929     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7930     PetscCall(PetscLayoutDestroy(&mat->rmap));
7931     mat->rmap          = nmap;
7932     mat->rmap->mapping = l2g;
7933   }
7934   if (mat->cmap->refcnt) {
7935     ISLocalToGlobalMapping l2g  = NULL;
7936     PetscLayout            nmap = NULL;
7937 
7938     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7939     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7940     PetscCall(PetscLayoutDestroy(&mat->cmap));
7941     mat->cmap          = nmap;
7942     mat->cmap->mapping = l2g;
7943   }
7944   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7945   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7946   PetscFunctionReturn(PETSC_SUCCESS);
7947 }
7948 
7949 /*@
7950   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7951 
7952   Logically Collective
7953 
7954   Input Parameters:
7955 + mat     - the matrix
7956 . fromRow - matrix from which to copy row block size
7957 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7958 
7959   Level: developer
7960 
7961 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7962 @*/
7963 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7964 {
7965   PetscFunctionBegin;
7966   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7967   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7968   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7969   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7970   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7971   PetscFunctionReturn(PETSC_SUCCESS);
7972 }
7973 
7974 /*@
7975   MatResidual - Default routine to calculate the residual r = b - Ax
7976 
7977   Collective
7978 
7979   Input Parameters:
7980 + mat - the matrix
7981 . b   - the right-hand-side
7982 - x   - the approximate solution
7983 
7984   Output Parameter:
7985 . r - location to store the residual
7986 
7987   Level: developer
7988 
7989 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7990 @*/
7991 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7992 {
7993   PetscFunctionBegin;
7994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7995   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7996   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7997   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7998   PetscValidType(mat, 1);
7999   MatCheckPreallocated(mat, 1);
8000   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8001   if (!mat->ops->residual) {
8002     PetscCall(MatMult(mat, x, r));
8003     PetscCall(VecAYPX(r, -1.0, b));
8004   } else {
8005     PetscUseTypeMethod(mat, residual, b, x, r);
8006   }
8007   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8008   PetscFunctionReturn(PETSC_SUCCESS);
8009 }
8010 
8011 /*MC
8012     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8013 
8014     Synopsis:
8015     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8016 
8017     Not Collective
8018 
8019     Input Parameters:
8020 +   A - the matrix
8021 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8022 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8023 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8024                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8025                  always used.
8026 
8027     Output Parameters:
8028 +   n - number of local rows in the (possibly compressed) matrix
8029 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8030 .   ja - the column indices
8031 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8032            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8033 
8034     Level: developer
8035 
8036     Note:
8037     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8038 
8039 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8040 M*/
8041 
8042 /*MC
8043     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8044 
8045     Synopsis:
8046     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8047 
8048     Not Collective
8049 
8050     Input Parameters:
8051 +   A - the  matrix
8052 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8053 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8054     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8055                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8056                  always used.
8057 .   n - number of local rows in the (possibly compressed) matrix
8058 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8059 .   ja - the column indices
8060 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8061            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8062 
8063     Level: developer
8064 
8065 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8066 M*/
8067 
8068 /*@C
8069   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8070 
8071   Collective
8072 
8073   Input Parameters:
8074 + mat             - the matrix
8075 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8076 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8077 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8078                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8079                  always used.
8080 
8081   Output Parameters:
8082 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8083 . 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
8084 . ja   - the column indices, use `NULL` if not needed
8085 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8086            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8087 
8088   Level: developer
8089 
8090   Notes:
8091   You CANNOT change any of the ia[] or ja[] values.
8092 
8093   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8094 
8095   Fortran Notes:
8096   Use
8097 .vb
8098     PetscInt, pointer :: ia(:),ja(:)
8099     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8100     ! Access the ith and jth entries via ia(i) and ja(j)
8101 .ve
8102 
8103   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8104 
8105 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8106 @*/
8107 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8108 {
8109   PetscFunctionBegin;
8110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8111   PetscValidType(mat, 1);
8112   if (n) PetscAssertPointer(n, 5);
8113   if (ia) PetscAssertPointer(ia, 6);
8114   if (ja) PetscAssertPointer(ja, 7);
8115   if (done) PetscAssertPointer(done, 8);
8116   MatCheckPreallocated(mat, 1);
8117   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8118   else {
8119     if (done) *done = PETSC_TRUE;
8120     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8121     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8122     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8123   }
8124   PetscFunctionReturn(PETSC_SUCCESS);
8125 }
8126 
8127 /*@C
8128   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8129 
8130   Collective
8131 
8132   Input Parameters:
8133 + mat             - the matrix
8134 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8135 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8136                 symmetrized
8137 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8138                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8139                  always used.
8140 . n               - number of columns in the (possibly compressed) matrix
8141 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8142 - ja              - the row indices
8143 
8144   Output Parameter:
8145 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8146 
8147   Level: developer
8148 
8149 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8150 @*/
8151 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8152 {
8153   PetscFunctionBegin;
8154   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8155   PetscValidType(mat, 1);
8156   PetscAssertPointer(n, 5);
8157   if (ia) PetscAssertPointer(ia, 6);
8158   if (ja) PetscAssertPointer(ja, 7);
8159   PetscAssertPointer(done, 8);
8160   MatCheckPreallocated(mat, 1);
8161   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8162   else {
8163     *done = PETSC_TRUE;
8164     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8165   }
8166   PetscFunctionReturn(PETSC_SUCCESS);
8167 }
8168 
8169 /*@C
8170   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8171 
8172   Collective
8173 
8174   Input Parameters:
8175 + mat             - the matrix
8176 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8177 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8178 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8179                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8180                  always used.
8181 . n               - size of (possibly compressed) matrix
8182 . ia              - the row pointers
8183 - ja              - the column indices
8184 
8185   Output Parameter:
8186 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8187 
8188   Level: developer
8189 
8190   Note:
8191   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8192   us of the array after it has been restored. If you pass `NULL`, it will
8193   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8194 
8195   Fortran Note:
8196   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8197 
8198 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8199 @*/
8200 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8201 {
8202   PetscFunctionBegin;
8203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8204   PetscValidType(mat, 1);
8205   if (ia) PetscAssertPointer(ia, 6);
8206   if (ja) PetscAssertPointer(ja, 7);
8207   if (done) PetscAssertPointer(done, 8);
8208   MatCheckPreallocated(mat, 1);
8209 
8210   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8211   else {
8212     if (done) *done = PETSC_TRUE;
8213     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8214     if (n) *n = 0;
8215     if (ia) *ia = NULL;
8216     if (ja) *ja = NULL;
8217   }
8218   PetscFunctionReturn(PETSC_SUCCESS);
8219 }
8220 
8221 /*@C
8222   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8223 
8224   Collective
8225 
8226   Input Parameters:
8227 + mat             - the matrix
8228 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8229 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8230 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8231                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8232                  always used.
8233 
8234   Output Parameters:
8235 + n    - size of (possibly compressed) matrix
8236 . ia   - the column pointers
8237 . ja   - the row indices
8238 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8239 
8240   Level: developer
8241 
8242 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8243 @*/
8244 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8245 {
8246   PetscFunctionBegin;
8247   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8248   PetscValidType(mat, 1);
8249   if (ia) PetscAssertPointer(ia, 6);
8250   if (ja) PetscAssertPointer(ja, 7);
8251   PetscAssertPointer(done, 8);
8252   MatCheckPreallocated(mat, 1);
8253 
8254   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8255   else {
8256     *done = PETSC_TRUE;
8257     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8258     if (n) *n = 0;
8259     if (ia) *ia = NULL;
8260     if (ja) *ja = NULL;
8261   }
8262   PetscFunctionReturn(PETSC_SUCCESS);
8263 }
8264 
8265 /*@
8266   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8267   `MatGetColumnIJ()`.
8268 
8269   Collective
8270 
8271   Input Parameters:
8272 + mat        - the matrix
8273 . ncolors    - maximum color value
8274 . n          - number of entries in colorarray
8275 - colorarray - array indicating color for each column
8276 
8277   Output Parameter:
8278 . iscoloring - coloring generated using colorarray information
8279 
8280   Level: developer
8281 
8282 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8283 @*/
8284 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8285 {
8286   PetscFunctionBegin;
8287   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8288   PetscValidType(mat, 1);
8289   PetscAssertPointer(colorarray, 4);
8290   PetscAssertPointer(iscoloring, 5);
8291   MatCheckPreallocated(mat, 1);
8292 
8293   if (!mat->ops->coloringpatch) {
8294     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8295   } else {
8296     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8297   }
8298   PetscFunctionReturn(PETSC_SUCCESS);
8299 }
8300 
8301 /*@
8302   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8303 
8304   Logically Collective
8305 
8306   Input Parameter:
8307 . mat - the factored matrix to be reset
8308 
8309   Level: developer
8310 
8311   Notes:
8312   This routine should be used only with factored matrices formed by in-place
8313   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8314   format).  This option can save memory, for example, when solving nonlinear
8315   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8316   ILU(0) preconditioner.
8317 
8318   One can specify in-place ILU(0) factorization by calling
8319 .vb
8320      PCType(pc,PCILU);
8321      PCFactorSeUseInPlace(pc);
8322 .ve
8323   or by using the options -pc_type ilu -pc_factor_in_place
8324 
8325   In-place factorization ILU(0) can also be used as a local
8326   solver for the blocks within the block Jacobi or additive Schwarz
8327   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8328   for details on setting local solver options.
8329 
8330   Most users should employ the `KSP` interface for linear solvers
8331   instead of working directly with matrix algebra routines such as this.
8332   See, e.g., `KSPCreate()`.
8333 
8334 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8335 @*/
8336 PetscErrorCode MatSetUnfactored(Mat mat)
8337 {
8338   PetscFunctionBegin;
8339   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8340   PetscValidType(mat, 1);
8341   MatCheckPreallocated(mat, 1);
8342   mat->factortype = MAT_FACTOR_NONE;
8343   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8344   PetscUseTypeMethod(mat, setunfactored);
8345   PetscFunctionReturn(PETSC_SUCCESS);
8346 }
8347 
8348 /*MC
8349     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8350 
8351     Synopsis:
8352     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8353 
8354     Not Collective
8355 
8356     Input Parameter:
8357 .   x - matrix
8358 
8359     Output Parameters:
8360 +   xx_v - the Fortran pointer to the array
8361 -   ierr - error code
8362 
8363     Example of Usage:
8364 .vb
8365       PetscScalar, pointer xx_v(:,:)
8366       ....
8367       call MatDenseGetArrayF90(x,xx_v,ierr)
8368       a = xx_v(3)
8369       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8370 .ve
8371 
8372     Level: advanced
8373 
8374 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8375 M*/
8376 
8377 /*MC
8378     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8379     accessed with `MatDenseGetArrayF90()`.
8380 
8381     Synopsis:
8382     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8383 
8384     Not Collective
8385 
8386     Input Parameters:
8387 +   x - matrix
8388 -   xx_v - the Fortran90 pointer to the array
8389 
8390     Output Parameter:
8391 .   ierr - error code
8392 
8393     Example of Usage:
8394 .vb
8395        PetscScalar, pointer xx_v(:,:)
8396        ....
8397        call MatDenseGetArrayF90(x,xx_v,ierr)
8398        a = xx_v(3)
8399        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8400 .ve
8401 
8402     Level: advanced
8403 
8404 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8405 M*/
8406 
8407 /*MC
8408     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8409 
8410     Synopsis:
8411     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8412 
8413     Not Collective
8414 
8415     Input Parameter:
8416 .   x - matrix
8417 
8418     Output Parameters:
8419 +   xx_v - the Fortran pointer to the array
8420 -   ierr - error code
8421 
8422     Example of Usage:
8423 .vb
8424       PetscScalar, pointer xx_v(:)
8425       ....
8426       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8427       a = xx_v(3)
8428       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8429 .ve
8430 
8431     Level: advanced
8432 
8433 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8434 M*/
8435 
8436 /*MC
8437     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8438     accessed with `MatSeqAIJGetArrayF90()`.
8439 
8440     Synopsis:
8441     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8442 
8443     Not Collective
8444 
8445     Input Parameters:
8446 +   x - matrix
8447 -   xx_v - the Fortran90 pointer to the array
8448 
8449     Output Parameter:
8450 .   ierr - error code
8451 
8452     Example of Usage:
8453 .vb
8454        PetscScalar, pointer xx_v(:)
8455        ....
8456        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8457        a = xx_v(3)
8458        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8459 .ve
8460 
8461     Level: advanced
8462 
8463 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8464 M*/
8465 
8466 /*@
8467   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8468   as the original matrix.
8469 
8470   Collective
8471 
8472   Input Parameters:
8473 + mat   - the original matrix
8474 . isrow - parallel `IS` containing the rows this processor should obtain
8475 . 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.
8476 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8477 
8478   Output Parameter:
8479 . newmat - the new submatrix, of the same type as the original matrix
8480 
8481   Level: advanced
8482 
8483   Notes:
8484   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8485 
8486   Some matrix types place restrictions on the row and column indices, such
8487   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;
8488   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8489 
8490   The index sets may not have duplicate entries.
8491 
8492   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8493   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8494   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8495   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8496   you are finished using it.
8497 
8498   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8499   the input matrix.
8500 
8501   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8502 
8503   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8504   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8505 
8506   Example usage:
8507   Consider the following 8x8 matrix with 34 non-zero values, that is
8508   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8509   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8510   as follows
8511 .vb
8512             1  2  0  |  0  3  0  |  0  4
8513     Proc0   0  5  6  |  7  0  0  |  8  0
8514             9  0 10  | 11  0  0  | 12  0
8515     -------------------------------------
8516            13  0 14  | 15 16 17  |  0  0
8517     Proc1   0 18  0  | 19 20 21  |  0  0
8518             0  0  0  | 22 23  0  | 24  0
8519     -------------------------------------
8520     Proc2  25 26 27  |  0  0 28  | 29  0
8521            30  0  0  | 31 32 33  |  0 34
8522 .ve
8523 
8524   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8525 
8526 .vb
8527             2  0  |  0  3  0  |  0
8528     Proc0   5  6  |  7  0  0  |  8
8529     -------------------------------
8530     Proc1  18  0  | 19 20 21  |  0
8531     -------------------------------
8532     Proc2  26 27  |  0  0 28  | 29
8533             0  0  | 31 32 33  |  0
8534 .ve
8535 
8536 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8537 @*/
8538 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8539 {
8540   PetscMPIInt size;
8541   Mat        *local;
8542   IS          iscoltmp;
8543   PetscBool   flg;
8544 
8545   PetscFunctionBegin;
8546   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8547   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8548   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8549   PetscAssertPointer(newmat, 5);
8550   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8551   PetscValidType(mat, 1);
8552   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8553   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8554 
8555   MatCheckPreallocated(mat, 1);
8556   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8557 
8558   if (!iscol || isrow == iscol) {
8559     PetscBool   stride;
8560     PetscMPIInt grabentirematrix = 0, grab;
8561     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8562     if (stride) {
8563       PetscInt first, step, n, rstart, rend;
8564       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8565       if (step == 1) {
8566         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8567         if (rstart == first) {
8568           PetscCall(ISGetLocalSize(isrow, &n));
8569           if (n == rend - rstart) grabentirematrix = 1;
8570         }
8571       }
8572     }
8573     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8574     if (grab) {
8575       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8576       if (cll == MAT_INITIAL_MATRIX) {
8577         *newmat = mat;
8578         PetscCall(PetscObjectReference((PetscObject)mat));
8579       }
8580       PetscFunctionReturn(PETSC_SUCCESS);
8581     }
8582   }
8583 
8584   if (!iscol) {
8585     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8586   } else {
8587     iscoltmp = iscol;
8588   }
8589 
8590   /* if original matrix is on just one processor then use submatrix generated */
8591   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8592     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8593     goto setproperties;
8594   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8595     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8596     *newmat = *local;
8597     PetscCall(PetscFree(local));
8598     goto setproperties;
8599   } else if (!mat->ops->createsubmatrix) {
8600     /* Create a new matrix type that implements the operation using the full matrix */
8601     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8602     switch (cll) {
8603     case MAT_INITIAL_MATRIX:
8604       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8605       break;
8606     case MAT_REUSE_MATRIX:
8607       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8608       break;
8609     default:
8610       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8611     }
8612     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8613     goto setproperties;
8614   }
8615 
8616   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8617   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8618   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8619 
8620 setproperties:
8621   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8622   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8623   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8624   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8625   PetscFunctionReturn(PETSC_SUCCESS);
8626 }
8627 
8628 /*@
8629   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8630 
8631   Not Collective
8632 
8633   Input Parameters:
8634 + A - the matrix we wish to propagate options from
8635 - B - the matrix we wish to propagate options to
8636 
8637   Level: beginner
8638 
8639   Note:
8640   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8641 
8642 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8643 @*/
8644 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8645 {
8646   PetscFunctionBegin;
8647   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8648   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8649   B->symmetry_eternal            = A->symmetry_eternal;
8650   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8651   B->symmetric                   = A->symmetric;
8652   B->structurally_symmetric      = A->structurally_symmetric;
8653   B->spd                         = A->spd;
8654   B->hermitian                   = A->hermitian;
8655   PetscFunctionReturn(PETSC_SUCCESS);
8656 }
8657 
8658 /*@
8659   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8660   used during the assembly process to store values that belong to
8661   other processors.
8662 
8663   Not Collective
8664 
8665   Input Parameters:
8666 + mat   - the matrix
8667 . size  - the initial size of the stash.
8668 - bsize - the initial size of the block-stash(if used).
8669 
8670   Options Database Keys:
8671 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8672 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8673 
8674   Level: intermediate
8675 
8676   Notes:
8677   The block-stash is used for values set with `MatSetValuesBlocked()` while
8678   the stash is used for values set with `MatSetValues()`
8679 
8680   Run with the option -info and look for output of the form
8681   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8682   to determine the appropriate value, MM, to use for size and
8683   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8684   to determine the value, BMM to use for bsize
8685 
8686 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8687 @*/
8688 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8689 {
8690   PetscFunctionBegin;
8691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8692   PetscValidType(mat, 1);
8693   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8694   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8695   PetscFunctionReturn(PETSC_SUCCESS);
8696 }
8697 
8698 /*@
8699   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8700   the matrix
8701 
8702   Neighbor-wise Collective
8703 
8704   Input Parameters:
8705 + A - the matrix
8706 . x - the vector to be multiplied by the interpolation operator
8707 - y - the vector to be added to the result
8708 
8709   Output Parameter:
8710 . w - the resulting vector
8711 
8712   Level: intermediate
8713 
8714   Notes:
8715   `w` may be the same vector as `y`.
8716 
8717   This allows one to use either the restriction or interpolation (its transpose)
8718   matrix to do the interpolation
8719 
8720 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8721 @*/
8722 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8723 {
8724   PetscInt M, N, Ny;
8725 
8726   PetscFunctionBegin;
8727   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8728   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8729   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8730   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8731   PetscCall(MatGetSize(A, &M, &N));
8732   PetscCall(VecGetSize(y, &Ny));
8733   if (M == Ny) {
8734     PetscCall(MatMultAdd(A, x, y, w));
8735   } else {
8736     PetscCall(MatMultTransposeAdd(A, x, y, w));
8737   }
8738   PetscFunctionReturn(PETSC_SUCCESS);
8739 }
8740 
8741 /*@
8742   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8743   the matrix
8744 
8745   Neighbor-wise Collective
8746 
8747   Input Parameters:
8748 + A - the matrix
8749 - x - the vector to be interpolated
8750 
8751   Output Parameter:
8752 . y - the resulting vector
8753 
8754   Level: intermediate
8755 
8756   Note:
8757   This allows one to use either the restriction or interpolation (its transpose)
8758   matrix to do the interpolation
8759 
8760 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8761 @*/
8762 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8763 {
8764   PetscInt M, N, Ny;
8765 
8766   PetscFunctionBegin;
8767   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8768   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8769   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8770   PetscCall(MatGetSize(A, &M, &N));
8771   PetscCall(VecGetSize(y, &Ny));
8772   if (M == Ny) {
8773     PetscCall(MatMult(A, x, y));
8774   } else {
8775     PetscCall(MatMultTranspose(A, x, y));
8776   }
8777   PetscFunctionReturn(PETSC_SUCCESS);
8778 }
8779 
8780 /*@
8781   MatRestrict - $y = A*x$ or $A^T*x$
8782 
8783   Neighbor-wise Collective
8784 
8785   Input Parameters:
8786 + A - the matrix
8787 - x - the vector to be restricted
8788 
8789   Output Parameter:
8790 . y - the resulting vector
8791 
8792   Level: intermediate
8793 
8794   Note:
8795   This allows one to use either the restriction or interpolation (its transpose)
8796   matrix to do the restriction
8797 
8798 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8799 @*/
8800 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8801 {
8802   PetscInt M, N, Nx;
8803 
8804   PetscFunctionBegin;
8805   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8806   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8807   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8808   PetscCall(MatGetSize(A, &M, &N));
8809   PetscCall(VecGetSize(x, &Nx));
8810   if (M == Nx) {
8811     PetscCall(MatMultTranspose(A, x, y));
8812   } else {
8813     PetscCall(MatMult(A, x, y));
8814   }
8815   PetscFunctionReturn(PETSC_SUCCESS);
8816 }
8817 
8818 /*@
8819   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8820 
8821   Neighbor-wise Collective
8822 
8823   Input Parameters:
8824 + A - the matrix
8825 . x - the input dense matrix to be multiplied
8826 - w - the input dense matrix to be added to the result
8827 
8828   Output Parameter:
8829 . y - the output dense matrix
8830 
8831   Level: intermediate
8832 
8833   Note:
8834   This allows one to use either the restriction or interpolation (its transpose)
8835   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8836   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8837 
8838 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8839 @*/
8840 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8841 {
8842   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8843   PetscBool trans = PETSC_TRUE;
8844   MatReuse  reuse = MAT_INITIAL_MATRIX;
8845 
8846   PetscFunctionBegin;
8847   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8848   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8849   PetscValidType(x, 2);
8850   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8851   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8852   PetscCall(MatGetSize(A, &M, &N));
8853   PetscCall(MatGetSize(x, &Mx, &Nx));
8854   if (N == Mx) trans = PETSC_FALSE;
8855   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);
8856   Mo = trans ? N : M;
8857   if (*y) {
8858     PetscCall(MatGetSize(*y, &My, &Ny));
8859     if (Mo == My && Nx == Ny) {
8860       reuse = MAT_REUSE_MATRIX;
8861     } else {
8862       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);
8863       PetscCall(MatDestroy(y));
8864     }
8865   }
8866 
8867   if (w && *y == w) { /* this is to minimize changes in PCMG */
8868     PetscBool flg;
8869 
8870     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8871     if (w) {
8872       PetscInt My, Ny, Mw, Nw;
8873 
8874       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8875       PetscCall(MatGetSize(*y, &My, &Ny));
8876       PetscCall(MatGetSize(w, &Mw, &Nw));
8877       if (!flg || My != Mw || Ny != Nw) w = NULL;
8878     }
8879     if (!w) {
8880       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8881       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8882       PetscCall(PetscObjectDereference((PetscObject)w));
8883     } else {
8884       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8885     }
8886   }
8887   if (!trans) {
8888     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8889   } else {
8890     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8891   }
8892   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8893   PetscFunctionReturn(PETSC_SUCCESS);
8894 }
8895 
8896 /*@
8897   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8898 
8899   Neighbor-wise Collective
8900 
8901   Input Parameters:
8902 + A - the matrix
8903 - x - the input dense matrix
8904 
8905   Output Parameter:
8906 . y - the output dense matrix
8907 
8908   Level: intermediate
8909 
8910   Note:
8911   This allows one to use either the restriction or interpolation (its transpose)
8912   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8913   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8914 
8915 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8916 @*/
8917 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8918 {
8919   PetscFunctionBegin;
8920   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8921   PetscFunctionReturn(PETSC_SUCCESS);
8922 }
8923 
8924 /*@
8925   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8926 
8927   Neighbor-wise Collective
8928 
8929   Input Parameters:
8930 + A - the matrix
8931 - x - the input dense matrix
8932 
8933   Output Parameter:
8934 . y - the output dense matrix
8935 
8936   Level: intermediate
8937 
8938   Note:
8939   This allows one to use either the restriction or interpolation (its transpose)
8940   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8941   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8942 
8943 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8944 @*/
8945 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8946 {
8947   PetscFunctionBegin;
8948   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8949   PetscFunctionReturn(PETSC_SUCCESS);
8950 }
8951 
8952 /*@
8953   MatGetNullSpace - retrieves the null space of a matrix.
8954 
8955   Logically Collective
8956 
8957   Input Parameters:
8958 + mat    - the matrix
8959 - nullsp - the null space object
8960 
8961   Level: developer
8962 
8963 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8964 @*/
8965 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8966 {
8967   PetscFunctionBegin;
8968   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8969   PetscAssertPointer(nullsp, 2);
8970   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8971   PetscFunctionReturn(PETSC_SUCCESS);
8972 }
8973 
8974 /*@C
8975   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8976 
8977   Logically Collective
8978 
8979   Input Parameters:
8980 + n   - the number of matrices
8981 - mat - the array of matrices
8982 
8983   Output Parameters:
8984 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space
8985 
8986   Level: developer
8987 
8988   Note:
8989   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8990 
8991 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8992           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8993 @*/
8994 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8995 {
8996   PetscFunctionBegin;
8997   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8998   PetscAssertPointer(mat, 2);
8999   PetscAssertPointer(nullsp, 3);
9000 
9001   PetscCall(PetscCalloc1(3 * n, nullsp));
9002   for (PetscInt i = 0; i < n; i++) {
9003     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9004     (*nullsp)[i] = mat[i]->nullsp;
9005     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9006     (*nullsp)[n + i] = mat[i]->nearnullsp;
9007     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9008     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9009     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9010   }
9011   PetscFunctionReturn(PETSC_SUCCESS);
9012 }
9013 
9014 /*@C
9015   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9016 
9017   Logically Collective
9018 
9019   Input Parameters:
9020 + n      - the number of matrices
9021 . mat    - the array of matrices
9022 - nullsp - an array of null spaces, `NULL` if the null space does not exist
9023 
9024   Level: developer
9025 
9026   Note:
9027   Call `MatGetNullSpaces()` to create `nullsp`
9028 
9029 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9030           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9031 @*/
9032 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9033 {
9034   PetscFunctionBegin;
9035   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9036   PetscAssertPointer(mat, 2);
9037   PetscAssertPointer(nullsp, 3);
9038   PetscAssertPointer(*nullsp, 3);
9039 
9040   for (PetscInt i = 0; i < n; i++) {
9041     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9042     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9043     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9044     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9045     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9046     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9047     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9048   }
9049   PetscCall(PetscFree(*nullsp));
9050   PetscFunctionReturn(PETSC_SUCCESS);
9051 }
9052 
9053 /*@
9054   MatSetNullSpace - attaches a null space to a matrix.
9055 
9056   Logically Collective
9057 
9058   Input Parameters:
9059 + mat    - the matrix
9060 - nullsp - the null space object
9061 
9062   Level: advanced
9063 
9064   Notes:
9065   This null space is used by the `KSP` linear solvers to solve singular systems.
9066 
9067   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`
9068 
9069   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
9070   to zero but the linear system will still be solved in a least squares sense.
9071 
9072   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9073   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)$.
9074   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
9075   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
9076   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$).
9077   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9078 
9079   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9080   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9081   routine also automatically calls `MatSetTransposeNullSpace()`.
9082 
9083   The user should call `MatNullSpaceDestroy()`.
9084 
9085 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9086           `KSPSetPCSide()`
9087 @*/
9088 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9089 {
9090   PetscFunctionBegin;
9091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9092   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9093   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9094   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9095   mat->nullsp = nullsp;
9096   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9097   PetscFunctionReturn(PETSC_SUCCESS);
9098 }
9099 
9100 /*@
9101   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9102 
9103   Logically Collective
9104 
9105   Input Parameters:
9106 + mat    - the matrix
9107 - nullsp - the null space object
9108 
9109   Level: developer
9110 
9111 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9112 @*/
9113 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9114 {
9115   PetscFunctionBegin;
9116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9117   PetscValidType(mat, 1);
9118   PetscAssertPointer(nullsp, 2);
9119   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9120   PetscFunctionReturn(PETSC_SUCCESS);
9121 }
9122 
9123 /*@
9124   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9125 
9126   Logically Collective
9127 
9128   Input Parameters:
9129 + mat    - the matrix
9130 - nullsp - the null space object
9131 
9132   Level: advanced
9133 
9134   Notes:
9135   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9136 
9137   See `MatSetNullSpace()`
9138 
9139 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9140 @*/
9141 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9142 {
9143   PetscFunctionBegin;
9144   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9145   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9146   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9147   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9148   mat->transnullsp = nullsp;
9149   PetscFunctionReturn(PETSC_SUCCESS);
9150 }
9151 
9152 /*@
9153   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9154   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9155 
9156   Logically Collective
9157 
9158   Input Parameters:
9159 + mat    - the matrix
9160 - nullsp - the null space object
9161 
9162   Level: advanced
9163 
9164   Notes:
9165   Overwrites any previous near null space that may have been attached
9166 
9167   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9168 
9169 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9170 @*/
9171 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9172 {
9173   PetscFunctionBegin;
9174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9175   PetscValidType(mat, 1);
9176   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9177   MatCheckPreallocated(mat, 1);
9178   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9179   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9180   mat->nearnullsp = nullsp;
9181   PetscFunctionReturn(PETSC_SUCCESS);
9182 }
9183 
9184 /*@
9185   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9186 
9187   Not Collective
9188 
9189   Input Parameter:
9190 . mat - the matrix
9191 
9192   Output Parameter:
9193 . nullsp - the null space object, `NULL` if not set
9194 
9195   Level: advanced
9196 
9197 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9198 @*/
9199 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9200 {
9201   PetscFunctionBegin;
9202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9203   PetscValidType(mat, 1);
9204   PetscAssertPointer(nullsp, 2);
9205   MatCheckPreallocated(mat, 1);
9206   *nullsp = mat->nearnullsp;
9207   PetscFunctionReturn(PETSC_SUCCESS);
9208 }
9209 
9210 /*@C
9211   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9212 
9213   Collective
9214 
9215   Input Parameters:
9216 + mat  - the matrix
9217 . row  - row/column permutation
9218 - info - information on desired factorization process
9219 
9220   Level: developer
9221 
9222   Notes:
9223   Probably really in-place only when level of fill is zero, otherwise allocates
9224   new space to store factored matrix and deletes previous memory.
9225 
9226   Most users should employ the `KSP` interface for linear solvers
9227   instead of working directly with matrix algebra routines such as this.
9228   See, e.g., `KSPCreate()`.
9229 
9230   Developer Note:
9231   The Fortran interface is not autogenerated as the
9232   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9233 
9234 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9235 @*/
9236 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9237 {
9238   PetscFunctionBegin;
9239   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9240   PetscValidType(mat, 1);
9241   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9242   PetscAssertPointer(info, 3);
9243   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9244   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9245   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9246   MatCheckPreallocated(mat, 1);
9247   PetscUseTypeMethod(mat, iccfactor, row, info);
9248   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9249   PetscFunctionReturn(PETSC_SUCCESS);
9250 }
9251 
9252 /*@
9253   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9254   ghosted ones.
9255 
9256   Not Collective
9257 
9258   Input Parameters:
9259 + mat  - the matrix
9260 - diag - the diagonal values, including ghost ones
9261 
9262   Level: developer
9263 
9264   Notes:
9265   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9266 
9267   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9268 
9269 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9270 @*/
9271 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9272 {
9273   PetscMPIInt size;
9274 
9275   PetscFunctionBegin;
9276   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9277   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9278   PetscValidType(mat, 1);
9279 
9280   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9281   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9282   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9283   if (size == 1) {
9284     PetscInt n, m;
9285     PetscCall(VecGetSize(diag, &n));
9286     PetscCall(MatGetSize(mat, NULL, &m));
9287     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9288     PetscCall(MatDiagonalScale(mat, NULL, diag));
9289   } else {
9290     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9291   }
9292   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9293   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9294   PetscFunctionReturn(PETSC_SUCCESS);
9295 }
9296 
9297 /*@
9298   MatGetInertia - Gets the inertia from a factored matrix
9299 
9300   Collective
9301 
9302   Input Parameter:
9303 . mat - the matrix
9304 
9305   Output Parameters:
9306 + nneg  - number of negative eigenvalues
9307 . nzero - number of zero eigenvalues
9308 - npos  - number of positive eigenvalues
9309 
9310   Level: advanced
9311 
9312   Note:
9313   Matrix must have been factored by `MatCholeskyFactor()`
9314 
9315 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9316 @*/
9317 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9318 {
9319   PetscFunctionBegin;
9320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9321   PetscValidType(mat, 1);
9322   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9323   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9324   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9325   PetscFunctionReturn(PETSC_SUCCESS);
9326 }
9327 
9328 /*@C
9329   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9330 
9331   Neighbor-wise Collective
9332 
9333   Input Parameters:
9334 + mat - the factored matrix obtained with `MatGetFactor()`
9335 - b   - the right-hand-side vectors
9336 
9337   Output Parameter:
9338 . x - the result vectors
9339 
9340   Level: developer
9341 
9342   Note:
9343   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9344   call `MatSolves`(A,x,x).
9345 
9346 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9347 @*/
9348 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9349 {
9350   PetscFunctionBegin;
9351   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9352   PetscValidType(mat, 1);
9353   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9354   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9355   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9356 
9357   MatCheckPreallocated(mat, 1);
9358   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9359   PetscUseTypeMethod(mat, solves, b, x);
9360   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9361   PetscFunctionReturn(PETSC_SUCCESS);
9362 }
9363 
9364 /*@
9365   MatIsSymmetric - Test whether a matrix is symmetric
9366 
9367   Collective
9368 
9369   Input Parameters:
9370 + A   - the matrix to test
9371 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9372 
9373   Output Parameter:
9374 . flg - the result
9375 
9376   Level: intermediate
9377 
9378   Notes:
9379   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9380 
9381   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9382 
9383   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9384   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9385 
9386 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9387           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9388 @*/
9389 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9390 {
9391   PetscFunctionBegin;
9392   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9393   PetscAssertPointer(flg, 3);
9394   if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric);
9395   else {
9396     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9397     else PetscCall(MatIsTranspose(A, A, tol, flg));
9398     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9399   }
9400   PetscFunctionReturn(PETSC_SUCCESS);
9401 }
9402 
9403 /*@
9404   MatIsHermitian - Test whether a matrix is Hermitian
9405 
9406   Collective
9407 
9408   Input Parameters:
9409 + A   - the matrix to test
9410 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9411 
9412   Output Parameter:
9413 . flg - the result
9414 
9415   Level: intermediate
9416 
9417   Notes:
9418   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9419 
9420   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9421 
9422   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9423   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9424 
9425 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9426           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9427 @*/
9428 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9429 {
9430   PetscFunctionBegin;
9431   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9432   PetscAssertPointer(flg, 3);
9433   if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian);
9434   else {
9435     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9436     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9437     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9438   }
9439   PetscFunctionReturn(PETSC_SUCCESS);
9440 }
9441 
9442 /*@
9443   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9444 
9445   Not Collective
9446 
9447   Input Parameter:
9448 . A - the matrix to check
9449 
9450   Output Parameters:
9451 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9452 - flg - the result (only valid if set is `PETSC_TRUE`)
9453 
9454   Level: advanced
9455 
9456   Notes:
9457   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9458   if you want it explicitly checked
9459 
9460   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9461   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9462 
9463 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9464 @*/
9465 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9466 {
9467   PetscFunctionBegin;
9468   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9469   PetscAssertPointer(set, 2);
9470   PetscAssertPointer(flg, 3);
9471   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9472     *set = PETSC_TRUE;
9473     *flg = PetscBool3ToBool(A->symmetric);
9474   } else {
9475     *set = PETSC_FALSE;
9476   }
9477   PetscFunctionReturn(PETSC_SUCCESS);
9478 }
9479 
9480 /*@
9481   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9482 
9483   Not Collective
9484 
9485   Input Parameter:
9486 . A - the matrix to check
9487 
9488   Output Parameters:
9489 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9490 - flg - the result (only valid if set is `PETSC_TRUE`)
9491 
9492   Level: advanced
9493 
9494   Notes:
9495   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9496 
9497   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9498   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9499 
9500 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9501 @*/
9502 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9503 {
9504   PetscFunctionBegin;
9505   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9506   PetscAssertPointer(set, 2);
9507   PetscAssertPointer(flg, 3);
9508   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9509     *set = PETSC_TRUE;
9510     *flg = PetscBool3ToBool(A->spd);
9511   } else {
9512     *set = PETSC_FALSE;
9513   }
9514   PetscFunctionReturn(PETSC_SUCCESS);
9515 }
9516 
9517 /*@
9518   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9519 
9520   Not Collective
9521 
9522   Input Parameter:
9523 . A - the matrix to check
9524 
9525   Output Parameters:
9526 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9527 - flg - the result (only valid if set is `PETSC_TRUE`)
9528 
9529   Level: advanced
9530 
9531   Notes:
9532   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9533   if you want it explicitly checked
9534 
9535   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9536   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9537 
9538 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9539 @*/
9540 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9541 {
9542   PetscFunctionBegin;
9543   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9544   PetscAssertPointer(set, 2);
9545   PetscAssertPointer(flg, 3);
9546   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9547     *set = PETSC_TRUE;
9548     *flg = PetscBool3ToBool(A->hermitian);
9549   } else {
9550     *set = PETSC_FALSE;
9551   }
9552   PetscFunctionReturn(PETSC_SUCCESS);
9553 }
9554 
9555 /*@
9556   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9557 
9558   Collective
9559 
9560   Input Parameter:
9561 . A - the matrix to test
9562 
9563   Output Parameter:
9564 . flg - the result
9565 
9566   Level: intermediate
9567 
9568   Notes:
9569   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9570 
9571   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
9572   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9573 
9574 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9575 @*/
9576 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9577 {
9578   PetscFunctionBegin;
9579   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9580   PetscAssertPointer(flg, 2);
9581   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9582     *flg = PetscBool3ToBool(A->structurally_symmetric);
9583   } else {
9584     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9585     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9586   }
9587   PetscFunctionReturn(PETSC_SUCCESS);
9588 }
9589 
9590 /*@
9591   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9592 
9593   Not Collective
9594 
9595   Input Parameter:
9596 . A - the matrix to check
9597 
9598   Output Parameters:
9599 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9600 - flg - the result (only valid if set is PETSC_TRUE)
9601 
9602   Level: advanced
9603 
9604   Notes:
9605   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
9606   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9607 
9608   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9609 
9610 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9611 @*/
9612 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9613 {
9614   PetscFunctionBegin;
9615   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9616   PetscAssertPointer(set, 2);
9617   PetscAssertPointer(flg, 3);
9618   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9619     *set = PETSC_TRUE;
9620     *flg = PetscBool3ToBool(A->structurally_symmetric);
9621   } else {
9622     *set = PETSC_FALSE;
9623   }
9624   PetscFunctionReturn(PETSC_SUCCESS);
9625 }
9626 
9627 /*@
9628   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9629   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9630 
9631   Not Collective
9632 
9633   Input Parameter:
9634 . mat - the matrix
9635 
9636   Output Parameters:
9637 + nstash    - the size of the stash
9638 . reallocs  - the number of additional mallocs incurred.
9639 . bnstash   - the size of the block stash
9640 - breallocs - the number of additional mallocs incurred.in the block stash
9641 
9642   Level: advanced
9643 
9644 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9645 @*/
9646 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9647 {
9648   PetscFunctionBegin;
9649   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9650   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9651   PetscFunctionReturn(PETSC_SUCCESS);
9652 }
9653 
9654 /*@C
9655   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9656   parallel layout, `PetscLayout` for rows and columns
9657 
9658   Collective
9659 
9660   Input Parameter:
9661 . mat - the matrix
9662 
9663   Output Parameters:
9664 + right - (optional) vector that the matrix can be multiplied against
9665 - left  - (optional) vector that the matrix vector product can be stored in
9666 
9667   Level: advanced
9668 
9669   Notes:
9670   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()`.
9671 
9672   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9673 
9674 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9675 @*/
9676 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9677 {
9678   PetscFunctionBegin;
9679   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9680   PetscValidType(mat, 1);
9681   if (mat->ops->getvecs) {
9682     PetscUseTypeMethod(mat, getvecs, right, left);
9683   } else {
9684     if (right) {
9685       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9686       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9687       PetscCall(VecSetType(*right, mat->defaultvectype));
9688 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9689       if (mat->boundtocpu && mat->bindingpropagates) {
9690         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9691         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9692       }
9693 #endif
9694     }
9695     if (left) {
9696       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9697       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9698       PetscCall(VecSetType(*left, mat->defaultvectype));
9699 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9700       if (mat->boundtocpu && mat->bindingpropagates) {
9701         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9702         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9703       }
9704 #endif
9705     }
9706   }
9707   PetscFunctionReturn(PETSC_SUCCESS);
9708 }
9709 
9710 /*@C
9711   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9712   with default values.
9713 
9714   Not Collective
9715 
9716   Input Parameter:
9717 . info - the `MatFactorInfo` data structure
9718 
9719   Level: developer
9720 
9721   Notes:
9722   The solvers are generally used through the `KSP` and `PC` objects, for example
9723   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9724 
9725   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9726 
9727   Developer Note:
9728   The Fortran interface is not autogenerated as the
9729   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9730 
9731 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9732 @*/
9733 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9734 {
9735   PetscFunctionBegin;
9736   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9737   PetscFunctionReturn(PETSC_SUCCESS);
9738 }
9739 
9740 /*@
9741   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9742 
9743   Collective
9744 
9745   Input Parameters:
9746 + mat - the factored matrix
9747 - is  - the index set defining the Schur indices (0-based)
9748 
9749   Level: advanced
9750 
9751   Notes:
9752   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9753 
9754   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9755 
9756   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9757 
9758 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9759           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9760 @*/
9761 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9762 {
9763   PetscErrorCode (*f)(Mat, IS);
9764 
9765   PetscFunctionBegin;
9766   PetscValidType(mat, 1);
9767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9768   PetscValidType(is, 2);
9769   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9770   PetscCheckSameComm(mat, 1, is, 2);
9771   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9772   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9773   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9774   PetscCall(MatDestroy(&mat->schur));
9775   PetscCall((*f)(mat, is));
9776   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9777   PetscFunctionReturn(PETSC_SUCCESS);
9778 }
9779 
9780 /*@
9781   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9782 
9783   Logically Collective
9784 
9785   Input Parameters:
9786 + F      - the factored matrix obtained by calling `MatGetFactor()`
9787 . S      - location where to return the Schur complement, can be `NULL`
9788 - status - the status of the Schur complement matrix, can be `NULL`
9789 
9790   Level: advanced
9791 
9792   Notes:
9793   You must call `MatFactorSetSchurIS()` before calling this routine.
9794 
9795   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9796 
9797   The routine provides a copy of the Schur matrix stored within the solver data structures.
9798   The caller must destroy the object when it is no longer needed.
9799   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9800 
9801   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)
9802 
9803   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9804 
9805   Developer Note:
9806   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9807   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9808 
9809 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9810 @*/
9811 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9812 {
9813   PetscFunctionBegin;
9814   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9815   if (S) PetscAssertPointer(S, 2);
9816   if (status) PetscAssertPointer(status, 3);
9817   if (S) {
9818     PetscErrorCode (*f)(Mat, Mat *);
9819 
9820     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9821     if (f) {
9822       PetscCall((*f)(F, S));
9823     } else {
9824       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9825     }
9826   }
9827   if (status) *status = F->schur_status;
9828   PetscFunctionReturn(PETSC_SUCCESS);
9829 }
9830 
9831 /*@
9832   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9833 
9834   Logically Collective
9835 
9836   Input Parameters:
9837 + F      - the factored matrix obtained by calling `MatGetFactor()`
9838 . S      - location where to return the Schur complement, can be `NULL`
9839 - status - the status of the Schur complement matrix, can be `NULL`
9840 
9841   Level: advanced
9842 
9843   Notes:
9844   You must call `MatFactorSetSchurIS()` before calling this routine.
9845 
9846   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9847 
9848   The routine returns a the Schur Complement stored within the data structures of the solver.
9849 
9850   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9851 
9852   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9853 
9854   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9855 
9856   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9857 
9858 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9859 @*/
9860 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9861 {
9862   PetscFunctionBegin;
9863   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9864   if (S) {
9865     PetscAssertPointer(S, 2);
9866     *S = F->schur;
9867   }
9868   if (status) {
9869     PetscAssertPointer(status, 3);
9870     *status = F->schur_status;
9871   }
9872   PetscFunctionReturn(PETSC_SUCCESS);
9873 }
9874 
9875 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9876 {
9877   Mat S = F->schur;
9878 
9879   PetscFunctionBegin;
9880   switch (F->schur_status) {
9881   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9882   case MAT_FACTOR_SCHUR_INVERTED:
9883     if (S) {
9884       S->ops->solve             = NULL;
9885       S->ops->matsolve          = NULL;
9886       S->ops->solvetranspose    = NULL;
9887       S->ops->matsolvetranspose = NULL;
9888       S->ops->solveadd          = NULL;
9889       S->ops->solvetransposeadd = NULL;
9890       S->factortype             = MAT_FACTOR_NONE;
9891       PetscCall(PetscFree(S->solvertype));
9892     }
9893   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9894     break;
9895   default:
9896     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9897   }
9898   PetscFunctionReturn(PETSC_SUCCESS);
9899 }
9900 
9901 /*@
9902   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9903 
9904   Logically Collective
9905 
9906   Input Parameters:
9907 + F      - the factored matrix obtained by calling `MatGetFactor()`
9908 . S      - location where the Schur complement is stored
9909 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9910 
9911   Level: advanced
9912 
9913 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9914 @*/
9915 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9916 {
9917   PetscFunctionBegin;
9918   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9919   if (S) {
9920     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9921     *S = NULL;
9922   }
9923   F->schur_status = status;
9924   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9925   PetscFunctionReturn(PETSC_SUCCESS);
9926 }
9927 
9928 /*@
9929   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9930 
9931   Logically Collective
9932 
9933   Input Parameters:
9934 + F   - the factored matrix obtained by calling `MatGetFactor()`
9935 . rhs - location where the right-hand side of the Schur complement system is stored
9936 - sol - location where the solution of the Schur complement system has to be returned
9937 
9938   Level: advanced
9939 
9940   Notes:
9941   The sizes of the vectors should match the size of the Schur complement
9942 
9943   Must be called after `MatFactorSetSchurIS()`
9944 
9945 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9946 @*/
9947 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9948 {
9949   PetscFunctionBegin;
9950   PetscValidType(F, 1);
9951   PetscValidType(rhs, 2);
9952   PetscValidType(sol, 3);
9953   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9954   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9955   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9956   PetscCheckSameComm(F, 1, rhs, 2);
9957   PetscCheckSameComm(F, 1, sol, 3);
9958   PetscCall(MatFactorFactorizeSchurComplement(F));
9959   switch (F->schur_status) {
9960   case MAT_FACTOR_SCHUR_FACTORED:
9961     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9962     break;
9963   case MAT_FACTOR_SCHUR_INVERTED:
9964     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9965     break;
9966   default:
9967     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9968   }
9969   PetscFunctionReturn(PETSC_SUCCESS);
9970 }
9971 
9972 /*@
9973   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9974 
9975   Logically Collective
9976 
9977   Input Parameters:
9978 + F   - the factored matrix obtained by calling `MatGetFactor()`
9979 . rhs - location where the right-hand side of the Schur complement system is stored
9980 - sol - location where the solution of the Schur complement system has to be returned
9981 
9982   Level: advanced
9983 
9984   Notes:
9985   The sizes of the vectors should match the size of the Schur complement
9986 
9987   Must be called after `MatFactorSetSchurIS()`
9988 
9989 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9990 @*/
9991 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9992 {
9993   PetscFunctionBegin;
9994   PetscValidType(F, 1);
9995   PetscValidType(rhs, 2);
9996   PetscValidType(sol, 3);
9997   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9998   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9999   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10000   PetscCheckSameComm(F, 1, rhs, 2);
10001   PetscCheckSameComm(F, 1, sol, 3);
10002   PetscCall(MatFactorFactorizeSchurComplement(F));
10003   switch (F->schur_status) {
10004   case MAT_FACTOR_SCHUR_FACTORED:
10005     PetscCall(MatSolve(F->schur, rhs, sol));
10006     break;
10007   case MAT_FACTOR_SCHUR_INVERTED:
10008     PetscCall(MatMult(F->schur, rhs, sol));
10009     break;
10010   default:
10011     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10012   }
10013   PetscFunctionReturn(PETSC_SUCCESS);
10014 }
10015 
10016 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10017 #if PetscDefined(HAVE_CUDA)
10018 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10019 #endif
10020 
10021 /* Schur status updated in the interface */
10022 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10023 {
10024   Mat S = F->schur;
10025 
10026   PetscFunctionBegin;
10027   if (S) {
10028     PetscMPIInt size;
10029     PetscBool   isdense, isdensecuda;
10030 
10031     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10032     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10033     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10034     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10035     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10036     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10037     if (isdense) {
10038       PetscCall(MatSeqDenseInvertFactors_Private(S));
10039     } else if (isdensecuda) {
10040 #if defined(PETSC_HAVE_CUDA)
10041       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10042 #endif
10043     }
10044     // HIP??????????????
10045     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10046   }
10047   PetscFunctionReturn(PETSC_SUCCESS);
10048 }
10049 
10050 /*@
10051   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10052 
10053   Logically Collective
10054 
10055   Input Parameter:
10056 . F - the factored matrix obtained by calling `MatGetFactor()`
10057 
10058   Level: advanced
10059 
10060   Notes:
10061   Must be called after `MatFactorSetSchurIS()`.
10062 
10063   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10064 
10065 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10066 @*/
10067 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10068 {
10069   PetscFunctionBegin;
10070   PetscValidType(F, 1);
10071   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10072   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10073   PetscCall(MatFactorFactorizeSchurComplement(F));
10074   PetscCall(MatFactorInvertSchurComplement_Private(F));
10075   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10076   PetscFunctionReturn(PETSC_SUCCESS);
10077 }
10078 
10079 /*@
10080   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10081 
10082   Logically Collective
10083 
10084   Input Parameter:
10085 . F - the factored matrix obtained by calling `MatGetFactor()`
10086 
10087   Level: advanced
10088 
10089   Note:
10090   Must be called after `MatFactorSetSchurIS()`
10091 
10092 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10093 @*/
10094 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10095 {
10096   MatFactorInfo info;
10097 
10098   PetscFunctionBegin;
10099   PetscValidType(F, 1);
10100   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10101   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10102   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10103   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10104   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10105     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10106   } else {
10107     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10108   }
10109   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10110   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10111   PetscFunctionReturn(PETSC_SUCCESS);
10112 }
10113 
10114 /*@
10115   MatPtAP - Creates the matrix product $C = P^T * A * P$
10116 
10117   Neighbor-wise Collective
10118 
10119   Input Parameters:
10120 + A     - the matrix
10121 . P     - the projection matrix
10122 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10123 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
10124           if the result is a dense matrix this is irrelevant
10125 
10126   Output Parameter:
10127 . C - the product matrix
10128 
10129   Level: intermediate
10130 
10131   Notes:
10132   C will be created and must be destroyed by the user with `MatDestroy()`.
10133 
10134   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10135 
10136   Developer Note:
10137   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10138 
10139 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10140 @*/
10141 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10142 {
10143   PetscFunctionBegin;
10144   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10145   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10146 
10147   if (scall == MAT_INITIAL_MATRIX) {
10148     PetscCall(MatProductCreate(A, P, NULL, C));
10149     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10150     PetscCall(MatProductSetAlgorithm(*C, "default"));
10151     PetscCall(MatProductSetFill(*C, fill));
10152 
10153     (*C)->product->api_user = PETSC_TRUE;
10154     PetscCall(MatProductSetFromOptions(*C));
10155     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);
10156     PetscCall(MatProductSymbolic(*C));
10157   } else { /* scall == MAT_REUSE_MATRIX */
10158     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10159   }
10160 
10161   PetscCall(MatProductNumeric(*C));
10162   (*C)->symmetric = A->symmetric;
10163   (*C)->spd       = A->spd;
10164   PetscFunctionReturn(PETSC_SUCCESS);
10165 }
10166 
10167 /*@
10168   MatRARt - Creates the matrix product $C = R * A * R^T$
10169 
10170   Neighbor-wise Collective
10171 
10172   Input Parameters:
10173 + A     - the matrix
10174 . R     - the projection matrix
10175 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10176 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
10177           if the result is a dense matrix this is irrelevant
10178 
10179   Output Parameter:
10180 . C - the product matrix
10181 
10182   Level: intermediate
10183 
10184   Notes:
10185   C will be created and must be destroyed by the user with `MatDestroy()`.
10186 
10187   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10188 
10189   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10190   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10191   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
10192   We recommend using MatPtAP().
10193 
10194 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10195 @*/
10196 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10197 {
10198   PetscFunctionBegin;
10199   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10200   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10201 
10202   if (scall == MAT_INITIAL_MATRIX) {
10203     PetscCall(MatProductCreate(A, R, NULL, C));
10204     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10205     PetscCall(MatProductSetAlgorithm(*C, "default"));
10206     PetscCall(MatProductSetFill(*C, fill));
10207 
10208     (*C)->product->api_user = PETSC_TRUE;
10209     PetscCall(MatProductSetFromOptions(*C));
10210     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);
10211     PetscCall(MatProductSymbolic(*C));
10212   } else { /* scall == MAT_REUSE_MATRIX */
10213     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10214   }
10215 
10216   PetscCall(MatProductNumeric(*C));
10217   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10218   PetscFunctionReturn(PETSC_SUCCESS);
10219 }
10220 
10221 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10222 {
10223   PetscBool flg = PETSC_TRUE;
10224 
10225   PetscFunctionBegin;
10226   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10227   if (scall == MAT_INITIAL_MATRIX) {
10228     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10229     PetscCall(MatProductCreate(A, B, NULL, C));
10230     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10231     PetscCall(MatProductSetFill(*C, fill));
10232   } else { /* scall == MAT_REUSE_MATRIX */
10233     Mat_Product *product = (*C)->product;
10234 
10235     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10236     if (flg && product && product->type != ptype) {
10237       PetscCall(MatProductClear(*C));
10238       product = NULL;
10239     }
10240     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10241     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10242       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10243       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10244       product        = (*C)->product;
10245       product->fill  = fill;
10246       product->clear = PETSC_TRUE;
10247     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10248       flg = PETSC_FALSE;
10249       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10250     }
10251   }
10252   if (flg) {
10253     (*C)->product->api_user = PETSC_TRUE;
10254     PetscCall(MatProductSetType(*C, ptype));
10255     PetscCall(MatProductSetFromOptions(*C));
10256     PetscCall(MatProductSymbolic(*C));
10257   }
10258   PetscCall(MatProductNumeric(*C));
10259   PetscFunctionReturn(PETSC_SUCCESS);
10260 }
10261 
10262 /*@
10263   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10264 
10265   Neighbor-wise Collective
10266 
10267   Input Parameters:
10268 + A     - the left matrix
10269 . B     - the right matrix
10270 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10271 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10272           if the result is a dense matrix this is irrelevant
10273 
10274   Output Parameter:
10275 . C - the product matrix
10276 
10277   Notes:
10278   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10279 
10280   `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
10281   call to this function with `MAT_INITIAL_MATRIX`.
10282 
10283   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10284 
10285   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`,
10286   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10287 
10288   Example of Usage:
10289 .vb
10290      MatProductCreate(A,B,NULL,&C);
10291      MatProductSetType(C,MATPRODUCT_AB);
10292      MatProductSymbolic(C);
10293      MatProductNumeric(C); // compute C=A * B
10294      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10295      MatProductNumeric(C);
10296      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10297      MatProductNumeric(C);
10298 .ve
10299 
10300   Level: intermediate
10301 
10302 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10303 @*/
10304 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10305 {
10306   PetscFunctionBegin;
10307   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10308   PetscFunctionReturn(PETSC_SUCCESS);
10309 }
10310 
10311 /*@
10312   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10313 
10314   Neighbor-wise Collective
10315 
10316   Input Parameters:
10317 + A     - the left matrix
10318 . B     - the right matrix
10319 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10320 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10321 
10322   Output Parameter:
10323 . C - the product matrix
10324 
10325   Options Database Key:
10326 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10327               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10328               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10329 
10330   Level: intermediate
10331 
10332   Notes:
10333   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10334 
10335   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10336 
10337   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10338   actually needed.
10339 
10340   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10341   and for pairs of `MATMPIDENSE` matrices.
10342 
10343   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10344 
10345 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10346 @*/
10347 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10348 {
10349   PetscFunctionBegin;
10350   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10351   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10352   PetscFunctionReturn(PETSC_SUCCESS);
10353 }
10354 
10355 /*@
10356   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10357 
10358   Neighbor-wise Collective
10359 
10360   Input Parameters:
10361 + A     - the left matrix
10362 . B     - the right matrix
10363 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10364 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10365 
10366   Output Parameter:
10367 . C - the product matrix
10368 
10369   Level: intermediate
10370 
10371   Notes:
10372   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10373 
10374   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10375 
10376   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10377 
10378   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10379   actually needed.
10380 
10381   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10382   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10383 
10384 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10385 @*/
10386 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10387 {
10388   PetscFunctionBegin;
10389   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10390   PetscFunctionReturn(PETSC_SUCCESS);
10391 }
10392 
10393 /*@
10394   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10395 
10396   Neighbor-wise Collective
10397 
10398   Input Parameters:
10399 + A     - the left matrix
10400 . B     - the middle matrix
10401 . C     - the right matrix
10402 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10403 - 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
10404           if the result is a dense matrix this is irrelevant
10405 
10406   Output Parameter:
10407 . D - the product matrix
10408 
10409   Level: intermediate
10410 
10411   Notes:
10412   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10413 
10414   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10415 
10416   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10417 
10418   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10419   actually needed.
10420 
10421   If you have many matrices with the same non-zero structure to multiply, you
10422   should use `MAT_REUSE_MATRIX` in all calls but the first
10423 
10424 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10425 @*/
10426 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10427 {
10428   PetscFunctionBegin;
10429   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10430   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10431 
10432   if (scall == MAT_INITIAL_MATRIX) {
10433     PetscCall(MatProductCreate(A, B, C, D));
10434     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10435     PetscCall(MatProductSetAlgorithm(*D, "default"));
10436     PetscCall(MatProductSetFill(*D, fill));
10437 
10438     (*D)->product->api_user = PETSC_TRUE;
10439     PetscCall(MatProductSetFromOptions(*D));
10440     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,
10441                ((PetscObject)C)->type_name);
10442     PetscCall(MatProductSymbolic(*D));
10443   } else { /* user may change input matrices when REUSE */
10444     PetscCall(MatProductReplaceMats(A, B, C, *D));
10445   }
10446   PetscCall(MatProductNumeric(*D));
10447   PetscFunctionReturn(PETSC_SUCCESS);
10448 }
10449 
10450 /*@
10451   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10452 
10453   Collective
10454 
10455   Input Parameters:
10456 + mat      - the matrix
10457 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10458 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10459 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10460 
10461   Output Parameter:
10462 . matredundant - redundant matrix
10463 
10464   Level: advanced
10465 
10466   Notes:
10467   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10468   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10469 
10470   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10471   calling it.
10472 
10473   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10474 
10475 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10476 @*/
10477 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10478 {
10479   MPI_Comm       comm;
10480   PetscMPIInt    size;
10481   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10482   Mat_Redundant *redund     = NULL;
10483   PetscSubcomm   psubcomm   = NULL;
10484   MPI_Comm       subcomm_in = subcomm;
10485   Mat           *matseq;
10486   IS             isrow, iscol;
10487   PetscBool      newsubcomm = PETSC_FALSE;
10488 
10489   PetscFunctionBegin;
10490   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10491   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10492     PetscAssertPointer(*matredundant, 5);
10493     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10494   }
10495 
10496   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10497   if (size == 1 || nsubcomm == 1) {
10498     if (reuse == MAT_INITIAL_MATRIX) {
10499       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10500     } else {
10501       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");
10502       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10503     }
10504     PetscFunctionReturn(PETSC_SUCCESS);
10505   }
10506 
10507   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10508   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10509   MatCheckPreallocated(mat, 1);
10510 
10511   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10512   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10513     /* create psubcomm, then get subcomm */
10514     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10515     PetscCallMPI(MPI_Comm_size(comm, &size));
10516     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10517 
10518     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10519     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10520     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10521     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10522     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10523     newsubcomm = PETSC_TRUE;
10524     PetscCall(PetscSubcommDestroy(&psubcomm));
10525   }
10526 
10527   /* get isrow, iscol and a local sequential matrix matseq[0] */
10528   if (reuse == MAT_INITIAL_MATRIX) {
10529     mloc_sub = PETSC_DECIDE;
10530     nloc_sub = PETSC_DECIDE;
10531     if (bs < 1) {
10532       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10533       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10534     } else {
10535       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10536       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10537     }
10538     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10539     rstart = rend - mloc_sub;
10540     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10541     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10542     PetscCall(ISSetIdentity(iscol));
10543   } else { /* reuse == MAT_REUSE_MATRIX */
10544     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");
10545     /* retrieve subcomm */
10546     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10547     redund = (*matredundant)->redundant;
10548     isrow  = redund->isrow;
10549     iscol  = redund->iscol;
10550     matseq = redund->matseq;
10551   }
10552   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10553 
10554   /* get matredundant over subcomm */
10555   if (reuse == MAT_INITIAL_MATRIX) {
10556     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10557 
10558     /* create a supporting struct and attach it to C for reuse */
10559     PetscCall(PetscNew(&redund));
10560     (*matredundant)->redundant = redund;
10561     redund->isrow              = isrow;
10562     redund->iscol              = iscol;
10563     redund->matseq             = matseq;
10564     if (newsubcomm) {
10565       redund->subcomm = subcomm;
10566     } else {
10567       redund->subcomm = MPI_COMM_NULL;
10568     }
10569   } else {
10570     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10571   }
10572 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10573   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10574     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10575     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10576   }
10577 #endif
10578   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10579   PetscFunctionReturn(PETSC_SUCCESS);
10580 }
10581 
10582 /*@C
10583   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10584   a given `Mat`. Each submatrix can span multiple procs.
10585 
10586   Collective
10587 
10588   Input Parameters:
10589 + mat     - the matrix
10590 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10591 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10592 
10593   Output Parameter:
10594 . subMat - parallel sub-matrices each spanning a given `subcomm`
10595 
10596   Level: advanced
10597 
10598   Notes:
10599   The submatrix partition across processors is dictated by `subComm` a
10600   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10601   is not restricted to be grouped with consecutive original MPI processes.
10602 
10603   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10604   map directly to the layout of the original matrix [wrt the local
10605   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10606   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10607   the `subMat`. However the offDiagMat looses some columns - and this is
10608   reconstructed with `MatSetValues()`
10609 
10610   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10611 
10612 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10613 @*/
10614 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10615 {
10616   PetscMPIInt commsize, subCommSize;
10617 
10618   PetscFunctionBegin;
10619   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10620   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10621   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10622 
10623   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");
10624   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10625   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10626   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10627   PetscFunctionReturn(PETSC_SUCCESS);
10628 }
10629 
10630 /*@
10631   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10632 
10633   Not Collective
10634 
10635   Input Parameters:
10636 + mat   - matrix to extract local submatrix from
10637 . isrow - local row indices for submatrix
10638 - iscol - local column indices for submatrix
10639 
10640   Output Parameter:
10641 . submat - the submatrix
10642 
10643   Level: intermediate
10644 
10645   Notes:
10646   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10647 
10648   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10649   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10650 
10651   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10652   `MatSetValuesBlockedLocal()` will also be implemented.
10653 
10654   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10655   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10656 
10657 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10658 @*/
10659 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10660 {
10661   PetscFunctionBegin;
10662   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10663   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10664   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10665   PetscCheckSameComm(isrow, 2, iscol, 3);
10666   PetscAssertPointer(submat, 4);
10667   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10668 
10669   if (mat->ops->getlocalsubmatrix) {
10670     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10671   } else {
10672     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10673   }
10674   PetscFunctionReturn(PETSC_SUCCESS);
10675 }
10676 
10677 /*@
10678   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10679 
10680   Not Collective
10681 
10682   Input Parameters:
10683 + mat    - matrix to extract local submatrix from
10684 . isrow  - local row indices for submatrix
10685 . iscol  - local column indices for submatrix
10686 - submat - the submatrix
10687 
10688   Level: intermediate
10689 
10690 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10691 @*/
10692 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10693 {
10694   PetscFunctionBegin;
10695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10696   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10697   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10698   PetscCheckSameComm(isrow, 2, iscol, 3);
10699   PetscAssertPointer(submat, 4);
10700   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10701 
10702   if (mat->ops->restorelocalsubmatrix) {
10703     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10704   } else {
10705     PetscCall(MatDestroy(submat));
10706   }
10707   *submat = NULL;
10708   PetscFunctionReturn(PETSC_SUCCESS);
10709 }
10710 
10711 /*@
10712   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10713 
10714   Collective
10715 
10716   Input Parameter:
10717 . mat - the matrix
10718 
10719   Output Parameter:
10720 . is - if any rows have zero diagonals this contains the list of them
10721 
10722   Level: developer
10723 
10724 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10725 @*/
10726 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10727 {
10728   PetscFunctionBegin;
10729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10730   PetscValidType(mat, 1);
10731   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10732   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10733 
10734   if (!mat->ops->findzerodiagonals) {
10735     Vec                diag;
10736     const PetscScalar *a;
10737     PetscInt          *rows;
10738     PetscInt           rStart, rEnd, r, nrow = 0;
10739 
10740     PetscCall(MatCreateVecs(mat, &diag, NULL));
10741     PetscCall(MatGetDiagonal(mat, diag));
10742     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10743     PetscCall(VecGetArrayRead(diag, &a));
10744     for (r = 0; r < rEnd - rStart; ++r)
10745       if (a[r] == 0.0) ++nrow;
10746     PetscCall(PetscMalloc1(nrow, &rows));
10747     nrow = 0;
10748     for (r = 0; r < rEnd - rStart; ++r)
10749       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10750     PetscCall(VecRestoreArrayRead(diag, &a));
10751     PetscCall(VecDestroy(&diag));
10752     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10753   } else {
10754     PetscUseTypeMethod(mat, findzerodiagonals, is);
10755   }
10756   PetscFunctionReturn(PETSC_SUCCESS);
10757 }
10758 
10759 /*@
10760   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10761 
10762   Collective
10763 
10764   Input Parameter:
10765 . mat - the matrix
10766 
10767   Output Parameter:
10768 . is - contains the list of rows with off block diagonal entries
10769 
10770   Level: developer
10771 
10772 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10773 @*/
10774 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10775 {
10776   PetscFunctionBegin;
10777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10778   PetscValidType(mat, 1);
10779   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10780   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10781 
10782   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10783   PetscFunctionReturn(PETSC_SUCCESS);
10784 }
10785 
10786 /*@C
10787   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10788 
10789   Collective; No Fortran Support
10790 
10791   Input Parameter:
10792 . mat - the matrix
10793 
10794   Output Parameter:
10795 . values - the block inverses in column major order (FORTRAN-like)
10796 
10797   Level: advanced
10798 
10799   Notes:
10800   The size of the blocks is determined by the block size of the matrix.
10801 
10802   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10803 
10804   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10805 
10806 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10807 @*/
10808 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10809 {
10810   PetscFunctionBegin;
10811   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10812   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10813   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10814   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10815   PetscFunctionReturn(PETSC_SUCCESS);
10816 }
10817 
10818 /*@
10819   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10820 
10821   Collective; No Fortran Support
10822 
10823   Input Parameters:
10824 + mat     - the matrix
10825 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10826 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10827 
10828   Output Parameter:
10829 . values - the block inverses in column major order (FORTRAN-like)
10830 
10831   Level: advanced
10832 
10833   Notes:
10834   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10835 
10836   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10837 
10838 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10839 @*/
10840 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10841 {
10842   PetscFunctionBegin;
10843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10844   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10845   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10846   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10847   PetscFunctionReturn(PETSC_SUCCESS);
10848 }
10849 
10850 /*@
10851   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10852 
10853   Collective
10854 
10855   Input Parameters:
10856 + A - the matrix
10857 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10858 
10859   Level: advanced
10860 
10861   Note:
10862   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10863 
10864 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10865 @*/
10866 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10867 {
10868   const PetscScalar *vals;
10869   PetscInt          *dnnz;
10870   PetscInt           m, rstart, rend, bs, i, j;
10871 
10872   PetscFunctionBegin;
10873   PetscCall(MatInvertBlockDiagonal(A, &vals));
10874   PetscCall(MatGetBlockSize(A, &bs));
10875   PetscCall(MatGetLocalSize(A, &m, NULL));
10876   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10877   PetscCall(PetscMalloc1(m / bs, &dnnz));
10878   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10879   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10880   PetscCall(PetscFree(dnnz));
10881   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10882   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10883   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10884   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10885   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10886   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10887   PetscFunctionReturn(PETSC_SUCCESS);
10888 }
10889 
10890 /*@C
10891   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10892   via `MatTransposeColoringCreate()`.
10893 
10894   Collective
10895 
10896   Input Parameter:
10897 . c - coloring context
10898 
10899   Level: intermediate
10900 
10901 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10902 @*/
10903 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10904 {
10905   MatTransposeColoring matcolor = *c;
10906 
10907   PetscFunctionBegin;
10908   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10909   if (--((PetscObject)matcolor)->refct > 0) {
10910     matcolor = NULL;
10911     PetscFunctionReturn(PETSC_SUCCESS);
10912   }
10913 
10914   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10915   PetscCall(PetscFree(matcolor->rows));
10916   PetscCall(PetscFree(matcolor->den2sp));
10917   PetscCall(PetscFree(matcolor->colorforcol));
10918   PetscCall(PetscFree(matcolor->columns));
10919   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10920   PetscCall(PetscHeaderDestroy(c));
10921   PetscFunctionReturn(PETSC_SUCCESS);
10922 }
10923 
10924 /*@
10925   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10926   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10927   `MatTransposeColoring` to sparse `B`.
10928 
10929   Collective
10930 
10931   Input Parameters:
10932 + coloring - coloring context created with `MatTransposeColoringCreate()`
10933 - B        - sparse matrix
10934 
10935   Output Parameter:
10936 . Btdense - dense matrix $B^T$
10937 
10938   Level: developer
10939 
10940   Note:
10941   These are used internally for some implementations of `MatRARt()`
10942 
10943 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10944 @*/
10945 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10946 {
10947   PetscFunctionBegin;
10948   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10949   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10950   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10951 
10952   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10953   PetscFunctionReturn(PETSC_SUCCESS);
10954 }
10955 
10956 /*@
10957   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10958   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10959   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10960   $C_{sp}$ from $C_{den}$.
10961 
10962   Collective
10963 
10964   Input Parameters:
10965 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10966 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10967 
10968   Output Parameter:
10969 . Csp - sparse matrix
10970 
10971   Level: developer
10972 
10973   Note:
10974   These are used internally for some implementations of `MatRARt()`
10975 
10976 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10977 @*/
10978 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10979 {
10980   PetscFunctionBegin;
10981   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10982   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10983   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10984 
10985   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10986   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10987   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10988   PetscFunctionReturn(PETSC_SUCCESS);
10989 }
10990 
10991 /*@
10992   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10993 
10994   Collective
10995 
10996   Input Parameters:
10997 + mat        - the matrix product C
10998 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10999 
11000   Output Parameter:
11001 . color - the new coloring context
11002 
11003   Level: intermediate
11004 
11005 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11006           `MatTransColoringApplyDenToSp()`
11007 @*/
11008 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11009 {
11010   MatTransposeColoring c;
11011   MPI_Comm             comm;
11012 
11013   PetscFunctionBegin;
11014   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11015   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11016   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11017 
11018   c->ctype = iscoloring->ctype;
11019   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11020 
11021   *color = c;
11022   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11023   PetscFunctionReturn(PETSC_SUCCESS);
11024 }
11025 
11026 /*@
11027   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11028   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11029 
11030   Not Collective
11031 
11032   Input Parameter:
11033 . mat - the matrix
11034 
11035   Output Parameter:
11036 . state - the current state
11037 
11038   Level: intermediate
11039 
11040   Notes:
11041   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11042   different matrices
11043 
11044   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11045 
11046   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11047 
11048 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11049 @*/
11050 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11051 {
11052   PetscFunctionBegin;
11053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11054   *state = mat->nonzerostate;
11055   PetscFunctionReturn(PETSC_SUCCESS);
11056 }
11057 
11058 /*@
11059   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11060   matrices from each processor
11061 
11062   Collective
11063 
11064   Input Parameters:
11065 + comm   - the communicators the parallel matrix will live on
11066 . seqmat - the input sequential matrices
11067 . n      - number of local columns (or `PETSC_DECIDE`)
11068 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11069 
11070   Output Parameter:
11071 . mpimat - the parallel matrix generated
11072 
11073   Level: developer
11074 
11075   Note:
11076   The number of columns of the matrix in EACH processor MUST be the same.
11077 
11078 .seealso: [](ch_matrices), `Mat`
11079 @*/
11080 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11081 {
11082   PetscMPIInt size;
11083 
11084   PetscFunctionBegin;
11085   PetscCallMPI(MPI_Comm_size(comm, &size));
11086   if (size == 1) {
11087     if (reuse == MAT_INITIAL_MATRIX) {
11088       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11089     } else {
11090       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11091     }
11092     PetscFunctionReturn(PETSC_SUCCESS);
11093   }
11094 
11095   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");
11096 
11097   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11098   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11099   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11100   PetscFunctionReturn(PETSC_SUCCESS);
11101 }
11102 
11103 /*@
11104   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11105 
11106   Collective
11107 
11108   Input Parameters:
11109 + A - the matrix to create subdomains from
11110 - N - requested number of subdomains
11111 
11112   Output Parameters:
11113 + n   - number of subdomains resulting on this MPI process
11114 - iss - `IS` list with indices of subdomains on this MPI process
11115 
11116   Level: advanced
11117 
11118   Note:
11119   The number of subdomains must be smaller than the communicator size
11120 
11121 .seealso: [](ch_matrices), `Mat`, `IS`
11122 @*/
11123 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11124 {
11125   MPI_Comm    comm, subcomm;
11126   PetscMPIInt size, rank, color;
11127   PetscInt    rstart, rend, k;
11128 
11129   PetscFunctionBegin;
11130   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11131   PetscCallMPI(MPI_Comm_size(comm, &size));
11132   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11133   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);
11134   *n    = 1;
11135   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11136   color = rank / k;
11137   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11138   PetscCall(PetscMalloc1(1, iss));
11139   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11140   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11141   PetscCallMPI(MPI_Comm_free(&subcomm));
11142   PetscFunctionReturn(PETSC_SUCCESS);
11143 }
11144 
11145 /*@
11146   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11147 
11148   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11149   If they are not the same, uses `MatMatMatMult()`.
11150 
11151   Once the coarse grid problem is constructed, correct for interpolation operators
11152   that are not of full rank, which can legitimately happen in the case of non-nested
11153   geometric multigrid.
11154 
11155   Input Parameters:
11156 + restrct     - restriction operator
11157 . dA          - fine grid matrix
11158 . interpolate - interpolation operator
11159 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11160 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
11161 
11162   Output Parameter:
11163 . A - the Galerkin coarse matrix
11164 
11165   Options Database Key:
11166 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11167 
11168   Level: developer
11169 
11170 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11171 @*/
11172 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11173 {
11174   IS  zerorows;
11175   Vec diag;
11176 
11177   PetscFunctionBegin;
11178   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11179   /* Construct the coarse grid matrix */
11180   if (interpolate == restrct) {
11181     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11182   } else {
11183     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11184   }
11185 
11186   /* If the interpolation matrix is not of full rank, A will have zero rows.
11187      This can legitimately happen in the case of non-nested geometric multigrid.
11188      In that event, we set the rows of the matrix to the rows of the identity,
11189      ignoring the equations (as the RHS will also be zero). */
11190 
11191   PetscCall(MatFindZeroRows(*A, &zerorows));
11192 
11193   if (zerorows != NULL) { /* if there are any zero rows */
11194     PetscCall(MatCreateVecs(*A, &diag, NULL));
11195     PetscCall(MatGetDiagonal(*A, diag));
11196     PetscCall(VecISSet(diag, zerorows, 1.0));
11197     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11198     PetscCall(VecDestroy(&diag));
11199     PetscCall(ISDestroy(&zerorows));
11200   }
11201   PetscFunctionReturn(PETSC_SUCCESS);
11202 }
11203 
11204 /*@C
11205   MatSetOperation - Allows user to set a matrix operation for any matrix type
11206 
11207   Logically Collective
11208 
11209   Input Parameters:
11210 + mat - the matrix
11211 . op  - the name of the operation
11212 - f   - the function that provides the operation
11213 
11214   Level: developer
11215 
11216   Example Usage:
11217 .vb
11218   extern PetscErrorCode usermult(Mat, Vec, Vec);
11219 
11220   PetscCall(MatCreateXXX(comm, ..., &A));
11221   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11222 .ve
11223 
11224   Notes:
11225   See the file `include/petscmat.h` for a complete list of matrix
11226   operations, which all have the form MATOP_<OPERATION>, where
11227   <OPERATION> is the name (in all capital letters) of the
11228   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11229 
11230   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11231   sequence as the usual matrix interface routines, since they
11232   are intended to be accessed via the usual matrix interface
11233   routines, e.g.,
11234 .vb
11235   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11236 .ve
11237 
11238   In particular each function MUST return `PETSC_SUCCESS` on success and
11239   nonzero on failure.
11240 
11241   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11242 
11243 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11244 @*/
11245 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11246 {
11247   PetscFunctionBegin;
11248   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11249   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11250   (((void (**)(void))mat->ops)[op]) = f;
11251   PetscFunctionReturn(PETSC_SUCCESS);
11252 }
11253 
11254 /*@C
11255   MatGetOperation - Gets a matrix operation for any matrix type.
11256 
11257   Not Collective
11258 
11259   Input Parameters:
11260 + mat - the matrix
11261 - op  - the name of the operation
11262 
11263   Output Parameter:
11264 . f - the function that provides the operation
11265 
11266   Level: developer
11267 
11268   Example Usage:
11269 .vb
11270   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11271 
11272   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11273 .ve
11274 
11275   Notes:
11276   See the file include/petscmat.h for a complete list of matrix
11277   operations, which all have the form MATOP_<OPERATION>, where
11278   <OPERATION> is the name (in all capital letters) of the
11279   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11280 
11281   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11282 
11283 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11284 @*/
11285 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11286 {
11287   PetscFunctionBegin;
11288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11289   *f = (((void (**)(void))mat->ops)[op]);
11290   PetscFunctionReturn(PETSC_SUCCESS);
11291 }
11292 
11293 /*@
11294   MatHasOperation - Determines whether the given matrix supports the particular operation.
11295 
11296   Not Collective
11297 
11298   Input Parameters:
11299 + mat - the matrix
11300 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11301 
11302   Output Parameter:
11303 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11304 
11305   Level: advanced
11306 
11307   Note:
11308   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11309 
11310 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11311 @*/
11312 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11313 {
11314   PetscFunctionBegin;
11315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11316   PetscAssertPointer(has, 3);
11317   if (mat->ops->hasoperation) {
11318     PetscUseTypeMethod(mat, hasoperation, op, has);
11319   } else {
11320     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11321     else {
11322       *has = PETSC_FALSE;
11323       if (op == MATOP_CREATE_SUBMATRIX) {
11324         PetscMPIInt size;
11325 
11326         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11327         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11328       }
11329     }
11330   }
11331   PetscFunctionReturn(PETSC_SUCCESS);
11332 }
11333 
11334 /*@
11335   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11336 
11337   Collective
11338 
11339   Input Parameter:
11340 . mat - the matrix
11341 
11342   Output Parameter:
11343 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11344 
11345   Level: beginner
11346 
11347 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11348 @*/
11349 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11350 {
11351   PetscFunctionBegin;
11352   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11353   PetscValidType(mat, 1);
11354   PetscAssertPointer(cong, 2);
11355   if (!mat->rmap || !mat->cmap) {
11356     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11357     PetscFunctionReturn(PETSC_SUCCESS);
11358   }
11359   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11360     PetscCall(PetscLayoutSetUp(mat->rmap));
11361     PetscCall(PetscLayoutSetUp(mat->cmap));
11362     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11363     if (*cong) mat->congruentlayouts = 1;
11364     else mat->congruentlayouts = 0;
11365   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11366   PetscFunctionReturn(PETSC_SUCCESS);
11367 }
11368 
11369 PetscErrorCode MatSetInf(Mat A)
11370 {
11371   PetscFunctionBegin;
11372   PetscUseTypeMethod(A, setinf);
11373   PetscFunctionReturn(PETSC_SUCCESS);
11374 }
11375 
11376 /*@
11377   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
11378   and possibly removes small values from the graph structure.
11379 
11380   Collective
11381 
11382   Input Parameters:
11383 + A       - the matrix
11384 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11385 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11386 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11387 . num_idx - size of 'index' array
11388 - index   - array of block indices to use for graph strength of connection weight
11389 
11390   Output Parameter:
11391 . graph - the resulting graph
11392 
11393   Level: advanced
11394 
11395 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11396 @*/
11397 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11398 {
11399   PetscFunctionBegin;
11400   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11401   PetscValidType(A, 1);
11402   PetscValidLogicalCollectiveBool(A, scale, 3);
11403   PetscAssertPointer(graph, 7);
11404   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11405   PetscFunctionReturn(PETSC_SUCCESS);
11406 }
11407 
11408 /*@
11409   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11410   meaning the same memory is used for the matrix, and no new memory is allocated.
11411 
11412   Collective
11413 
11414   Input Parameters:
11415 + A    - the matrix
11416 - 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
11417 
11418   Level: intermediate
11419 
11420   Developer Note:
11421   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11422   of the arrays in the data structure are unneeded.
11423 
11424 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11425 @*/
11426 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11427 {
11428   PetscFunctionBegin;
11429   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11430   PetscUseTypeMethod(A, eliminatezeros, keep);
11431   PetscFunctionReturn(PETSC_SUCCESS);
11432 }
11433