xref: /petsc/src/mat/interface/matrix.c (revision 9fe822445bcdd45fb93170ff68fa7403d3f52f09)
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_CreateGraph;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52   MatSetRandom - Sets all components of a matrix to random numbers.
53 
54   Logically Collective
55 
56   Input Parameters:
57 + x    - the matrix
58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61   Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68   Level: intermediate
69 
70   Notes:
71   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
72 
73   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
74 
75   It generates an error if used on unassembled sparse matrices that have not been preallocated.
76 
77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
109 
110   Logically Collective
111 
112   Input Parameter:
113 . mat - the factored matrix
114 
115   Output Parameters:
116 + pivot - the pivot value computed
117 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
118          the share the matrix
119 
120   Level: advanced
121 
122   Notes:
123   This routine does not work for factorizations done with external packages.
124 
125   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126 
127   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
128 
129 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
130 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
131 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
132 @*/
133 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
134 {
135   PetscFunctionBegin;
136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
137   PetscAssertPointer(pivot, 2);
138   PetscAssertPointer(row, 3);
139   *pivot = mat->factorerror_zeropivot_value;
140   *row   = mat->factorerror_zeropivot_row;
141   PetscFunctionReturn(PETSC_SUCCESS);
142 }
143 
144 /*@
145   MatFactorGetError - gets the error code from a factorization
146 
147   Logically Collective
148 
149   Input Parameter:
150 . mat - the factored matrix
151 
152   Output Parameter:
153 . err - the error code
154 
155   Level: advanced
156 
157   Note:
158   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
159 
160 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
161           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
162 @*/
163 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
164 {
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
167   PetscAssertPointer(err, 2);
168   *err = mat->factorerrortype;
169   PetscFunctionReturn(PETSC_SUCCESS);
170 }
171 
172 /*@
173   MatFactorClearError - clears the error code in a factorization
174 
175   Logically Collective
176 
177   Input Parameter:
178 . mat - the factored matrix
179 
180   Level: developer
181 
182   Note:
183   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
184 
185 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
186           `MatGetErrorCode()`, `MatFactorError`
187 @*/
188 PetscErrorCode MatFactorClearError(Mat mat)
189 {
190   PetscFunctionBegin;
191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
192   mat->factorerrortype             = MAT_FACTOR_NOERROR;
193   mat->factorerror_zeropivot_value = 0.0;
194   mat->factorerror_zeropivot_row   = 0;
195   PetscFunctionReturn(PETSC_SUCCESS);
196 }
197 
198 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
199 {
200   Vec                r, l;
201   const PetscScalar *al;
202   PetscInt           i, nz, gnz, N, n, st;
203 
204   PetscFunctionBegin;
205   PetscCall(MatCreateVecs(mat, &r, &l));
206   if (!cols) { /* nonzero rows */
207     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
208     PetscCall(MatGetSize(mat, &N, NULL));
209     PetscCall(MatGetLocalSize(mat, &n, NULL));
210     PetscCall(VecSet(l, 0.0));
211     PetscCall(VecSetRandom(r, NULL));
212     PetscCall(MatMult(mat, r, l));
213     PetscCall(VecGetArrayRead(l, &al));
214   } else { /* nonzero columns */
215     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
216     PetscCall(MatGetSize(mat, NULL, &N));
217     PetscCall(MatGetLocalSize(mat, NULL, &n));
218     PetscCall(VecSet(r, 0.0));
219     PetscCall(VecSetRandom(l, NULL));
220     PetscCall(MatMultTranspose(mat, l, r));
221     PetscCall(VecGetArrayRead(r, &al));
222   }
223   if (tol <= 0.0) {
224     for (i = 0, nz = 0; i < n; i++)
225       if (al[i] != 0.0) nz++;
226   } else {
227     for (i = 0, nz = 0; i < n; i++)
228       if (PetscAbsScalar(al[i]) > tol) nz++;
229   }
230   PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
231   if (gnz != N) {
232     PetscInt *nzr;
233     PetscCall(PetscMalloc1(nz, &nzr));
234     if (nz) {
235       if (tol < 0) {
236         for (i = 0, nz = 0; i < n; i++)
237           if (al[i] != 0.0) nzr[nz++] = i + st;
238       } else {
239         for (i = 0, nz = 0; i < n; i++)
240           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
241       }
242     }
243     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
244   } else *nonzero = NULL;
245   if (!cols) { /* nonzero rows */
246     PetscCall(VecRestoreArrayRead(l, &al));
247   } else {
248     PetscCall(VecRestoreArrayRead(r, &al));
249   }
250   PetscCall(VecDestroy(&l));
251   PetscCall(VecDestroy(&r));
252   PetscFunctionReturn(PETSC_SUCCESS);
253 }
254 
255 /*@
256   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
257 
258   Input Parameter:
259 . mat - the matrix
260 
261   Output Parameter:
262 . keptrows - the rows that are not completely zero
263 
264   Level: intermediate
265 
266   Note:
267   `keptrows` is set to `NULL` if all rows are nonzero.
268 
269   Developer Note:
270   If `keptrows` is not `NULL`, it must be sorted.
271 
272 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
273  @*/
274 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
275 {
276   PetscFunctionBegin;
277   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
278   PetscValidType(mat, 1);
279   PetscAssertPointer(keptrows, 2);
280   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
281   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
282   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
283   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
284   if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
285   PetscFunctionReturn(PETSC_SUCCESS);
286 }
287 
288 /*@
289   MatFindZeroRows - Locate all rows that are completely zero in the matrix
290 
291   Input Parameter:
292 . mat - the matrix
293 
294   Output Parameter:
295 . zerorows - the rows that are completely zero
296 
297   Level: intermediate
298 
299   Note:
300   `zerorows` is set to `NULL` if no rows are zero.
301 
302 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
303  @*/
304 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
305 {
306   IS       keptrows;
307   PetscInt m, n;
308 
309   PetscFunctionBegin;
310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
311   PetscValidType(mat, 1);
312   PetscAssertPointer(zerorows, 2);
313   PetscCall(MatFindNonzeroRows(mat, &keptrows));
314   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
315      In keeping with this convention, we set zerorows to NULL if there are no zero
316      rows. */
317   if (keptrows == NULL) {
318     *zerorows = NULL;
319   } else {
320     PetscCall(MatGetOwnershipRange(mat, &m, &n));
321     PetscCall(ISComplement(keptrows, m, n, zerorows));
322     PetscCall(ISDestroy(&keptrows));
323   }
324   PetscFunctionReturn(PETSC_SUCCESS);
325 }
326 
327 /*@
328   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
329 
330   Not Collective
331 
332   Input Parameter:
333 . A - the matrix
334 
335   Output Parameter:
336 . a - the diagonal part (which is a SEQUENTIAL matrix)
337 
338   Level: advanced
339 
340   Notes:
341   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
342 
343   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
344 
345 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
346 @*/
347 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
348 {
349   PetscFunctionBegin;
350   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
351   PetscValidType(A, 1);
352   PetscAssertPointer(a, 2);
353   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
354   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
355   else {
356     PetscMPIInt size;
357 
358     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
359     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
360     *a = A;
361   }
362   PetscFunctionReturn(PETSC_SUCCESS);
363 }
364 
365 /*@
366   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
367 
368   Collective
369 
370   Input Parameter:
371 . mat - the matrix
372 
373   Output Parameter:
374 . trace - the sum of the diagonal entries
375 
376   Level: advanced
377 
378 .seealso: [](ch_matrices), `Mat`
379 @*/
380 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
381 {
382   Vec diag;
383 
384   PetscFunctionBegin;
385   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
386   PetscAssertPointer(trace, 2);
387   PetscCall(MatCreateVecs(mat, &diag, NULL));
388   PetscCall(MatGetDiagonal(mat, diag));
389   PetscCall(VecSum(diag, trace));
390   PetscCall(VecDestroy(&diag));
391   PetscFunctionReturn(PETSC_SUCCESS);
392 }
393 
394 /*@
395   MatRealPart - Zeros out the imaginary part of the matrix
396 
397   Logically Collective
398 
399   Input Parameter:
400 . mat - the matrix
401 
402   Level: advanced
403 
404 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
405 @*/
406 PetscErrorCode MatRealPart(Mat mat)
407 {
408   PetscFunctionBegin;
409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
410   PetscValidType(mat, 1);
411   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
412   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
413   MatCheckPreallocated(mat, 1);
414   PetscUseTypeMethod(mat, realpart);
415   PetscFunctionReturn(PETSC_SUCCESS);
416 }
417 
418 /*@C
419   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
420 
421   Collective
422 
423   Input Parameter:
424 . mat - the matrix
425 
426   Output Parameters:
427 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
428 - ghosts  - the global indices of the ghost points
429 
430   Level: advanced
431 
432   Note:
433   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
434 
435 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
436 @*/
437 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
438 {
439   PetscFunctionBegin;
440   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
441   PetscValidType(mat, 1);
442   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
443   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
444   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
445   else {
446     if (nghosts) *nghosts = 0;
447     if (ghosts) *ghosts = NULL;
448   }
449   PetscFunctionReturn(PETSC_SUCCESS);
450 }
451 
452 /*@
453   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
454 
455   Logically Collective
456 
457   Input Parameter:
458 . mat - the matrix
459 
460   Level: advanced
461 
462 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
463 @*/
464 PetscErrorCode MatImaginaryPart(Mat mat)
465 {
466   PetscFunctionBegin;
467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
468   PetscValidType(mat, 1);
469   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
470   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
471   MatCheckPreallocated(mat, 1);
472   PetscUseTypeMethod(mat, imaginarypart);
473   PetscFunctionReturn(PETSC_SUCCESS);
474 }
475 
476 /*@
477   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
478 
479   Not Collective
480 
481   Input Parameter:
482 . mat - the matrix
483 
484   Output Parameters:
485 + missing - is any diagonal entry missing
486 - dd      - first diagonal entry that is missing (optional) on this process
487 
488   Level: advanced
489 
490   Note:
491   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
492 
493 .seealso: [](ch_matrices), `Mat`
494 @*/
495 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
496 {
497   PetscFunctionBegin;
498   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
499   PetscValidType(mat, 1);
500   PetscAssertPointer(missing, 2);
501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
503   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
504   PetscFunctionReturn(PETSC_SUCCESS);
505 }
506 
507 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
508 /*@C
509   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
510   for each row that you get to ensure that your application does
511   not bleed memory.
512 
513   Not Collective
514 
515   Input Parameters:
516 + mat - the matrix
517 - row - the row to get
518 
519   Output Parameters:
520 + ncols - if not `NULL`, the number of nonzeros in `row`
521 . cols  - if not `NULL`, the column numbers
522 - vals  - if not `NULL`, the numerical values
523 
524   Level: advanced
525 
526   Notes:
527   This routine is provided for people who need to have direct access
528   to the structure of a matrix.  We hope that we provide enough
529   high-level matrix routines that few users will need it.
530 
531   `MatGetRow()` always returns 0-based column indices, regardless of
532   whether the internal representation is 0-based (default) or 1-based.
533 
534   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
535   not wish to extract these quantities.
536 
537   The user can only examine the values extracted with `MatGetRow()`;
538   the values CANNOT be altered.  To change the matrix entries, one
539   must use `MatSetValues()`.
540 
541   You can only have one call to `MatGetRow()` outstanding for a particular
542   matrix at a time, per processor. `MatGetRow()` can only obtain rows
543   associated with the given processor, it cannot get rows from the
544   other processors; for that we suggest using `MatCreateSubMatrices()`, then
545   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
546   is in the global number of rows.
547 
548   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
549 
550   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
551 
552   Fortran Note:
553   The calling sequence is
554 .vb
555    MatGetRow(matrix,row,ncols,cols,values,ierr)
556          Mat         matrix (input)
557          PetscInt    row    (input)
558          PetscInt    ncols  (output)
559          PetscInt    cols(maxcols) (output)
560          PetscScalar values(maxcols) output
561 .ve
562   where maxcols >= maximum nonzeros in any row of the matrix.
563 
564 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
565 @*/
566 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
567 {
568   PetscInt incols;
569 
570   PetscFunctionBegin;
571   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
572   PetscValidType(mat, 1);
573   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
574   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
575   MatCheckPreallocated(mat, 1);
576   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);
577   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
578   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
579   if (ncols) *ncols = incols;
580   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
581   PetscFunctionReturn(PETSC_SUCCESS);
582 }
583 
584 /*@
585   MatConjugate - replaces the matrix values with their complex conjugates
586 
587   Logically Collective
588 
589   Input Parameter:
590 . mat - the matrix
591 
592   Level: advanced
593 
594 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
595 @*/
596 PetscErrorCode MatConjugate(Mat mat)
597 {
598   PetscFunctionBegin;
599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
600   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
601   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
602     PetscUseTypeMethod(mat, conjugate);
603     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
604   }
605   PetscFunctionReturn(PETSC_SUCCESS);
606 }
607 
608 /*@C
609   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
610 
611   Not Collective
612 
613   Input Parameters:
614 + mat   - the matrix
615 . row   - the row to get
616 . ncols - the number of nonzeros
617 . cols  - the columns of the nonzeros
618 - vals  - if nonzero the column values
619 
620   Level: advanced
621 
622   Notes:
623   This routine should be called after you have finished examining the entries.
624 
625   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
626   us of the array after it has been restored. If you pass `NULL`, it will
627   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
628 
629   Fortran Note:
630   `MatRestoreRow()` MUST be called after `MatGetRow()`
631   before another call to `MatGetRow()` can be made.
632 
633 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
634 @*/
635 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
636 {
637   PetscFunctionBegin;
638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
639   if (ncols) PetscAssertPointer(ncols, 3);
640   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
641   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
642   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
643   if (ncols) *ncols = 0;
644   if (cols) *cols = NULL;
645   if (vals) *vals = NULL;
646   PetscFunctionReturn(PETSC_SUCCESS);
647 }
648 
649 /*@
650   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
651   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
652 
653   Not Collective
654 
655   Input Parameter:
656 . mat - the matrix
657 
658   Level: advanced
659 
660   Note:
661   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.
662 
663 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
664 @*/
665 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
666 {
667   PetscFunctionBegin;
668   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
669   PetscValidType(mat, 1);
670   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
671   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
672   MatCheckPreallocated(mat, 1);
673   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
674   PetscUseTypeMethod(mat, getrowuppertriangular);
675   PetscFunctionReturn(PETSC_SUCCESS);
676 }
677 
678 /*@
679   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
680 
681   Not Collective
682 
683   Input Parameter:
684 . mat - the matrix
685 
686   Level: advanced
687 
688   Note:
689   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
690 
691 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
692 @*/
693 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
694 {
695   PetscFunctionBegin;
696   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
697   PetscValidType(mat, 1);
698   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
699   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
700   MatCheckPreallocated(mat, 1);
701   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
702   PetscUseTypeMethod(mat, restorerowuppertriangular);
703   PetscFunctionReturn(PETSC_SUCCESS);
704 }
705 
706 /*@
707   MatSetOptionsPrefix - Sets the prefix used for searching for all
708   `Mat` options in the database.
709 
710   Logically Collective
711 
712   Input Parameters:
713 + A      - the matrix
714 - prefix - the prefix to prepend to all option names
715 
716   Level: advanced
717 
718   Notes:
719   A hyphen (-) must NOT be given at the beginning of the prefix name.
720   The first character of all runtime options is AUTOMATICALLY the hyphen.
721 
722   This is NOT used for options for the factorization of the matrix. Normally the
723   prefix is automatically passed in from the PC calling the factorization. To set
724   it directly use  `MatSetOptionsPrefixFactor()`
725 
726 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
727 @*/
728 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
729 {
730   PetscFunctionBegin;
731   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
732   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
733   PetscFunctionReturn(PETSC_SUCCESS);
734 }
735 
736 /*@
737   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
738   for matrices created with `MatGetFactor()`
739 
740   Logically Collective
741 
742   Input Parameters:
743 + A      - the matrix
744 - prefix - the prefix to prepend to all option names for the factored matrix
745 
746   Level: developer
747 
748   Notes:
749   A hyphen (-) must NOT be given at the beginning of the prefix name.
750   The first character of all runtime options is AUTOMATICALLY the hyphen.
751 
752   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
753   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
754 
755 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
756 @*/
757 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
758 {
759   PetscFunctionBegin;
760   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
761   if (prefix) {
762     PetscAssertPointer(prefix, 2);
763     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
764     if (prefix != A->factorprefix) {
765       PetscCall(PetscFree(A->factorprefix));
766       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
767     }
768   } else PetscCall(PetscFree(A->factorprefix));
769   PetscFunctionReturn(PETSC_SUCCESS);
770 }
771 
772 /*@
773   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
774   for matrices created with `MatGetFactor()`
775 
776   Logically Collective
777 
778   Input Parameters:
779 + A      - the matrix
780 - prefix - the prefix to prepend to all option names for the factored matrix
781 
782   Level: developer
783 
784   Notes:
785   A hyphen (-) must NOT be given at the beginning of the prefix name.
786   The first character of all runtime options is AUTOMATICALLY the hyphen.
787 
788   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
789   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
790 
791 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
792           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
793           `MatSetOptionsPrefix()`
794 @*/
795 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
796 {
797   size_t len1, len2, new_len;
798 
799   PetscFunctionBegin;
800   PetscValidHeader(A, 1);
801   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
802   if (!A->factorprefix) {
803     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
804     PetscFunctionReturn(PETSC_SUCCESS);
805   }
806   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
807 
808   PetscCall(PetscStrlen(A->factorprefix, &len1));
809   PetscCall(PetscStrlen(prefix, &len2));
810   new_len = len1 + len2 + 1;
811   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
812   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
813   PetscFunctionReturn(PETSC_SUCCESS);
814 }
815 
816 /*@
817   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
818   matrix options in the database.
819 
820   Logically Collective
821 
822   Input Parameters:
823 + A      - the matrix
824 - prefix - the prefix to prepend to all option names
825 
826   Level: advanced
827 
828   Note:
829   A hyphen (-) must NOT be given at the beginning of the prefix name.
830   The first character of all runtime options is AUTOMATICALLY the hyphen.
831 
832 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
833 @*/
834 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
835 {
836   PetscFunctionBegin;
837   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
838   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
839   PetscFunctionReturn(PETSC_SUCCESS);
840 }
841 
842 /*@
843   MatGetOptionsPrefix - Gets the prefix used for searching for all
844   matrix options in the database.
845 
846   Not Collective
847 
848   Input Parameter:
849 . A - the matrix
850 
851   Output Parameter:
852 . prefix - pointer to the prefix string used
853 
854   Level: advanced
855 
856   Fortran Note:
857   The user should pass in a string `prefix` of
858   sufficient length to hold the prefix.
859 
860 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
861 @*/
862 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
863 {
864   PetscFunctionBegin;
865   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
866   PetscAssertPointer(prefix, 2);
867   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
868   PetscFunctionReturn(PETSC_SUCCESS);
869 }
870 
871 /*@
872   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
873 
874   Not Collective
875 
876   Input Parameter:
877 . A - the matrix
878 
879   Output Parameter:
880 . state - the object state
881 
882   Level: advanced
883 
884   Note:
885   Object state is an integer which gets increased every time
886   the object is changed. By saving and later querying the object state
887   one can determine whether information about the object is still current.
888 
889   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
890 
891 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
892 @*/
893 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscAssertPointer(state, 2);
898   PetscCall(PetscObjectStateGet((PetscObject)A, state));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 /*@
903   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
904 
905   Collective
906 
907   Input Parameter:
908 . A - the matrix
909 
910   Level: beginner
911 
912   Notes:
913   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
914   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
915   makes all of the preallocation space available
916 
917   Current values in the matrix are lost in this call
918 
919   Currently only supported for  `MATAIJ` matrices.
920 
921 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
922 @*/
923 PetscErrorCode MatResetPreallocation(Mat A)
924 {
925   PetscFunctionBegin;
926   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
927   PetscValidType(A, 1);
928   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
929   PetscFunctionReturn(PETSC_SUCCESS);
930 }
931 
932 /*@
933   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
934 
935   Collective
936 
937   Input Parameter:
938 . A - the matrix
939 
940   Level: advanced
941 
942   Notes:
943   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
944   setting values in the matrix.
945 
946   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
947 
948 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
949 @*/
950 PetscErrorCode MatSetUp(Mat A)
951 {
952   PetscFunctionBegin;
953   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
954   if (!((PetscObject)A)->type_name) {
955     PetscMPIInt size;
956 
957     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
958     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
959   }
960   if (!A->preallocated) PetscTryTypeMethod(A, setup);
961   PetscCall(PetscLayoutSetUp(A->rmap));
962   PetscCall(PetscLayoutSetUp(A->cmap));
963   A->preallocated = PETSC_TRUE;
964   PetscFunctionReturn(PETSC_SUCCESS);
965 }
966 
967 #if defined(PETSC_HAVE_SAWS)
968   #include <petscviewersaws.h>
969 #endif
970 
971 /*
972    If threadsafety is on extraneous matrices may be printed
973 
974    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
975 */
976 #if !defined(PETSC_HAVE_THREADSAFETY)
977 static PetscInt insidematview = 0;
978 #endif
979 
980 /*@
981   MatViewFromOptions - View properties of the matrix based on options set in the options database
982 
983   Collective
984 
985   Input Parameters:
986 + A    - the matrix
987 . obj  - optional additional object that provides the options prefix to use
988 - name - command line option
989 
990   Options Database Key:
991 . -mat_view [viewertype]:... - the viewer and its options
992 
993   Level: intermediate
994 
995   Note:
996 .vb
997     If no value is provided ascii:stdout is used
998        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
999                                                   for example ascii::ascii_info prints just the information about the object not all details
1000                                                   unless :append is given filename opens in write mode, overwriting what was already there
1001        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1002        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1003        socket[:port]                             defaults to the standard output port
1004        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1005 .ve
1006 
1007 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1008 @*/
1009 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1010 {
1011   PetscFunctionBegin;
1012   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1013 #if !defined(PETSC_HAVE_THREADSAFETY)
1014   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1015 #endif
1016   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1017   PetscFunctionReturn(PETSC_SUCCESS);
1018 }
1019 
1020 /*@
1021   MatView - display information about a matrix in a variety ways
1022 
1023   Collective on viewer
1024 
1025   Input Parameters:
1026 + mat    - the matrix
1027 - viewer - visualization context
1028 
1029   Options Database Keys:
1030 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1031 . -mat_view ::ascii_info_detail    - Prints more detailed info
1032 . -mat_view                        - Prints matrix in ASCII format
1033 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1034 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1035 . -display <name>                  - Sets display name (default is host)
1036 . -draw_pause <sec>                - Sets number of seconds to pause after display
1037 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1038 . -viewer_socket_machine <machine> - -
1039 . -viewer_socket_port <port>       - -
1040 . -mat_view binary                 - save matrix to file in binary format
1041 - -viewer_binary_filename <name>   - -
1042 
1043   Level: beginner
1044 
1045   Notes:
1046   The available visualization contexts include
1047 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1048 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1049 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1050 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1051 
1052   The user can open alternative visualization contexts with
1053 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1054 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1055 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1056 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1057 
1058   The user can call `PetscViewerPushFormat()` to specify the output
1059   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1060   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1061 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1062 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1063 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1064 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1065 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1066 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1067 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1068 
1069   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1070   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1071 
1072   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1073 
1074   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1075   viewer is used.
1076 
1077   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1078   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1079 
1080   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1081   and then use the following mouse functions.
1082 .vb
1083   left mouse: zoom in
1084   middle mouse: zoom out
1085   right mouse: continue with the simulation
1086 .ve
1087 
1088 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1089           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1090 @*/
1091 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1092 {
1093   PetscInt          rows, cols, rbs, cbs;
1094   PetscBool         isascii, isstring, issaws;
1095   PetscViewerFormat format;
1096   PetscMPIInt       size;
1097 
1098   PetscFunctionBegin;
1099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1100   PetscValidType(mat, 1);
1101   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1102   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1103 
1104   PetscCall(PetscViewerGetFormat(viewer, &format));
1105   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1106   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1107 
1108 #if !defined(PETSC_HAVE_THREADSAFETY)
1109   insidematview++;
1110 #endif
1111   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1112   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1113   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1114   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");
1115 
1116   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1117   if (isascii) {
1118     if (!mat->preallocated) {
1119       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1120 #if !defined(PETSC_HAVE_THREADSAFETY)
1121       insidematview--;
1122 #endif
1123       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1124       PetscFunctionReturn(PETSC_SUCCESS);
1125     }
1126     if (!mat->assembled) {
1127       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1128 #if !defined(PETSC_HAVE_THREADSAFETY)
1129       insidematview--;
1130 #endif
1131       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1132       PetscFunctionReturn(PETSC_SUCCESS);
1133     }
1134     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1135     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1136       MatNullSpace nullsp, transnullsp;
1137 
1138       PetscCall(PetscViewerASCIIPushTab(viewer));
1139       PetscCall(MatGetSize(mat, &rows, &cols));
1140       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1141       if (rbs != 1 || cbs != 1) {
1142         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" : ""));
1143         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1144       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1145       if (mat->factortype) {
1146         MatSolverType solver;
1147         PetscCall(MatFactorGetSolverType(mat, &solver));
1148         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1149       }
1150       if (mat->ops->getinfo) {
1151         MatInfo info;
1152         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1153         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1154         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1155       }
1156       PetscCall(MatGetNullSpace(mat, &nullsp));
1157       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1158       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1159       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1160       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1161       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1162       PetscCall(PetscViewerASCIIPushTab(viewer));
1163       PetscCall(MatProductView(mat, viewer));
1164       PetscCall(PetscViewerASCIIPopTab(viewer));
1165       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1166         IS tmp;
1167 
1168         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1169         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1170         PetscCall(PetscViewerASCIIPushTab(viewer));
1171         PetscCall(ISView(tmp, viewer));
1172         PetscCall(PetscViewerASCIIPopTab(viewer));
1173         PetscCall(ISDestroy(&tmp));
1174       }
1175     }
1176   } else if (issaws) {
1177 #if defined(PETSC_HAVE_SAWS)
1178     PetscMPIInt rank;
1179 
1180     PetscCall(PetscObjectName((PetscObject)mat));
1181     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1182     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1183 #endif
1184   } else if (isstring) {
1185     const char *type;
1186     PetscCall(MatGetType(mat, &type));
1187     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1188     PetscTryTypeMethod(mat, view, viewer);
1189   }
1190   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1191     PetscCall(PetscViewerASCIIPushTab(viewer));
1192     PetscUseTypeMethod(mat, viewnative, viewer);
1193     PetscCall(PetscViewerASCIIPopTab(viewer));
1194   } else if (mat->ops->view) {
1195     PetscCall(PetscViewerASCIIPushTab(viewer));
1196     PetscUseTypeMethod(mat, view, viewer);
1197     PetscCall(PetscViewerASCIIPopTab(viewer));
1198   }
1199   if (isascii) {
1200     PetscCall(PetscViewerGetFormat(viewer, &format));
1201     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1202   }
1203   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1204 #if !defined(PETSC_HAVE_THREADSAFETY)
1205   insidematview--;
1206 #endif
1207   PetscFunctionReturn(PETSC_SUCCESS);
1208 }
1209 
1210 #if defined(PETSC_USE_DEBUG)
1211   #include <../src/sys/totalview/tv_data_display.h>
1212 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1213 {
1214   TV_add_row("Local rows", "int", &mat->rmap->n);
1215   TV_add_row("Local columns", "int", &mat->cmap->n);
1216   TV_add_row("Global rows", "int", &mat->rmap->N);
1217   TV_add_row("Global columns", "int", &mat->cmap->N);
1218   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1219   return TV_format_OK;
1220 }
1221 #endif
1222 
1223 /*@
1224   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1225   with `MatView()`.  The matrix format is determined from the options database.
1226   Generates a parallel MPI matrix if the communicator has more than one
1227   processor.  The default matrix type is `MATAIJ`.
1228 
1229   Collective
1230 
1231   Input Parameters:
1232 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1233             or some related function before a call to `MatLoad()`
1234 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1235 
1236   Options Database Key:
1237 . -matload_block_size <bs> - set block size
1238 
1239   Level: beginner
1240 
1241   Notes:
1242   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1243   `Mat` before calling this routine if you wish to set it from the options database.
1244 
1245   `MatLoad()` automatically loads into the options database any options
1246   given in the file filename.info where filename is the name of the file
1247   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1248   file will be ignored if you use the -viewer_binary_skip_info option.
1249 
1250   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1251   sets the default matrix type AIJ and sets the local and global sizes.
1252   If type and/or size is already set, then the same are used.
1253 
1254   In parallel, each processor can load a subset of rows (or the
1255   entire matrix).  This routine is especially useful when a large
1256   matrix is stored on disk and only part of it is desired on each
1257   processor.  For example, a parallel solver may access only some of
1258   the rows from each processor.  The algorithm used here reads
1259   relatively small blocks of data rather than reading the entire
1260   matrix and then subsetting it.
1261 
1262   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1263   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1264   or the sequence like
1265 .vb
1266     `PetscViewer` v;
1267     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1268     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1269     `PetscViewerSetFromOptions`(v);
1270     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1271     `PetscViewerFileSetName`(v,"datafile");
1272 .ve
1273   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1274 $ -viewer_type {binary, hdf5}
1275 
1276   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1277   and src/mat/tutorials/ex10.c with the second approach.
1278 
1279   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1280   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1281   Multiple objects, both matrices and vectors, can be stored within the same file.
1282   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1283 
1284   Most users should not need to know the details of the binary storage
1285   format, since `MatLoad()` and `MatView()` completely hide these details.
1286   But for anyone who is interested, the standard binary matrix storage
1287   format is
1288 
1289 .vb
1290     PetscInt    MAT_FILE_CLASSID
1291     PetscInt    number of rows
1292     PetscInt    number of columns
1293     PetscInt    total number of nonzeros
1294     PetscInt    *number nonzeros in each row
1295     PetscInt    *column indices of all nonzeros (starting index is zero)
1296     PetscScalar *values of all nonzeros
1297 .ve
1298   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1299   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
1300   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1301 
1302   PETSc automatically does the byte swapping for
1303   machines that store the bytes reversed. Thus if you write your own binary
1304   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1305   and `PetscBinaryWrite()` to see how this may be done.
1306 
1307   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1308   Each processor's chunk is loaded independently by its owning MPI process.
1309   Multiple objects, both matrices and vectors, can be stored within the same file.
1310   They are looked up by their PetscObject name.
1311 
1312   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1313   by default the same structure and naming of the AIJ arrays and column count
1314   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1315 $    save example.mat A b -v7.3
1316   can be directly read by this routine (see Reference 1 for details).
1317 
1318   Depending on your MATLAB version, this format might be a default,
1319   otherwise you can set it as default in Preferences.
1320 
1321   Unless -nocompression flag is used to save the file in MATLAB,
1322   PETSc must be configured with ZLIB package.
1323 
1324   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1325 
1326   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1327 
1328   Corresponding `MatView()` is not yet implemented.
1329 
1330   The loaded matrix is actually a transpose of the original one in MATLAB,
1331   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1332   With this format, matrix is automatically transposed by PETSc,
1333   unless the matrix is marked as SPD or symmetric
1334   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1335 
1336   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1337 
1338 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1339  @*/
1340 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1341 {
1342   PetscBool flg;
1343 
1344   PetscFunctionBegin;
1345   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1346   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1347 
1348   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1349 
1350   flg = PETSC_FALSE;
1351   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1352   if (flg) {
1353     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1354     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1355   }
1356   flg = PETSC_FALSE;
1357   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1358   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1359 
1360   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1361   PetscUseTypeMethod(mat, load, viewer);
1362   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1363   PetscFunctionReturn(PETSC_SUCCESS);
1364 }
1365 
1366 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1367 {
1368   Mat_Redundant *redund = *redundant;
1369 
1370   PetscFunctionBegin;
1371   if (redund) {
1372     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1373       PetscCall(ISDestroy(&redund->isrow));
1374       PetscCall(ISDestroy(&redund->iscol));
1375       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1376     } else {
1377       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1378       PetscCall(PetscFree(redund->sbuf_j));
1379       PetscCall(PetscFree(redund->sbuf_a));
1380       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1381         PetscCall(PetscFree(redund->rbuf_j[i]));
1382         PetscCall(PetscFree(redund->rbuf_a[i]));
1383       }
1384       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1385     }
1386 
1387     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1388     PetscCall(PetscFree(redund));
1389   }
1390   PetscFunctionReturn(PETSC_SUCCESS);
1391 }
1392 
1393 /*@
1394   MatDestroy - Frees space taken by a matrix.
1395 
1396   Collective
1397 
1398   Input Parameter:
1399 . A - the matrix
1400 
1401   Level: beginner
1402 
1403   Developer Note:
1404   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1405   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1406   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1407   if changes are needed here.
1408 
1409 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1410 @*/
1411 PetscErrorCode MatDestroy(Mat *A)
1412 {
1413   PetscFunctionBegin;
1414   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1415   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1416   if (--((PetscObject)*A)->refct > 0) {
1417     *A = NULL;
1418     PetscFunctionReturn(PETSC_SUCCESS);
1419   }
1420 
1421   /* if memory was published with SAWs then destroy it */
1422   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1423   PetscTryTypeMethod(*A, destroy);
1424 
1425   PetscCall(PetscFree((*A)->factorprefix));
1426   PetscCall(PetscFree((*A)->defaultvectype));
1427   PetscCall(PetscFree((*A)->defaultrandtype));
1428   PetscCall(PetscFree((*A)->bsizes));
1429   PetscCall(PetscFree((*A)->solvertype));
1430   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1431   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1432   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1433   PetscCall(MatProductClear(*A));
1434   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1435   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1436   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1437   PetscCall(MatDestroy(&(*A)->schur));
1438   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1439   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1440   PetscCall(PetscHeaderDestroy(A));
1441   PetscFunctionReturn(PETSC_SUCCESS);
1442 }
1443 
1444 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1445 /*@
1446   MatSetValues - Inserts or adds a block of values into a matrix.
1447   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1448   MUST be called after all calls to `MatSetValues()` have been completed.
1449 
1450   Not Collective
1451 
1452   Input Parameters:
1453 + mat  - the matrix
1454 . v    - a logically two-dimensional array of values
1455 . m    - the number of rows
1456 . idxm - the global indices of the rows
1457 . n    - the number of columns
1458 . idxn - the global indices of the columns
1459 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1460 
1461   Level: beginner
1462 
1463   Notes:
1464   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1465 
1466   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1467   options cannot be mixed without intervening calls to the assembly
1468   routines.
1469 
1470   `MatSetValues()` uses 0-based row and column numbers in Fortran
1471   as well as in C.
1472 
1473   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1474   simply ignored. This allows easily inserting element stiffness matrices
1475   with homogeneous Dirichlet boundary conditions that you don't want represented
1476   in the matrix.
1477 
1478   Efficiency Alert:
1479   The routine `MatSetValuesBlocked()` may offer much better efficiency
1480   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1481 
1482   Fortran Notes:
1483   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1484 .vb
1485   MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
1486 .ve
1487 
1488   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1489 
1490   Developer Note:
1491   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1492   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1493 
1494 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1495           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1496 @*/
1497 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1498 {
1499   PetscFunctionBeginHot;
1500   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1501   PetscValidType(mat, 1);
1502   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1503   PetscAssertPointer(idxm, 3);
1504   PetscAssertPointer(idxn, 5);
1505   MatCheckPreallocated(mat, 1);
1506 
1507   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1508   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1509 
1510   if (PetscDefined(USE_DEBUG)) {
1511     PetscInt i, j;
1512 
1513     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1514     if (v) {
1515       for (i = 0; i < m; i++) {
1516         for (j = 0; j < n; j++) {
1517           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1518 #if defined(PETSC_USE_COMPLEX)
1519             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]);
1520 #else
1521             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]);
1522 #endif
1523         }
1524       }
1525     }
1526     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);
1527     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);
1528   }
1529 
1530   if (mat->assembled) {
1531     mat->was_assembled = PETSC_TRUE;
1532     mat->assembled     = PETSC_FALSE;
1533   }
1534   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1535   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1536   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1537   PetscFunctionReturn(PETSC_SUCCESS);
1538 }
1539 
1540 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1541 /*@
1542   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1543   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1544   MUST be called after all calls to `MatSetValues()` have been completed.
1545 
1546   Not Collective
1547 
1548   Input Parameters:
1549 + mat  - the matrix
1550 . v    - a logically two-dimensional array of values
1551 . ism  - the rows to provide
1552 . isn  - the columns to provide
1553 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1554 
1555   Level: beginner
1556 
1557   Notes:
1558   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1559 
1560   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1561   options cannot be mixed without intervening calls to the assembly
1562   routines.
1563 
1564   `MatSetValues()` uses 0-based row and column numbers in Fortran
1565   as well as in C.
1566 
1567   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1568   simply ignored. This allows easily inserting element stiffness matrices
1569   with homogeneous Dirichlet boundary conditions that you don't want represented
1570   in the matrix.
1571 
1572   Efficiency Alert:
1573   The routine `MatSetValuesBlocked()` may offer much better efficiency
1574   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1575 
1576   This is currently not optimized for any particular `ISType`
1577 
1578   Developer Note:
1579   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1580   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1581 
1582 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1583           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1584 @*/
1585 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1586 {
1587   PetscInt        m, n;
1588   const PetscInt *rows, *cols;
1589 
1590   PetscFunctionBeginHot;
1591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1592   PetscCall(ISGetIndices(ism, &rows));
1593   PetscCall(ISGetIndices(isn, &cols));
1594   PetscCall(ISGetLocalSize(ism, &m));
1595   PetscCall(ISGetLocalSize(isn, &n));
1596   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1597   PetscCall(ISRestoreIndices(ism, &rows));
1598   PetscCall(ISRestoreIndices(isn, &cols));
1599   PetscFunctionReturn(PETSC_SUCCESS);
1600 }
1601 
1602 /*@
1603   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1604   values into a matrix
1605 
1606   Not Collective
1607 
1608   Input Parameters:
1609 + mat - the matrix
1610 . row - the (block) row to set
1611 - v   - a logically two-dimensional array of values
1612 
1613   Level: intermediate
1614 
1615   Notes:
1616   The values, `v`, are column-oriented (for the block version) and sorted
1617 
1618   All the nonzero values in `row` must be provided
1619 
1620   The matrix must have previously had its column indices set, likely by having been assembled.
1621 
1622   `row` must belong to this MPI process
1623 
1624 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1625           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1626 @*/
1627 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1628 {
1629   PetscInt globalrow;
1630 
1631   PetscFunctionBegin;
1632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1633   PetscValidType(mat, 1);
1634   PetscAssertPointer(v, 3);
1635   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1636   PetscCall(MatSetValuesRow(mat, globalrow, v));
1637   PetscFunctionReturn(PETSC_SUCCESS);
1638 }
1639 
1640 /*@
1641   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1642   values into a matrix
1643 
1644   Not Collective
1645 
1646   Input Parameters:
1647 + mat - the matrix
1648 . row - the (block) row to set
1649 - 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
1650 
1651   Level: advanced
1652 
1653   Notes:
1654   The values, `v`, are column-oriented for the block version.
1655 
1656   All the nonzeros in `row` must be provided
1657 
1658   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1659 
1660   `row` must belong to this process
1661 
1662 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1663           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1664 @*/
1665 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1666 {
1667   PetscFunctionBeginHot;
1668   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1669   PetscValidType(mat, 1);
1670   MatCheckPreallocated(mat, 1);
1671   PetscAssertPointer(v, 3);
1672   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1673   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1674   mat->insertmode = INSERT_VALUES;
1675 
1676   if (mat->assembled) {
1677     mat->was_assembled = PETSC_TRUE;
1678     mat->assembled     = PETSC_FALSE;
1679   }
1680   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1681   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1682   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1683   PetscFunctionReturn(PETSC_SUCCESS);
1684 }
1685 
1686 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1687 /*@
1688   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1689   Using structured grid indexing
1690 
1691   Not Collective
1692 
1693   Input Parameters:
1694 + mat  - the matrix
1695 . m    - number of rows being entered
1696 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1697 . n    - number of columns being entered
1698 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1699 . v    - a logically two-dimensional array of values
1700 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1701 
1702   Level: beginner
1703 
1704   Notes:
1705   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1706 
1707   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1708   options cannot be mixed without intervening calls to the assembly
1709   routines.
1710 
1711   The grid coordinates are across the entire grid, not just the local portion
1712 
1713   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1714   as well as in C.
1715 
1716   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1717 
1718   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1719   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1720 
1721   The columns and rows in the stencil passed in MUST be contained within the
1722   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1723   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1724   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1725   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1726 
1727   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1728   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1729   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1730   `DM_BOUNDARY_PERIODIC` boundary type.
1731 
1732   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
1733   a single value per point) you can skip filling those indices.
1734 
1735   Inspired by the structured grid interface to the HYPRE package
1736   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1737 
1738   Efficiency Alert:
1739   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1740   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1741 
1742   Fortran Note:
1743   `idxm` and `idxn` should be declared as
1744 $     MatStencil idxm(4,m),idxn(4,n)
1745   and the values inserted using
1746 .vb
1747     idxm(MatStencil_i,1) = i
1748     idxm(MatStencil_j,1) = j
1749     idxm(MatStencil_k,1) = k
1750     idxm(MatStencil_c,1) = c
1751     etc
1752 .ve
1753 
1754 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1755           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1756 @*/
1757 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1758 {
1759   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1760   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1761   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1762 
1763   PetscFunctionBegin;
1764   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1766   PetscValidType(mat, 1);
1767   PetscAssertPointer(idxm, 3);
1768   PetscAssertPointer(idxn, 5);
1769 
1770   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1771     jdxm = buf;
1772     jdxn = buf + m;
1773   } else {
1774     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1775     jdxm = bufm;
1776     jdxn = bufn;
1777   }
1778   for (i = 0; i < m; i++) {
1779     for (j = 0; j < 3 - sdim; j++) dxm++;
1780     tmp = *dxm++ - starts[0];
1781     for (j = 0; j < dim - 1; j++) {
1782       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1783       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1784     }
1785     if (mat->stencil.noc) dxm++;
1786     jdxm[i] = tmp;
1787   }
1788   for (i = 0; i < n; i++) {
1789     for (j = 0; j < 3 - sdim; j++) dxn++;
1790     tmp = *dxn++ - starts[0];
1791     for (j = 0; j < dim - 1; j++) {
1792       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1793       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1794     }
1795     if (mat->stencil.noc) dxn++;
1796     jdxn[i] = tmp;
1797   }
1798   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1799   PetscCall(PetscFree2(bufm, bufn));
1800   PetscFunctionReturn(PETSC_SUCCESS);
1801 }
1802 
1803 /*@
1804   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1805   Using structured grid indexing
1806 
1807   Not Collective
1808 
1809   Input Parameters:
1810 + mat  - the matrix
1811 . m    - number of rows being entered
1812 . idxm - grid coordinates for matrix rows being entered
1813 . n    - number of columns being entered
1814 . idxn - grid coordinates for matrix columns being entered
1815 . v    - a logically two-dimensional array of values
1816 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1817 
1818   Level: beginner
1819 
1820   Notes:
1821   By default the values, `v`, are row-oriented and unsorted.
1822   See `MatSetOption()` for other options.
1823 
1824   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1825   options cannot be mixed without intervening calls to the assembly
1826   routines.
1827 
1828   The grid coordinates are across the entire grid, not just the local portion
1829 
1830   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1831   as well as in C.
1832 
1833   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1834 
1835   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1836   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1837 
1838   The columns and rows in the stencil passed in MUST be contained within the
1839   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1840   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1841   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1842   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1843 
1844   Negative indices may be passed in idxm and idxn, these rows and columns are
1845   simply ignored. This allows easily inserting element stiffness matrices
1846   with homogeneous Dirichlet boundary conditions that you don't want represented
1847   in the matrix.
1848 
1849   Inspired by the structured grid interface to the HYPRE package
1850   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1851 
1852   Fortran Note:
1853   `idxm` and `idxn` should be declared as
1854 $     MatStencil idxm(4,m),idxn(4,n)
1855   and the values inserted using
1856 .vb
1857     idxm(MatStencil_i,1) = i
1858     idxm(MatStencil_j,1) = j
1859     idxm(MatStencil_k,1) = k
1860    etc
1861 .ve
1862 
1863 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1864           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1865           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1866 @*/
1867 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1868 {
1869   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1870   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1871   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1872 
1873   PetscFunctionBegin;
1874   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1876   PetscValidType(mat, 1);
1877   PetscAssertPointer(idxm, 3);
1878   PetscAssertPointer(idxn, 5);
1879   PetscAssertPointer(v, 6);
1880 
1881   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1882     jdxm = buf;
1883     jdxn = buf + m;
1884   } else {
1885     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1886     jdxm = bufm;
1887     jdxn = bufn;
1888   }
1889   for (i = 0; i < m; i++) {
1890     for (j = 0; j < 3 - sdim; j++) dxm++;
1891     tmp = *dxm++ - starts[0];
1892     for (j = 0; j < sdim - 1; j++) {
1893       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1894       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1895     }
1896     dxm++;
1897     jdxm[i] = tmp;
1898   }
1899   for (i = 0; i < n; i++) {
1900     for (j = 0; j < 3 - sdim; j++) dxn++;
1901     tmp = *dxn++ - starts[0];
1902     for (j = 0; j < sdim - 1; j++) {
1903       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1904       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1905     }
1906     dxn++;
1907     jdxn[i] = tmp;
1908   }
1909   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1910   PetscCall(PetscFree2(bufm, bufn));
1911   PetscFunctionReturn(PETSC_SUCCESS);
1912 }
1913 
1914 /*@
1915   MatSetStencil - Sets the grid information for setting values into a matrix via
1916   `MatSetValuesStencil()`
1917 
1918   Not Collective
1919 
1920   Input Parameters:
1921 + mat    - the matrix
1922 . dim    - dimension of the grid 1, 2, or 3
1923 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1924 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1925 - dof    - number of degrees of freedom per node
1926 
1927   Level: beginner
1928 
1929   Notes:
1930   Inspired by the structured grid interface to the HYPRE package
1931   (www.llnl.gov/CASC/hyper)
1932 
1933   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1934   user.
1935 
1936 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1937           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1938 @*/
1939 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1940 {
1941   PetscFunctionBegin;
1942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1943   PetscAssertPointer(dims, 3);
1944   PetscAssertPointer(starts, 4);
1945 
1946   mat->stencil.dim = dim + (dof > 1);
1947   for (PetscInt i = 0; i < dim; i++) {
1948     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1949     mat->stencil.starts[i] = starts[dim - i - 1];
1950   }
1951   mat->stencil.dims[dim]   = dof;
1952   mat->stencil.starts[dim] = 0;
1953   mat->stencil.noc         = (PetscBool)(dof == 1);
1954   PetscFunctionReturn(PETSC_SUCCESS);
1955 }
1956 
1957 /*@
1958   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1959 
1960   Not Collective
1961 
1962   Input Parameters:
1963 + mat  - the matrix
1964 . v    - a logically two-dimensional array of values
1965 . m    - the number of block rows
1966 . idxm - the global block indices
1967 . n    - the number of block columns
1968 . idxn - the global block indices
1969 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1970 
1971   Level: intermediate
1972 
1973   Notes:
1974   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1975   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1976 
1977   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1978   NOT the total number of rows/columns; for example, if the block size is 2 and
1979   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
1980   The values in `idxm` would be 1 2; that is the first index for each block divided by
1981   the block size.
1982 
1983   You must call `MatSetBlockSize()` when constructing this matrix (before
1984   preallocating it).
1985 
1986   By default the values, `v`, are row-oriented, so the layout of
1987   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1988 
1989   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1990   options cannot be mixed without intervening calls to the assembly
1991   routines.
1992 
1993   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1994   as well as in C.
1995 
1996   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1997   simply ignored. This allows easily inserting element stiffness matrices
1998   with homogeneous Dirichlet boundary conditions that you don't want represented
1999   in the matrix.
2000 
2001   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2002   internal searching must be done to determine where to place the
2003   data in the matrix storage space.  By instead inserting blocks of
2004   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2005   reduced.
2006 
2007   Example:
2008 .vb
2009    Suppose m=n=2 and block size(bs) = 2 The array is
2010 
2011    1  2  | 3  4
2012    5  6  | 7  8
2013    - - - | - - -
2014    9  10 | 11 12
2015    13 14 | 15 16
2016 
2017    v[] should be passed in like
2018    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2019 
2020   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2021    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2022 .ve
2023 
2024   Fortran Notes:
2025   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2026 .vb
2027   MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
2028 .ve
2029 
2030   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
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 /*@
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 /*@
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 /*@
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   Fortran Notes:
2411   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2412 .vb
2413   MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2414 .ve
2415 
2416   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2417 
2418   Developer Note:
2419   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2420   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2421 
2422 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2423           `MatGetValuesLocal()`
2424 @*/
2425 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2426 {
2427   PetscFunctionBeginHot;
2428   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2429   PetscValidType(mat, 1);
2430   MatCheckPreallocated(mat, 1);
2431   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2432   PetscAssertPointer(irow, 3);
2433   PetscAssertPointer(icol, 5);
2434   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2435   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2436   if (PetscDefined(USE_DEBUG)) {
2437     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2438     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2439   }
2440 
2441   if (mat->assembled) {
2442     mat->was_assembled = PETSC_TRUE;
2443     mat->assembled     = PETSC_FALSE;
2444   }
2445   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2446   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2447   else {
2448     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2449     const PetscInt *irowm, *icolm;
2450 
2451     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2452       bufr  = buf;
2453       bufc  = buf + nrow;
2454       irowm = bufr;
2455       icolm = bufc;
2456     } else {
2457       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2458       irowm = bufr;
2459       icolm = bufc;
2460     }
2461     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2462     else irowm = irow;
2463     if (mat->cmap->mapping) {
2464       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2465         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2466       } else icolm = irowm;
2467     } else icolm = icol;
2468     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2469     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2470   }
2471   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2472   PetscFunctionReturn(PETSC_SUCCESS);
2473 }
2474 
2475 /*@
2476   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2477   using a local ordering of the nodes a block at a time.
2478 
2479   Not Collective
2480 
2481   Input Parameters:
2482 + mat  - the matrix
2483 . nrow - number of rows
2484 . irow - the row local indices
2485 . ncol - number of columns
2486 . icol - the column local indices
2487 . y    - a logically two-dimensional array of values
2488 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2489 
2490   Level: intermediate
2491 
2492   Notes:
2493   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2494   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2495 
2496   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2497   options cannot be mixed without intervening calls to the assembly
2498   routines.
2499 
2500   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2501   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2502 
2503   Fortran Notes:
2504   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2505 .vb
2506   MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2507 .ve
2508 
2509   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2510 
2511   Developer Note:
2512   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2513   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2514 
2515 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2516           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2517 @*/
2518 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2519 {
2520   PetscFunctionBeginHot;
2521   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2522   PetscValidType(mat, 1);
2523   MatCheckPreallocated(mat, 1);
2524   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2525   PetscAssertPointer(irow, 3);
2526   PetscAssertPointer(icol, 5);
2527   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2528   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2529   if (PetscDefined(USE_DEBUG)) {
2530     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2531     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);
2532   }
2533 
2534   if (mat->assembled) {
2535     mat->was_assembled = PETSC_TRUE;
2536     mat->assembled     = PETSC_FALSE;
2537   }
2538   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2539     PetscInt irbs, rbs;
2540     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2541     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2542     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2543   }
2544   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2545     PetscInt icbs, cbs;
2546     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2547     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2548     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2549   }
2550   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2551   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2552   else {
2553     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2554     const PetscInt *irowm, *icolm;
2555 
2556     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2557       bufr  = buf;
2558       bufc  = buf + nrow;
2559       irowm = bufr;
2560       icolm = bufc;
2561     } else {
2562       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2563       irowm = bufr;
2564       icolm = bufc;
2565     }
2566     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2567     else irowm = irow;
2568     if (mat->cmap->mapping) {
2569       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2570         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2571       } else icolm = irowm;
2572     } else icolm = icol;
2573     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2574     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2575   }
2576   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2577   PetscFunctionReturn(PETSC_SUCCESS);
2578 }
2579 
2580 /*@
2581   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2582 
2583   Collective
2584 
2585   Input Parameters:
2586 + mat - the matrix
2587 - x   - the vector to be multiplied
2588 
2589   Output Parameter:
2590 . y - the result
2591 
2592   Level: developer
2593 
2594   Note:
2595   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2596   call `MatMultDiagonalBlock`(A,y,y).
2597 
2598 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2599 @*/
2600 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2601 {
2602   PetscFunctionBegin;
2603   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2604   PetscValidType(mat, 1);
2605   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2606   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2607 
2608   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2609   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2610   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2611   MatCheckPreallocated(mat, 1);
2612 
2613   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2614   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2615   PetscFunctionReturn(PETSC_SUCCESS);
2616 }
2617 
2618 /*@
2619   MatMult - Computes the matrix-vector product, $y = Ax$.
2620 
2621   Neighbor-wise Collective
2622 
2623   Input Parameters:
2624 + mat - the matrix
2625 - x   - the vector to be multiplied
2626 
2627   Output Parameter:
2628 . y - the result
2629 
2630   Level: beginner
2631 
2632   Note:
2633   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2634   call `MatMult`(A,y,y).
2635 
2636 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2637 @*/
2638 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2639 {
2640   PetscFunctionBegin;
2641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2642   PetscValidType(mat, 1);
2643   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2644   VecCheckAssembled(x);
2645   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2646   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2647   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2648   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2649   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);
2650   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);
2651   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);
2652   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);
2653   PetscCall(VecSetErrorIfLocked(y, 3));
2654   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2655   MatCheckPreallocated(mat, 1);
2656 
2657   PetscCall(VecLockReadPush(x));
2658   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2659   PetscUseTypeMethod(mat, mult, x, y);
2660   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2661   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2662   PetscCall(VecLockReadPop(x));
2663   PetscFunctionReturn(PETSC_SUCCESS);
2664 }
2665 
2666 /*@
2667   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2668 
2669   Neighbor-wise Collective
2670 
2671   Input Parameters:
2672 + mat - the matrix
2673 - x   - the vector to be multiplied
2674 
2675   Output Parameter:
2676 . y - the result
2677 
2678   Level: beginner
2679 
2680   Notes:
2681   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2682   call `MatMultTranspose`(A,y,y).
2683 
2684   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2685   use `MatMultHermitianTranspose()`
2686 
2687 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2688 @*/
2689 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2690 {
2691   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2692 
2693   PetscFunctionBegin;
2694   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2695   PetscValidType(mat, 1);
2696   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2697   VecCheckAssembled(x);
2698   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2699 
2700   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2701   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2702   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2703   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);
2704   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);
2705   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);
2706   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);
2707   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2708   MatCheckPreallocated(mat, 1);
2709 
2710   if (!mat->ops->multtranspose) {
2711     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2712     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);
2713   } else op = mat->ops->multtranspose;
2714   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2715   PetscCall(VecLockReadPush(x));
2716   PetscCall((*op)(mat, x, y));
2717   PetscCall(VecLockReadPop(x));
2718   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2719   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2720   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2721   PetscFunctionReturn(PETSC_SUCCESS);
2722 }
2723 
2724 /*@
2725   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2726 
2727   Neighbor-wise Collective
2728 
2729   Input Parameters:
2730 + mat - the matrix
2731 - x   - the vector to be multiplied
2732 
2733   Output Parameter:
2734 . y - the result
2735 
2736   Level: beginner
2737 
2738   Notes:
2739   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2740   call `MatMultHermitianTranspose`(A,y,y).
2741 
2742   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2743 
2744   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2745 
2746 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2747 @*/
2748 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2749 {
2750   PetscFunctionBegin;
2751   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2752   PetscValidType(mat, 1);
2753   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2754   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2755 
2756   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2757   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2758   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2759   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);
2760   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);
2761   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);
2762   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);
2763   MatCheckPreallocated(mat, 1);
2764 
2765   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2766 #if defined(PETSC_USE_COMPLEX)
2767   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2768     PetscCall(VecLockReadPush(x));
2769     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2770     else PetscUseTypeMethod(mat, mult, x, y);
2771     PetscCall(VecLockReadPop(x));
2772   } else {
2773     Vec w;
2774     PetscCall(VecDuplicate(x, &w));
2775     PetscCall(VecCopy(x, w));
2776     PetscCall(VecConjugate(w));
2777     PetscCall(MatMultTranspose(mat, w, y));
2778     PetscCall(VecDestroy(&w));
2779     PetscCall(VecConjugate(y));
2780   }
2781   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2782 #else
2783   PetscCall(MatMultTranspose(mat, x, y));
2784 #endif
2785   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2786   PetscFunctionReturn(PETSC_SUCCESS);
2787 }
2788 
2789 /*@
2790   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2791 
2792   Neighbor-wise Collective
2793 
2794   Input Parameters:
2795 + mat - the matrix
2796 . v1  - the vector to be multiplied by `mat`
2797 - v2  - the vector to be added to the result
2798 
2799   Output Parameter:
2800 . v3 - the result
2801 
2802   Level: beginner
2803 
2804   Note:
2805   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2806   call `MatMultAdd`(A,v1,v2,v1).
2807 
2808 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2809 @*/
2810 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2811 {
2812   PetscFunctionBegin;
2813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2814   PetscValidType(mat, 1);
2815   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2816   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2817   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2818 
2819   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2820   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2821   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);
2822   /* 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);
2823      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); */
2824   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);
2825   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);
2826   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2827   MatCheckPreallocated(mat, 1);
2828 
2829   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2830   PetscCall(VecLockReadPush(v1));
2831   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2832   PetscCall(VecLockReadPop(v1));
2833   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2834   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2835   PetscFunctionReturn(PETSC_SUCCESS);
2836 }
2837 
2838 /*@
2839   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2840 
2841   Neighbor-wise Collective
2842 
2843   Input Parameters:
2844 + mat - the matrix
2845 . v1  - the vector to be multiplied by the transpose of the matrix
2846 - v2  - the vector to be added to the result
2847 
2848   Output Parameter:
2849 . v3 - the result
2850 
2851   Level: beginner
2852 
2853   Note:
2854   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2855   call `MatMultTransposeAdd`(A,v1,v2,v1).
2856 
2857 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2858 @*/
2859 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2860 {
2861   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2862 
2863   PetscFunctionBegin;
2864   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2865   PetscValidType(mat, 1);
2866   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2867   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2868   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2869 
2870   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2871   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2872   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);
2873   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);
2874   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);
2875   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2876   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2877   MatCheckPreallocated(mat, 1);
2878 
2879   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2880   PetscCall(VecLockReadPush(v1));
2881   PetscCall((*op)(mat, v1, v2, v3));
2882   PetscCall(VecLockReadPop(v1));
2883   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2884   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2885   PetscFunctionReturn(PETSC_SUCCESS);
2886 }
2887 
2888 /*@
2889   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2890 
2891   Neighbor-wise Collective
2892 
2893   Input Parameters:
2894 + mat - the matrix
2895 . v1  - the vector to be multiplied by the Hermitian transpose
2896 - v2  - the vector to be added to the result
2897 
2898   Output Parameter:
2899 . v3 - the result
2900 
2901   Level: beginner
2902 
2903   Note:
2904   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2905   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2906 
2907 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2908 @*/
2909 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2910 {
2911   PetscFunctionBegin;
2912   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2913   PetscValidType(mat, 1);
2914   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2915   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2916   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2917 
2918   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2919   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2920   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2921   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);
2922   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);
2923   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);
2924   MatCheckPreallocated(mat, 1);
2925 
2926   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2927   PetscCall(VecLockReadPush(v1));
2928   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2929   else {
2930     Vec w, z;
2931     PetscCall(VecDuplicate(v1, &w));
2932     PetscCall(VecCopy(v1, w));
2933     PetscCall(VecConjugate(w));
2934     PetscCall(VecDuplicate(v3, &z));
2935     PetscCall(MatMultTranspose(mat, w, z));
2936     PetscCall(VecDestroy(&w));
2937     PetscCall(VecConjugate(z));
2938     if (v2 != v3) {
2939       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2940     } else {
2941       PetscCall(VecAXPY(v3, 1.0, z));
2942     }
2943     PetscCall(VecDestroy(&z));
2944   }
2945   PetscCall(VecLockReadPop(v1));
2946   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2947   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2948   PetscFunctionReturn(PETSC_SUCCESS);
2949 }
2950 
2951 /*@
2952   MatGetFactorType - gets the type of factorization a matrix is
2953 
2954   Not Collective
2955 
2956   Input Parameter:
2957 . mat - the matrix
2958 
2959   Output Parameter:
2960 . 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`
2961 
2962   Level: intermediate
2963 
2964 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2965           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2966 @*/
2967 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2968 {
2969   PetscFunctionBegin;
2970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2971   PetscValidType(mat, 1);
2972   PetscAssertPointer(t, 2);
2973   *t = mat->factortype;
2974   PetscFunctionReturn(PETSC_SUCCESS);
2975 }
2976 
2977 /*@
2978   MatSetFactorType - sets the type of factorization a matrix is
2979 
2980   Logically Collective
2981 
2982   Input Parameters:
2983 + mat - the matrix
2984 - 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`
2985 
2986   Level: intermediate
2987 
2988 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2989           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2990 @*/
2991 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2992 {
2993   PetscFunctionBegin;
2994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2995   PetscValidType(mat, 1);
2996   mat->factortype = t;
2997   PetscFunctionReturn(PETSC_SUCCESS);
2998 }
2999 
3000 /*@
3001   MatGetInfo - Returns information about matrix storage (number of
3002   nonzeros, memory, etc.).
3003 
3004   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3005 
3006   Input Parameters:
3007 + mat  - the matrix
3008 - 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)
3009 
3010   Output Parameter:
3011 . info - matrix information context
3012 
3013   Options Database Key:
3014 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3015 
3016   Level: intermediate
3017 
3018   Notes:
3019   The `MatInfo` context contains a variety of matrix data, including
3020   number of nonzeros allocated and used, number of mallocs during
3021   matrix assembly, etc.  Additional information for factored matrices
3022   is provided (such as the fill ratio, number of mallocs during
3023   factorization, etc.).
3024 
3025   Example:
3026   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3027   data within the `MatInfo` context.  For example,
3028 .vb
3029       MatInfo info;
3030       Mat     A;
3031       double  mal, nz_a, nz_u;
3032 
3033       MatGetInfo(A, MAT_LOCAL, &info);
3034       mal  = info.mallocs;
3035       nz_a = info.nz_allocated;
3036 .ve
3037 
3038   Fortran Note:
3039   Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3040   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3041   a complete list of parameter names.
3042 .vb
3043       MatInfo info(MAT_INFO_SIZE)
3044       double  precision mal, nz_a
3045       Mat     A
3046       integer ierr
3047 
3048       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3049       mal = info(MAT_INFO_MALLOCS)
3050       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3051 .ve
3052 
3053 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3054 @*/
3055 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3056 {
3057   PetscFunctionBegin;
3058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3059   PetscValidType(mat, 1);
3060   PetscAssertPointer(info, 3);
3061   MatCheckPreallocated(mat, 1);
3062   PetscUseTypeMethod(mat, getinfo, flag, info);
3063   PetscFunctionReturn(PETSC_SUCCESS);
3064 }
3065 
3066 /*
3067    This is used by external packages where it is not easy to get the info from the actual
3068    matrix factorization.
3069 */
3070 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3071 {
3072   PetscFunctionBegin;
3073   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3074   PetscFunctionReturn(PETSC_SUCCESS);
3075 }
3076 
3077 /*@
3078   MatLUFactor - Performs in-place LU factorization of matrix.
3079 
3080   Collective
3081 
3082   Input Parameters:
3083 + mat  - the matrix
3084 . row  - row permutation
3085 . col  - column permutation
3086 - info - options for factorization, includes
3087 .vb
3088           fill - expected fill as ratio of original fill.
3089           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3090                    Run with the option -info to determine an optimal value to use
3091 .ve
3092 
3093   Level: developer
3094 
3095   Notes:
3096   Most users should employ the `KSP` interface for linear solvers
3097   instead of working directly with matrix algebra routines such as this.
3098   See, e.g., `KSPCreate()`.
3099 
3100   This changes the state of the matrix to a factored matrix; it cannot be used
3101   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3102 
3103   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3104   when not using `KSP`.
3105 
3106   Developer Note:
3107   The Fortran interface is not autogenerated as the
3108   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3109 
3110 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3111           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3112 @*/
3113 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3114 {
3115   MatFactorInfo tinfo;
3116 
3117   PetscFunctionBegin;
3118   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3119   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3120   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3121   if (info) PetscAssertPointer(info, 4);
3122   PetscValidType(mat, 1);
3123   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3124   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3125   MatCheckPreallocated(mat, 1);
3126   if (!info) {
3127     PetscCall(MatFactorInfoInitialize(&tinfo));
3128     info = &tinfo;
3129   }
3130 
3131   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3132   PetscUseTypeMethod(mat, lufactor, row, col, info);
3133   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3134   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3135   PetscFunctionReturn(PETSC_SUCCESS);
3136 }
3137 
3138 /*@
3139   MatILUFactor - Performs in-place ILU factorization of matrix.
3140 
3141   Collective
3142 
3143   Input Parameters:
3144 + mat  - the matrix
3145 . row  - row permutation
3146 . col  - column permutation
3147 - info - structure containing
3148 .vb
3149       levels - number of levels of fill.
3150       expected fill - as ratio of original fill.
3151       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3152                 missing diagonal entries)
3153 .ve
3154 
3155   Level: developer
3156 
3157   Notes:
3158   Most users should employ the `KSP` interface for linear solvers
3159   instead of working directly with matrix algebra routines such as this.
3160   See, e.g., `KSPCreate()`.
3161 
3162   Probably really in-place only when level of fill is zero, otherwise allocates
3163   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3164   when not using `KSP`.
3165 
3166   Developer Note:
3167   The Fortran interface is not autogenerated as the
3168   interface definition cannot be generated correctly [due to MatFactorInfo]
3169 
3170 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3171 @*/
3172 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3173 {
3174   PetscFunctionBegin;
3175   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3176   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3177   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3178   PetscAssertPointer(info, 4);
3179   PetscValidType(mat, 1);
3180   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3181   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3182   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3183   MatCheckPreallocated(mat, 1);
3184 
3185   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3186   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3187   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3188   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3189   PetscFunctionReturn(PETSC_SUCCESS);
3190 }
3191 
3192 /*@
3193   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3194   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3195 
3196   Collective
3197 
3198   Input Parameters:
3199 + fact - the factor matrix obtained with `MatGetFactor()`
3200 . mat  - the matrix
3201 . row  - the row permutation
3202 . col  - the column permutation
3203 - info - options for factorization, includes
3204 .vb
3205           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3206           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3207 .ve
3208 
3209   Level: developer
3210 
3211   Notes:
3212   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3213 
3214   Most users should employ the simplified `KSP` interface for linear solvers
3215   instead of working directly with matrix algebra routines such as this.
3216   See, e.g., `KSPCreate()`.
3217 
3218   Developer Note:
3219   The Fortran interface is not autogenerated as the
3220   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3221 
3222 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3223 @*/
3224 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3225 {
3226   MatFactorInfo tinfo;
3227 
3228   PetscFunctionBegin;
3229   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3230   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3231   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3232   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3233   if (info) PetscAssertPointer(info, 5);
3234   PetscValidType(fact, 1);
3235   PetscValidType(mat, 2);
3236   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3237   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3238   MatCheckPreallocated(mat, 2);
3239   if (!info) {
3240     PetscCall(MatFactorInfoInitialize(&tinfo));
3241     info = &tinfo;
3242   }
3243 
3244   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3245   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3246   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3247   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3248   PetscFunctionReturn(PETSC_SUCCESS);
3249 }
3250 
3251 /*@
3252   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3253   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3254 
3255   Collective
3256 
3257   Input Parameters:
3258 + fact - the factor matrix obtained with `MatGetFactor()`
3259 . mat  - the matrix
3260 - info - options for factorization
3261 
3262   Level: developer
3263 
3264   Notes:
3265   See `MatLUFactor()` for in-place factorization.  See
3266   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3267 
3268   Most users should employ the `KSP` interface for linear solvers
3269   instead of working directly with matrix algebra routines such as this.
3270   See, e.g., `KSPCreate()`.
3271 
3272   Developer Note:
3273   The Fortran interface is not autogenerated as the
3274   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3275 
3276 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3277 @*/
3278 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3279 {
3280   MatFactorInfo tinfo;
3281 
3282   PetscFunctionBegin;
3283   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3285   PetscValidType(fact, 1);
3286   PetscValidType(mat, 2);
3287   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3288   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,
3289              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3290 
3291   MatCheckPreallocated(mat, 2);
3292   if (!info) {
3293     PetscCall(MatFactorInfoInitialize(&tinfo));
3294     info = &tinfo;
3295   }
3296 
3297   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3298   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3299   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3300   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3301   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3302   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3303   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3304   PetscFunctionReturn(PETSC_SUCCESS);
3305 }
3306 
3307 /*@
3308   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3309   symmetric matrix.
3310 
3311   Collective
3312 
3313   Input Parameters:
3314 + mat  - the matrix
3315 . perm - row and column permutations
3316 - info - expected fill as ratio of original fill
3317 
3318   Level: developer
3319 
3320   Notes:
3321   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3322   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3323 
3324   Most users should employ the `KSP` interface for linear solvers
3325   instead of working directly with matrix algebra routines such as this.
3326   See, e.g., `KSPCreate()`.
3327 
3328   Developer Note:
3329   The Fortran interface is not autogenerated as the
3330   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3331 
3332 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3333           `MatGetOrdering()`
3334 @*/
3335 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3336 {
3337   MatFactorInfo tinfo;
3338 
3339   PetscFunctionBegin;
3340   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3341   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3342   if (info) PetscAssertPointer(info, 3);
3343   PetscValidType(mat, 1);
3344   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3345   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3346   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3347   MatCheckPreallocated(mat, 1);
3348   if (!info) {
3349     PetscCall(MatFactorInfoInitialize(&tinfo));
3350     info = &tinfo;
3351   }
3352 
3353   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3354   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3355   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3356   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3357   PetscFunctionReturn(PETSC_SUCCESS);
3358 }
3359 
3360 /*@
3361   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3362   of a symmetric matrix.
3363 
3364   Collective
3365 
3366   Input Parameters:
3367 + fact - the factor matrix obtained with `MatGetFactor()`
3368 . mat  - the matrix
3369 . perm - row and column permutations
3370 - info - options for factorization, includes
3371 .vb
3372           fill - expected fill as ratio of original fill.
3373           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3374                    Run with the option -info to determine an optimal value to use
3375 .ve
3376 
3377   Level: developer
3378 
3379   Notes:
3380   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3381   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3382 
3383   Most users should employ the `KSP` interface for linear solvers
3384   instead of working directly with matrix algebra routines such as this.
3385   See, e.g., `KSPCreate()`.
3386 
3387   Developer Note:
3388   The Fortran interface is not autogenerated as the
3389   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3390 
3391 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3392           `MatGetOrdering()`
3393 @*/
3394 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3395 {
3396   MatFactorInfo tinfo;
3397 
3398   PetscFunctionBegin;
3399   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3401   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3402   if (info) PetscAssertPointer(info, 4);
3403   PetscValidType(fact, 1);
3404   PetscValidType(mat, 2);
3405   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3406   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3407   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3408   MatCheckPreallocated(mat, 2);
3409   if (!info) {
3410     PetscCall(MatFactorInfoInitialize(&tinfo));
3411     info = &tinfo;
3412   }
3413 
3414   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3415   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3416   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3417   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3418   PetscFunctionReturn(PETSC_SUCCESS);
3419 }
3420 
3421 /*@
3422   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3423   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3424   `MatCholeskyFactorSymbolic()`.
3425 
3426   Collective
3427 
3428   Input Parameters:
3429 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3430 . mat  - the initial matrix that is to be factored
3431 - info - options for factorization
3432 
3433   Level: developer
3434 
3435   Note:
3436   Most users should employ the `KSP` interface for linear solvers
3437   instead of working directly with matrix algebra routines such as this.
3438   See, e.g., `KSPCreate()`.
3439 
3440   Developer Note:
3441   The Fortran interface is not autogenerated as the
3442   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3443 
3444 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3445 @*/
3446 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3447 {
3448   MatFactorInfo tinfo;
3449 
3450   PetscFunctionBegin;
3451   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3453   PetscValidType(fact, 1);
3454   PetscValidType(mat, 2);
3455   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3456   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,
3457              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3458   MatCheckPreallocated(mat, 2);
3459   if (!info) {
3460     PetscCall(MatFactorInfoInitialize(&tinfo));
3461     info = &tinfo;
3462   }
3463 
3464   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3465   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3466   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3467   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3468   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3469   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3470   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3471   PetscFunctionReturn(PETSC_SUCCESS);
3472 }
3473 
3474 /*@
3475   MatQRFactor - Performs in-place QR factorization of matrix.
3476 
3477   Collective
3478 
3479   Input Parameters:
3480 + mat  - the matrix
3481 . col  - column permutation
3482 - info - options for factorization, includes
3483 .vb
3484           fill - expected fill as ratio of original fill.
3485           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3486                    Run with the option -info to determine an optimal value to use
3487 .ve
3488 
3489   Level: developer
3490 
3491   Notes:
3492   Most users should employ the `KSP` interface for linear solvers
3493   instead of working directly with matrix algebra routines such as this.
3494   See, e.g., `KSPCreate()`.
3495 
3496   This changes the state of the matrix to a factored matrix; it cannot be used
3497   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3498 
3499   Developer Note:
3500   The Fortran interface is not autogenerated as the
3501   interface definition cannot be generated correctly [due to MatFactorInfo]
3502 
3503 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3504           `MatSetUnfactored()`
3505 @*/
3506 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3507 {
3508   PetscFunctionBegin;
3509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3510   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3511   if (info) PetscAssertPointer(info, 3);
3512   PetscValidType(mat, 1);
3513   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3514   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3515   MatCheckPreallocated(mat, 1);
3516   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3517   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3518   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3519   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3520   PetscFunctionReturn(PETSC_SUCCESS);
3521 }
3522 
3523 /*@
3524   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3525   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3526 
3527   Collective
3528 
3529   Input Parameters:
3530 + fact - the factor matrix obtained with `MatGetFactor()`
3531 . mat  - the matrix
3532 . col  - column permutation
3533 - info - options for factorization, includes
3534 .vb
3535           fill - expected fill as ratio of original fill.
3536           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3537                    Run with the option -info to determine an optimal value to use
3538 .ve
3539 
3540   Level: developer
3541 
3542   Note:
3543   Most users should employ the `KSP` interface for linear solvers
3544   instead of working directly with matrix algebra routines such as this.
3545   See, e.g., `KSPCreate()`.
3546 
3547   Developer Note:
3548   The Fortran interface is not autogenerated as the
3549   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3550 
3551 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3552 @*/
3553 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3554 {
3555   MatFactorInfo tinfo;
3556 
3557   PetscFunctionBegin;
3558   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3560   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3561   if (info) PetscAssertPointer(info, 4);
3562   PetscValidType(fact, 1);
3563   PetscValidType(mat, 2);
3564   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3565   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3566   MatCheckPreallocated(mat, 2);
3567   if (!info) {
3568     PetscCall(MatFactorInfoInitialize(&tinfo));
3569     info = &tinfo;
3570   }
3571 
3572   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3573   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3574   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3575   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3576   PetscFunctionReturn(PETSC_SUCCESS);
3577 }
3578 
3579 /*@
3580   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3581   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3582 
3583   Collective
3584 
3585   Input Parameters:
3586 + fact - the factor matrix obtained with `MatGetFactor()`
3587 . mat  - the matrix
3588 - info - options for factorization
3589 
3590   Level: developer
3591 
3592   Notes:
3593   See `MatQRFactor()` for in-place factorization.
3594 
3595   Most users should employ the `KSP` interface for linear solvers
3596   instead of working directly with matrix algebra routines such as this.
3597   See, e.g., `KSPCreate()`.
3598 
3599   Developer Note:
3600   The Fortran interface is not autogenerated as the
3601   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3602 
3603 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3604 @*/
3605 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3606 {
3607   MatFactorInfo tinfo;
3608 
3609   PetscFunctionBegin;
3610   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3611   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3612   PetscValidType(fact, 1);
3613   PetscValidType(mat, 2);
3614   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3615   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,
3616              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3617 
3618   MatCheckPreallocated(mat, 2);
3619   if (!info) {
3620     PetscCall(MatFactorInfoInitialize(&tinfo));
3621     info = &tinfo;
3622   }
3623 
3624   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3625   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3626   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3627   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3628   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3629   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3630   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3631   PetscFunctionReturn(PETSC_SUCCESS);
3632 }
3633 
3634 /*@
3635   MatSolve - Solves $A x = b$, given a factored matrix.
3636 
3637   Neighbor-wise Collective
3638 
3639   Input Parameters:
3640 + mat - the factored matrix
3641 - b   - the right-hand-side vector
3642 
3643   Output Parameter:
3644 . x - the result vector
3645 
3646   Level: developer
3647 
3648   Notes:
3649   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3650   call `MatSolve`(A,x,x).
3651 
3652   Most users should employ the `KSP` interface for linear solvers
3653   instead of working directly with matrix algebra routines such as this.
3654   See, e.g., `KSPCreate()`.
3655 
3656 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3657 @*/
3658 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3659 {
3660   PetscFunctionBegin;
3661   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3662   PetscValidType(mat, 1);
3663   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3664   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3665   PetscCheckSameComm(mat, 1, b, 2);
3666   PetscCheckSameComm(mat, 1, x, 3);
3667   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3668   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);
3669   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);
3670   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);
3671   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3672   MatCheckPreallocated(mat, 1);
3673 
3674   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3675   PetscCall(VecFlag(x, mat->factorerrortype));
3676   if (mat->factorerrortype) {
3677     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3678   } else PetscUseTypeMethod(mat, solve, b, x);
3679   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3680   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3681   PetscFunctionReturn(PETSC_SUCCESS);
3682 }
3683 
3684 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3685 {
3686   Vec      b, x;
3687   PetscInt N, i;
3688   PetscErrorCode (*f)(Mat, Vec, Vec);
3689   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3690 
3691   PetscFunctionBegin;
3692   if (A->factorerrortype) {
3693     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3694     PetscCall(MatSetInf(X));
3695     PetscFunctionReturn(PETSC_SUCCESS);
3696   }
3697   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3698   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3699   PetscCall(MatBoundToCPU(A, &Abound));
3700   if (!Abound) {
3701     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3702     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3703   }
3704 #if PetscDefined(HAVE_CUDA)
3705   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3706   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3707 #elif PetscDefined(HAVE_HIP)
3708   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3709   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3710 #endif
3711   PetscCall(MatGetSize(B, NULL, &N));
3712   for (i = 0; i < N; i++) {
3713     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3714     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3715     PetscCall((*f)(A, b, x));
3716     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3717     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3718   }
3719   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3720   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3721   PetscFunctionReturn(PETSC_SUCCESS);
3722 }
3723 
3724 /*@
3725   MatMatSolve - Solves $A X = B$, given a factored matrix.
3726 
3727   Neighbor-wise Collective
3728 
3729   Input Parameters:
3730 + A - the factored matrix
3731 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3732 
3733   Output Parameter:
3734 . X - the result matrix (dense matrix)
3735 
3736   Level: developer
3737 
3738   Note:
3739   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3740   otherwise, `B` and `X` cannot be the same.
3741 
3742 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3743 @*/
3744 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3745 {
3746   PetscFunctionBegin;
3747   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3748   PetscValidType(A, 1);
3749   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3750   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3751   PetscCheckSameComm(A, 1, B, 2);
3752   PetscCheckSameComm(A, 1, X, 3);
3753   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);
3754   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);
3755   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");
3756   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3757   MatCheckPreallocated(A, 1);
3758 
3759   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3760   if (!A->ops->matsolve) {
3761     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3762     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3763   } else PetscUseTypeMethod(A, matsolve, B, X);
3764   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(PETSC_SUCCESS);
3767 }
3768 
3769 /*@
3770   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3771 
3772   Neighbor-wise Collective
3773 
3774   Input Parameters:
3775 + A - the factored matrix
3776 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3777 
3778   Output Parameter:
3779 . X - the result matrix (dense matrix)
3780 
3781   Level: developer
3782 
3783   Note:
3784   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3785   call `MatMatSolveTranspose`(A,X,X).
3786 
3787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3788 @*/
3789 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3790 {
3791   PetscFunctionBegin;
3792   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3793   PetscValidType(A, 1);
3794   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3795   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3796   PetscCheckSameComm(A, 1, B, 2);
3797   PetscCheckSameComm(A, 1, X, 3);
3798   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3799   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);
3800   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);
3801   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);
3802   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");
3803   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3804   MatCheckPreallocated(A, 1);
3805 
3806   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3807   if (!A->ops->matsolvetranspose) {
3808     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3809     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3810   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3811   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3812   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3813   PetscFunctionReturn(PETSC_SUCCESS);
3814 }
3815 
3816 /*@
3817   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3818 
3819   Neighbor-wise Collective
3820 
3821   Input Parameters:
3822 + A  - the factored matrix
3823 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3824 
3825   Output Parameter:
3826 . X - the result matrix (dense matrix)
3827 
3828   Level: developer
3829 
3830   Note:
3831   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
3832   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3833 
3834 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3835 @*/
3836 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3837 {
3838   PetscFunctionBegin;
3839   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3840   PetscValidType(A, 1);
3841   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3842   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3843   PetscCheckSameComm(A, 1, Bt, 2);
3844   PetscCheckSameComm(A, 1, X, 3);
3845 
3846   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3847   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);
3848   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);
3849   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");
3850   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3851   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3852   MatCheckPreallocated(A, 1);
3853 
3854   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3855   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3856   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3857   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3858   PetscFunctionReturn(PETSC_SUCCESS);
3859 }
3860 
3861 /*@
3862   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3863   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3864 
3865   Neighbor-wise Collective
3866 
3867   Input Parameters:
3868 + mat - the factored matrix
3869 - b   - the right-hand-side vector
3870 
3871   Output Parameter:
3872 . x - the result vector
3873 
3874   Level: developer
3875 
3876   Notes:
3877   `MatSolve()` should be used for most applications, as it performs
3878   a forward solve followed by a backward solve.
3879 
3880   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3881   call `MatForwardSolve`(A,x,x).
3882 
3883   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3884   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3885   `MatForwardSolve()` solves $U^T*D y = b$, and
3886   `MatBackwardSolve()` solves $U x = y$.
3887   Thus they do not provide a symmetric preconditioner.
3888 
3889 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3890 @*/
3891 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3892 {
3893   PetscFunctionBegin;
3894   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3895   PetscValidType(mat, 1);
3896   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3897   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3898   PetscCheckSameComm(mat, 1, b, 2);
3899   PetscCheckSameComm(mat, 1, x, 3);
3900   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3901   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);
3902   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);
3903   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);
3904   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3905   MatCheckPreallocated(mat, 1);
3906 
3907   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3908   PetscUseTypeMethod(mat, forwardsolve, b, x);
3909   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3910   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3911   PetscFunctionReturn(PETSC_SUCCESS);
3912 }
3913 
3914 /*@
3915   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3916   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3917 
3918   Neighbor-wise Collective
3919 
3920   Input Parameters:
3921 + mat - the factored matrix
3922 - b   - the right-hand-side vector
3923 
3924   Output Parameter:
3925 . x - the result vector
3926 
3927   Level: developer
3928 
3929   Notes:
3930   `MatSolve()` should be used for most applications, as it performs
3931   a forward solve followed by a backward solve.
3932 
3933   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3934   call `MatBackwardSolve`(A,x,x).
3935 
3936   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3937   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3938   `MatForwardSolve()` solves $U^T*D y = b$, and
3939   `MatBackwardSolve()` solves $U x = y$.
3940   Thus they do not provide a symmetric preconditioner.
3941 
3942 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3943 @*/
3944 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3945 {
3946   PetscFunctionBegin;
3947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3948   PetscValidType(mat, 1);
3949   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3950   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3951   PetscCheckSameComm(mat, 1, b, 2);
3952   PetscCheckSameComm(mat, 1, x, 3);
3953   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3954   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);
3955   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);
3956   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);
3957   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3958   MatCheckPreallocated(mat, 1);
3959 
3960   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3961   PetscUseTypeMethod(mat, backwardsolve, b, x);
3962   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3963   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3964   PetscFunctionReturn(PETSC_SUCCESS);
3965 }
3966 
3967 /*@
3968   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3969 
3970   Neighbor-wise Collective
3971 
3972   Input Parameters:
3973 + mat - the factored matrix
3974 . b   - the right-hand-side vector
3975 - y   - the vector to be added to
3976 
3977   Output Parameter:
3978 . x - the result vector
3979 
3980   Level: developer
3981 
3982   Note:
3983   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3984   call `MatSolveAdd`(A,x,y,x).
3985 
3986 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3987 @*/
3988 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3989 {
3990   PetscScalar one = 1.0;
3991   Vec         tmp;
3992 
3993   PetscFunctionBegin;
3994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3995   PetscValidType(mat, 1);
3996   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3997   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3998   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3999   PetscCheckSameComm(mat, 1, b, 2);
4000   PetscCheckSameComm(mat, 1, y, 3);
4001   PetscCheckSameComm(mat, 1, x, 4);
4002   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4003   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);
4004   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);
4005   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);
4006   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);
4007   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);
4008   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4009   MatCheckPreallocated(mat, 1);
4010 
4011   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4012   PetscCall(VecFlag(x, mat->factorerrortype));
4013   if (mat->factorerrortype) {
4014     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4015   } else if (mat->ops->solveadd) {
4016     PetscUseTypeMethod(mat, solveadd, b, y, x);
4017   } else {
4018     /* do the solve then the add manually */
4019     if (x != y) {
4020       PetscCall(MatSolve(mat, b, x));
4021       PetscCall(VecAXPY(x, one, y));
4022     } else {
4023       PetscCall(VecDuplicate(x, &tmp));
4024       PetscCall(VecCopy(x, tmp));
4025       PetscCall(MatSolve(mat, b, x));
4026       PetscCall(VecAXPY(x, one, tmp));
4027       PetscCall(VecDestroy(&tmp));
4028     }
4029   }
4030   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4031   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4032   PetscFunctionReturn(PETSC_SUCCESS);
4033 }
4034 
4035 /*@
4036   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4037 
4038   Neighbor-wise Collective
4039 
4040   Input Parameters:
4041 + mat - the factored matrix
4042 - b   - the right-hand-side vector
4043 
4044   Output Parameter:
4045 . x - the result vector
4046 
4047   Level: developer
4048 
4049   Notes:
4050   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4051   call `MatSolveTranspose`(A,x,x).
4052 
4053   Most users should employ the `KSP` interface for linear solvers
4054   instead of working directly with matrix algebra routines such as this.
4055   See, e.g., `KSPCreate()`.
4056 
4057 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4058 @*/
4059 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4060 {
4061   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4062 
4063   PetscFunctionBegin;
4064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4065   PetscValidType(mat, 1);
4066   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4067   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4068   PetscCheckSameComm(mat, 1, b, 2);
4069   PetscCheckSameComm(mat, 1, x, 3);
4070   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4071   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);
4072   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);
4073   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4074   MatCheckPreallocated(mat, 1);
4075   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4076   PetscCall(VecFlag(x, mat->factorerrortype));
4077   if (mat->factorerrortype) {
4078     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4079   } else {
4080     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4081     PetscCall((*f)(mat, b, x));
4082   }
4083   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4084   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4085   PetscFunctionReturn(PETSC_SUCCESS);
4086 }
4087 
4088 /*@
4089   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4090   factored matrix.
4091 
4092   Neighbor-wise Collective
4093 
4094   Input Parameters:
4095 + mat - the factored matrix
4096 . b   - the right-hand-side vector
4097 - y   - the vector to be added to
4098 
4099   Output Parameter:
4100 . x - the result vector
4101 
4102   Level: developer
4103 
4104   Note:
4105   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4106   call `MatSolveTransposeAdd`(A,x,y,x).
4107 
4108 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4109 @*/
4110 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4111 {
4112   PetscScalar one = 1.0;
4113   Vec         tmp;
4114   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4115 
4116   PetscFunctionBegin;
4117   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4118   PetscValidType(mat, 1);
4119   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4120   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4121   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4122   PetscCheckSameComm(mat, 1, b, 2);
4123   PetscCheckSameComm(mat, 1, y, 3);
4124   PetscCheckSameComm(mat, 1, x, 4);
4125   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4126   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);
4127   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);
4128   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);
4129   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);
4130   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4131   MatCheckPreallocated(mat, 1);
4132 
4133   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4134   PetscCall(VecFlag(x, mat->factorerrortype));
4135   if (mat->factorerrortype) {
4136     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4137   } else if (f) {
4138     PetscCall((*f)(mat, b, y, x));
4139   } else {
4140     /* do the solve then the add manually */
4141     if (x != y) {
4142       PetscCall(MatSolveTranspose(mat, b, x));
4143       PetscCall(VecAXPY(x, one, y));
4144     } else {
4145       PetscCall(VecDuplicate(x, &tmp));
4146       PetscCall(VecCopy(x, tmp));
4147       PetscCall(MatSolveTranspose(mat, b, x));
4148       PetscCall(VecAXPY(x, one, tmp));
4149       PetscCall(VecDestroy(&tmp));
4150     }
4151   }
4152   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4153   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4154   PetscFunctionReturn(PETSC_SUCCESS);
4155 }
4156 
4157 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4158 /*@
4159   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4160 
4161   Neighbor-wise Collective
4162 
4163   Input Parameters:
4164 + mat   - the matrix
4165 . b     - the right-hand side
4166 . omega - the relaxation factor
4167 . flag  - flag indicating the type of SOR (see below)
4168 . shift - diagonal shift
4169 . its   - the number of iterations
4170 - lits  - the number of local iterations
4171 
4172   Output Parameter:
4173 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4174 
4175   SOR Flags:
4176 +     `SOR_FORWARD_SWEEP` - forward SOR
4177 .     `SOR_BACKWARD_SWEEP` - backward SOR
4178 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4179 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4180 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4181 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4182 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4183 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4184   upper/lower triangular part of matrix to
4185   vector (with omega)
4186 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4187 
4188   Level: developer
4189 
4190   Notes:
4191   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4192   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4193   on each processor.
4194 
4195   Application programmers will not generally use `MatSOR()` directly,
4196   but instead will employ the `KSP`/`PC` interface.
4197 
4198   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4199 
4200   Most users should employ the `KSP` interface for linear solvers
4201   instead of working directly with matrix algebra routines such as this.
4202   See, e.g., `KSPCreate()`.
4203 
4204   Vectors `x` and `b` CANNOT be the same
4205 
4206   The flags are implemented as bitwise inclusive or operations.
4207   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4208   to specify a zero initial guess for SSOR.
4209 
4210   Developer Note:
4211   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4212 
4213 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4214 @*/
4215 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4216 {
4217   PetscFunctionBegin;
4218   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4219   PetscValidType(mat, 1);
4220   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4221   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4222   PetscCheckSameComm(mat, 1, b, 2);
4223   PetscCheckSameComm(mat, 1, x, 8);
4224   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4225   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4226   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);
4227   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);
4228   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);
4229   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4230   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4231   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4232 
4233   MatCheckPreallocated(mat, 1);
4234   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4235   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4236   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4237   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4238   PetscFunctionReturn(PETSC_SUCCESS);
4239 }
4240 
4241 /*
4242       Default matrix copy routine.
4243 */
4244 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4245 {
4246   PetscInt           i, rstart = 0, rend = 0, nz;
4247   const PetscInt    *cwork;
4248   const PetscScalar *vwork;
4249 
4250   PetscFunctionBegin;
4251   if (B->assembled) PetscCall(MatZeroEntries(B));
4252   if (str == SAME_NONZERO_PATTERN) {
4253     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4254     for (i = rstart; i < rend; i++) {
4255       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4256       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4257       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4258     }
4259   } else {
4260     PetscCall(MatAYPX(B, 0.0, A, str));
4261   }
4262   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4263   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4264   PetscFunctionReturn(PETSC_SUCCESS);
4265 }
4266 
4267 /*@
4268   MatCopy - Copies a matrix to another matrix.
4269 
4270   Collective
4271 
4272   Input Parameters:
4273 + A   - the matrix
4274 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4275 
4276   Output Parameter:
4277 . B - where the copy is put
4278 
4279   Level: intermediate
4280 
4281   Notes:
4282   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4283 
4284   `MatCopy()` copies the matrix entries of a matrix to another existing
4285   matrix (after first zeroing the second matrix).  A related routine is
4286   `MatConvert()`, which first creates a new matrix and then copies the data.
4287 
4288 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4289 @*/
4290 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4291 {
4292   PetscInt i;
4293 
4294   PetscFunctionBegin;
4295   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4296   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4297   PetscValidType(A, 1);
4298   PetscValidType(B, 2);
4299   PetscCheckSameComm(A, 1, B, 2);
4300   MatCheckPreallocated(B, 2);
4301   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4302   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4303   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,
4304              A->cmap->N, B->cmap->N);
4305   MatCheckPreallocated(A, 1);
4306   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4307 
4308   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4309   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4310   else PetscCall(MatCopy_Basic(A, B, str));
4311 
4312   B->stencil.dim = A->stencil.dim;
4313   B->stencil.noc = A->stencil.noc;
4314   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4315     B->stencil.dims[i]   = A->stencil.dims[i];
4316     B->stencil.starts[i] = A->stencil.starts[i];
4317   }
4318 
4319   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4320   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4321   PetscFunctionReturn(PETSC_SUCCESS);
4322 }
4323 
4324 /*@
4325   MatConvert - Converts a matrix to another matrix, either of the same
4326   or different type.
4327 
4328   Collective
4329 
4330   Input Parameters:
4331 + mat     - the matrix
4332 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4333             same type as the original matrix.
4334 - reuse   - denotes if the destination matrix is to be created or reused.
4335             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
4336             `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).
4337 
4338   Output Parameter:
4339 . M - pointer to place new matrix
4340 
4341   Level: intermediate
4342 
4343   Notes:
4344   `MatConvert()` first creates a new matrix and then copies the data from
4345   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4346   entries of one matrix to another already existing matrix context.
4347 
4348   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4349   the MPI communicator of the generated matrix is always the same as the communicator
4350   of the input matrix.
4351 
4352 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4353 @*/
4354 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4355 {
4356   PetscBool  sametype, issame, flg;
4357   PetscBool3 issymmetric, ishermitian;
4358   char       convname[256], mtype[256];
4359   Mat        B;
4360 
4361   PetscFunctionBegin;
4362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4363   PetscValidType(mat, 1);
4364   PetscAssertPointer(M, 4);
4365   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4366   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4367   MatCheckPreallocated(mat, 1);
4368 
4369   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4370   if (flg) newtype = mtype;
4371 
4372   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4373   PetscCall(PetscStrcmp(newtype, "same", &issame));
4374   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4375   if (reuse == MAT_REUSE_MATRIX) {
4376     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4377     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4378   }
4379 
4380   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4381     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4382     PetscFunctionReturn(PETSC_SUCCESS);
4383   }
4384 
4385   /* Cache Mat options because some converters use MatHeaderReplace  */
4386   issymmetric = mat->symmetric;
4387   ishermitian = mat->hermitian;
4388 
4389   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4390     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4391     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4392   } else {
4393     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4394     const char *prefix[3]                                 = {"seq", "mpi", ""};
4395     PetscInt    i;
4396     /*
4397        Order of precedence:
4398        0) See if newtype is a superclass of the current matrix.
4399        1) See if a specialized converter is known to the current matrix.
4400        2) See if a specialized converter is known to the desired matrix class.
4401        3) See if a good general converter is registered for the desired class
4402           (as of 6/27/03 only MATMPIADJ falls into this category).
4403        4) See if a good general converter is known for the current matrix.
4404        5) Use a really basic converter.
4405     */
4406 
4407     /* 0) See if newtype is a superclass of the current matrix.
4408           i.e mat is mpiaij and newtype is aij */
4409     for (i = 0; i < 2; i++) {
4410       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4411       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4412       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4413       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4414       if (flg) {
4415         if (reuse == MAT_INPLACE_MATRIX) {
4416           PetscCall(PetscInfo(mat, "Early return\n"));
4417           PetscFunctionReturn(PETSC_SUCCESS);
4418         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4419           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4420           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4421           PetscFunctionReturn(PETSC_SUCCESS);
4422         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4423           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4424           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4425           PetscFunctionReturn(PETSC_SUCCESS);
4426         }
4427       }
4428     }
4429     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4430     for (i = 0; i < 3; i++) {
4431       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4432       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4433       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4434       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4435       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4436       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4437       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4438       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4439       if (conv) goto foundconv;
4440     }
4441 
4442     /* 2)  See if a specialized converter is known to the desired matrix class. */
4443     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4444     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4445     PetscCall(MatSetType(B, newtype));
4446     for (i = 0; i < 3; i++) {
4447       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4448       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4449       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4450       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4451       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4452       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4453       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4454       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4455       if (conv) {
4456         PetscCall(MatDestroy(&B));
4457         goto foundconv;
4458       }
4459     }
4460 
4461     /* 3) See if a good general converter is registered for the desired class */
4462     conv = B->ops->convertfrom;
4463     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4464     PetscCall(MatDestroy(&B));
4465     if (conv) goto foundconv;
4466 
4467     /* 4) See if a good general converter is known for the current matrix */
4468     if (mat->ops->convert) conv = mat->ops->convert;
4469     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4470     if (conv) goto foundconv;
4471 
4472     /* 5) Use a really basic converter. */
4473     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4474     conv = MatConvert_Basic;
4475 
4476   foundconv:
4477     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4478     PetscCall((*conv)(mat, newtype, reuse, M));
4479     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4480       /* the block sizes must be same if the mappings are copied over */
4481       (*M)->rmap->bs = mat->rmap->bs;
4482       (*M)->cmap->bs = mat->cmap->bs;
4483       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4484       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4485       (*M)->rmap->mapping = mat->rmap->mapping;
4486       (*M)->cmap->mapping = mat->cmap->mapping;
4487     }
4488     (*M)->stencil.dim = mat->stencil.dim;
4489     (*M)->stencil.noc = mat->stencil.noc;
4490     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4491       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4492       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4493     }
4494     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4495   }
4496   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4497 
4498   /* Copy Mat options */
4499   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4500   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4501   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4502   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4503   PetscFunctionReturn(PETSC_SUCCESS);
4504 }
4505 
4506 /*@
4507   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4508 
4509   Not Collective
4510 
4511   Input Parameter:
4512 . mat - the matrix, must be a factored matrix
4513 
4514   Output Parameter:
4515 . type - the string name of the package (do not free this string)
4516 
4517   Level: intermediate
4518 
4519   Fortran Note:
4520   Pass in an empty string that is long enough and the package name will be copied into it.
4521 
4522 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4523 @*/
4524 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4525 {
4526   PetscErrorCode (*conv)(Mat, MatSolverType *);
4527 
4528   PetscFunctionBegin;
4529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4530   PetscValidType(mat, 1);
4531   PetscAssertPointer(type, 2);
4532   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4533   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4534   if (conv) PetscCall((*conv)(mat, type));
4535   else *type = MATSOLVERPETSC;
4536   PetscFunctionReturn(PETSC_SUCCESS);
4537 }
4538 
4539 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4540 struct _MatSolverTypeForSpecifcType {
4541   MatType mtype;
4542   /* no entry for MAT_FACTOR_NONE */
4543   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4544   MatSolverTypeForSpecifcType next;
4545 };
4546 
4547 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4548 struct _MatSolverTypeHolder {
4549   char                       *name;
4550   MatSolverTypeForSpecifcType handlers;
4551   MatSolverTypeHolder         next;
4552 };
4553 
4554 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4555 
4556 /*@C
4557   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4558 
4559   Logically Collective, No Fortran Support
4560 
4561   Input Parameters:
4562 + package      - name of the package, for example petsc or superlu
4563 . mtype        - the matrix type that works with this package
4564 . ftype        - the type of factorization supported by the package
4565 - createfactor - routine that will create the factored matrix ready to be used
4566 
4567   Level: developer
4568 
4569 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4570   `MatGetFactor()`
4571 @*/
4572 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4573 {
4574   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4575   PetscBool                   flg;
4576   MatSolverTypeForSpecifcType inext, iprev = NULL;
4577 
4578   PetscFunctionBegin;
4579   PetscCall(MatInitializePackage());
4580   if (!next) {
4581     PetscCall(PetscNew(&MatSolverTypeHolders));
4582     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4583     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4584     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4585     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4586     PetscFunctionReturn(PETSC_SUCCESS);
4587   }
4588   while (next) {
4589     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4590     if (flg) {
4591       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4592       inext = next->handlers;
4593       while (inext) {
4594         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4595         if (flg) {
4596           inext->createfactor[(int)ftype - 1] = createfactor;
4597           PetscFunctionReturn(PETSC_SUCCESS);
4598         }
4599         iprev = inext;
4600         inext = inext->next;
4601       }
4602       PetscCall(PetscNew(&iprev->next));
4603       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4604       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4605       PetscFunctionReturn(PETSC_SUCCESS);
4606     }
4607     prev = next;
4608     next = next->next;
4609   }
4610   PetscCall(PetscNew(&prev->next));
4611   PetscCall(PetscStrallocpy(package, &prev->next->name));
4612   PetscCall(PetscNew(&prev->next->handlers));
4613   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4614   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4615   PetscFunctionReturn(PETSC_SUCCESS);
4616 }
4617 
4618 /*@C
4619   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4620 
4621   Input Parameters:
4622 + 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
4623 . ftype - the type of factorization supported by the type
4624 - mtype - the matrix type that works with this type
4625 
4626   Output Parameters:
4627 + foundtype    - `PETSC_TRUE` if the type was registered
4628 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4629 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4630 
4631   Calling sequence of `createfactor`:
4632 + A     - the matrix providing the factor matrix
4633 . ftype - the `MatFactorType` of the factor requested
4634 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4635 
4636   Level: developer
4637 
4638   Note:
4639   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4640   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4641   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4642 
4643 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4644           `MatInitializePackage()`
4645 @*/
4646 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4647 {
4648   MatSolverTypeHolder         next = MatSolverTypeHolders;
4649   PetscBool                   flg;
4650   MatSolverTypeForSpecifcType inext;
4651 
4652   PetscFunctionBegin;
4653   if (foundtype) *foundtype = PETSC_FALSE;
4654   if (foundmtype) *foundmtype = PETSC_FALSE;
4655   if (createfactor) *createfactor = NULL;
4656 
4657   if (type) {
4658     while (next) {
4659       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4660       if (flg) {
4661         if (foundtype) *foundtype = PETSC_TRUE;
4662         inext = next->handlers;
4663         while (inext) {
4664           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4665           if (flg) {
4666             if (foundmtype) *foundmtype = PETSC_TRUE;
4667             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4668             PetscFunctionReturn(PETSC_SUCCESS);
4669           }
4670           inext = inext->next;
4671         }
4672       }
4673       next = next->next;
4674     }
4675   } else {
4676     while (next) {
4677       inext = next->handlers;
4678       while (inext) {
4679         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4680         if (flg && inext->createfactor[(int)ftype - 1]) {
4681           if (foundtype) *foundtype = PETSC_TRUE;
4682           if (foundmtype) *foundmtype = PETSC_TRUE;
4683           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4684           PetscFunctionReturn(PETSC_SUCCESS);
4685         }
4686         inext = inext->next;
4687       }
4688       next = next->next;
4689     }
4690     /* try with base classes inext->mtype */
4691     next = MatSolverTypeHolders;
4692     while (next) {
4693       inext = next->handlers;
4694       while (inext) {
4695         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4696         if (flg && inext->createfactor[(int)ftype - 1]) {
4697           if (foundtype) *foundtype = PETSC_TRUE;
4698           if (foundmtype) *foundmtype = PETSC_TRUE;
4699           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4700           PetscFunctionReturn(PETSC_SUCCESS);
4701         }
4702         inext = inext->next;
4703       }
4704       next = next->next;
4705     }
4706   }
4707   PetscFunctionReturn(PETSC_SUCCESS);
4708 }
4709 
4710 PetscErrorCode MatSolverTypeDestroy(void)
4711 {
4712   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4713   MatSolverTypeForSpecifcType inext, iprev;
4714 
4715   PetscFunctionBegin;
4716   while (next) {
4717     PetscCall(PetscFree(next->name));
4718     inext = next->handlers;
4719     while (inext) {
4720       PetscCall(PetscFree(inext->mtype));
4721       iprev = inext;
4722       inext = inext->next;
4723       PetscCall(PetscFree(iprev));
4724     }
4725     prev = next;
4726     next = next->next;
4727     PetscCall(PetscFree(prev));
4728   }
4729   MatSolverTypeHolders = NULL;
4730   PetscFunctionReturn(PETSC_SUCCESS);
4731 }
4732 
4733 /*@
4734   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4735 
4736   Logically Collective
4737 
4738   Input Parameter:
4739 . mat - the matrix
4740 
4741   Output Parameter:
4742 . flg - `PETSC_TRUE` if uses the ordering
4743 
4744   Level: developer
4745 
4746   Note:
4747   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4748   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4749 
4750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4751 @*/
4752 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4753 {
4754   PetscFunctionBegin;
4755   *flg = mat->canuseordering;
4756   PetscFunctionReturn(PETSC_SUCCESS);
4757 }
4758 
4759 /*@
4760   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4761 
4762   Logically Collective
4763 
4764   Input Parameters:
4765 + mat   - the matrix obtained with `MatGetFactor()`
4766 - ftype - the factorization type to be used
4767 
4768   Output Parameter:
4769 . otype - the preferred ordering type
4770 
4771   Level: developer
4772 
4773 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4774 @*/
4775 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4776 {
4777   PetscFunctionBegin;
4778   *otype = mat->preferredordering[ftype];
4779   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4780   PetscFunctionReturn(PETSC_SUCCESS);
4781 }
4782 
4783 /*@
4784   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4785 
4786   Collective
4787 
4788   Input Parameters:
4789 + mat   - the matrix
4790 . 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
4791           the other criteria is returned
4792 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4793 
4794   Output Parameter:
4795 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4796 
4797   Options Database Keys:
4798 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4799 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4800                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4801 
4802   Level: intermediate
4803 
4804   Notes:
4805   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4806   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4807 
4808   Users usually access the factorization solvers via `KSP`
4809 
4810   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4811   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
4812 
4813   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4814   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4815   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4816 
4817   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4818   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4819   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4820 
4821   Developer Note:
4822   This should actually be called `MatCreateFactor()` since it creates a new factor object
4823 
4824 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4825           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4826           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4827 @*/
4828 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4829 {
4830   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4831   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4832 
4833   PetscFunctionBegin;
4834   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4835   PetscValidType(mat, 1);
4836 
4837   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4838   MatCheckPreallocated(mat, 1);
4839 
4840   PetscCall(MatIsShell(mat, &shell));
4841   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4842   if (hasop) {
4843     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4844     PetscFunctionReturn(PETSC_SUCCESS);
4845   }
4846 
4847   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4848   if (!foundtype) {
4849     if (type) {
4850       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],
4851               ((PetscObject)mat)->type_name, type);
4852     } else {
4853       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);
4854     }
4855   }
4856   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4857   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);
4858 
4859   PetscCall((*conv)(mat, ftype, f));
4860   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4861   PetscFunctionReturn(PETSC_SUCCESS);
4862 }
4863 
4864 /*@
4865   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4866 
4867   Not Collective
4868 
4869   Input Parameters:
4870 + mat   - the matrix
4871 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4872 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4873 
4874   Output Parameter:
4875 . flg - PETSC_TRUE if the factorization is available
4876 
4877   Level: intermediate
4878 
4879   Notes:
4880   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4881   such as pastix, superlu, mumps etc.
4882 
4883   PETSc must have been ./configure to use the external solver, using the option --download-package
4884 
4885   Developer Note:
4886   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4887 
4888 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4889           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4890 @*/
4891 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4892 {
4893   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4894 
4895   PetscFunctionBegin;
4896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4897   PetscAssertPointer(flg, 4);
4898 
4899   *flg = PETSC_FALSE;
4900   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4901 
4902   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4903   MatCheckPreallocated(mat, 1);
4904 
4905   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4906   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4907   PetscFunctionReturn(PETSC_SUCCESS);
4908 }
4909 
4910 /*@
4911   MatDuplicate - Duplicates a matrix including the non-zero structure.
4912 
4913   Collective
4914 
4915   Input Parameters:
4916 + mat - the matrix
4917 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4918         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4919 
4920   Output Parameter:
4921 . M - pointer to place new matrix
4922 
4923   Level: intermediate
4924 
4925   Notes:
4926   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4927 
4928   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4929 
4930   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.
4931 
4932   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4933   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4934   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4935 
4936 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4937 @*/
4938 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4939 {
4940   Mat         B;
4941   VecType     vtype;
4942   PetscInt    i;
4943   PetscObject dm, container_h, container_d;
4944   void (*viewf)(void);
4945 
4946   PetscFunctionBegin;
4947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4948   PetscValidType(mat, 1);
4949   PetscAssertPointer(M, 3);
4950   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4951   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4952   MatCheckPreallocated(mat, 1);
4953 
4954   *M = NULL;
4955   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4956   PetscUseTypeMethod(mat, duplicate, op, M);
4957   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4958   B = *M;
4959 
4960   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4961   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4962   PetscCall(MatGetVecType(mat, &vtype));
4963   PetscCall(MatSetVecType(B, vtype));
4964 
4965   B->stencil.dim = mat->stencil.dim;
4966   B->stencil.noc = mat->stencil.noc;
4967   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4968     B->stencil.dims[i]   = mat->stencil.dims[i];
4969     B->stencil.starts[i] = mat->stencil.starts[i];
4970   }
4971 
4972   B->nooffproczerorows = mat->nooffproczerorows;
4973   B->nooffprocentries  = mat->nooffprocentries;
4974 
4975   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4976   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4977   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4978   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4979   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4980   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4981   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
4982   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4983   PetscFunctionReturn(PETSC_SUCCESS);
4984 }
4985 
4986 /*@
4987   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4988 
4989   Logically Collective
4990 
4991   Input Parameter:
4992 . mat - the matrix
4993 
4994   Output Parameter:
4995 . v - the diagonal of the matrix
4996 
4997   Level: intermediate
4998 
4999   Note:
5000   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5001   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5002   is larger than `ndiag`, the values of the remaining entries are unspecified.
5003 
5004   Currently only correct in parallel for square matrices.
5005 
5006 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5007 @*/
5008 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5009 {
5010   PetscFunctionBegin;
5011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5012   PetscValidType(mat, 1);
5013   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5014   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5015   MatCheckPreallocated(mat, 1);
5016   if (PetscDefined(USE_DEBUG)) {
5017     PetscInt nv, row, col, ndiag;
5018 
5019     PetscCall(VecGetLocalSize(v, &nv));
5020     PetscCall(MatGetLocalSize(mat, &row, &col));
5021     ndiag = PetscMin(row, col);
5022     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);
5023   }
5024 
5025   PetscUseTypeMethod(mat, getdiagonal, v);
5026   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5027   PetscFunctionReturn(PETSC_SUCCESS);
5028 }
5029 
5030 /*@
5031   MatGetRowMin - Gets the minimum value (of the real part) of each
5032   row of the matrix
5033 
5034   Logically Collective
5035 
5036   Input Parameter:
5037 . mat - the matrix
5038 
5039   Output Parameters:
5040 + v   - the vector for storing the maximums
5041 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5042 
5043   Level: intermediate
5044 
5045   Note:
5046   The result of this call are the same as if one converted the matrix to dense format
5047   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5048 
5049   This code is only implemented for a couple of matrix formats.
5050 
5051 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5052           `MatGetRowMax()`
5053 @*/
5054 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5055 {
5056   PetscFunctionBegin;
5057   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5058   PetscValidType(mat, 1);
5059   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5060   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5061 
5062   if (!mat->cmap->N) {
5063     PetscCall(VecSet(v, PETSC_MAX_REAL));
5064     if (idx) {
5065       PetscInt i, m = mat->rmap->n;
5066       for (i = 0; i < m; i++) idx[i] = -1;
5067     }
5068   } else {
5069     MatCheckPreallocated(mat, 1);
5070   }
5071   PetscUseTypeMethod(mat, getrowmin, v, idx);
5072   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5073   PetscFunctionReturn(PETSC_SUCCESS);
5074 }
5075 
5076 /*@
5077   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5078   row of the matrix
5079 
5080   Logically Collective
5081 
5082   Input Parameter:
5083 . mat - the matrix
5084 
5085   Output Parameters:
5086 + v   - the vector for storing the minimums
5087 - idx - the indices of the column found for each row (or `NULL` if not needed)
5088 
5089   Level: intermediate
5090 
5091   Notes:
5092   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5093   row is 0 (the first column).
5094 
5095   This code is only implemented for a couple of matrix formats.
5096 
5097 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5098 @*/
5099 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5100 {
5101   PetscFunctionBegin;
5102   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5103   PetscValidType(mat, 1);
5104   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5105   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5106   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5107 
5108   if (!mat->cmap->N) {
5109     PetscCall(VecSet(v, 0.0));
5110     if (idx) {
5111       PetscInt i, m = mat->rmap->n;
5112       for (i = 0; i < m; i++) idx[i] = -1;
5113     }
5114   } else {
5115     MatCheckPreallocated(mat, 1);
5116     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5117     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5118   }
5119   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5120   PetscFunctionReturn(PETSC_SUCCESS);
5121 }
5122 
5123 /*@
5124   MatGetRowMax - Gets the maximum value (of the real part) of each
5125   row of the matrix
5126 
5127   Logically Collective
5128 
5129   Input Parameter:
5130 . mat - the matrix
5131 
5132   Output Parameters:
5133 + v   - the vector for storing the maximums
5134 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5135 
5136   Level: intermediate
5137 
5138   Notes:
5139   The result of this call are the same as if one converted the matrix to dense format
5140   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5141 
5142   This code is only implemented for a couple of matrix formats.
5143 
5144 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5145 @*/
5146 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5147 {
5148   PetscFunctionBegin;
5149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5150   PetscValidType(mat, 1);
5151   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5153 
5154   if (!mat->cmap->N) {
5155     PetscCall(VecSet(v, PETSC_MIN_REAL));
5156     if (idx) {
5157       PetscInt i, m = mat->rmap->n;
5158       for (i = 0; i < m; i++) idx[i] = -1;
5159     }
5160   } else {
5161     MatCheckPreallocated(mat, 1);
5162     PetscUseTypeMethod(mat, getrowmax, v, idx);
5163   }
5164   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5165   PetscFunctionReturn(PETSC_SUCCESS);
5166 }
5167 
5168 /*@
5169   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5170   row of the matrix
5171 
5172   Logically Collective
5173 
5174   Input Parameter:
5175 . mat - the matrix
5176 
5177   Output Parameters:
5178 + v   - the vector for storing the maximums
5179 - idx - the indices of the column found for each row (or `NULL` if not needed)
5180 
5181   Level: intermediate
5182 
5183   Notes:
5184   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5185   row is 0 (the first column).
5186 
5187   This code is only implemented for a couple of matrix formats.
5188 
5189 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5190 @*/
5191 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5192 {
5193   PetscFunctionBegin;
5194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5195   PetscValidType(mat, 1);
5196   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5197   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5198 
5199   if (!mat->cmap->N) {
5200     PetscCall(VecSet(v, 0.0));
5201     if (idx) {
5202       PetscInt i, m = mat->rmap->n;
5203       for (i = 0; i < m; i++) idx[i] = -1;
5204     }
5205   } else {
5206     MatCheckPreallocated(mat, 1);
5207     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5208     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5209   }
5210   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5211   PetscFunctionReturn(PETSC_SUCCESS);
5212 }
5213 
5214 /*@
5215   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5216 
5217   Logically Collective
5218 
5219   Input Parameter:
5220 . mat - the matrix
5221 
5222   Output Parameter:
5223 . v - the vector for storing the sum
5224 
5225   Level: intermediate
5226 
5227   This code is only implemented for a couple of matrix formats.
5228 
5229 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5230 @*/
5231 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5232 {
5233   PetscFunctionBegin;
5234   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5235   PetscValidType(mat, 1);
5236   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5237   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5238 
5239   if (!mat->cmap->N) {
5240     PetscCall(VecSet(v, 0.0));
5241   } else {
5242     MatCheckPreallocated(mat, 1);
5243     PetscUseTypeMethod(mat, getrowsumabs, v);
5244   }
5245   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5246   PetscFunctionReturn(PETSC_SUCCESS);
5247 }
5248 
5249 /*@
5250   MatGetRowSum - Gets the sum of each row of the matrix
5251 
5252   Logically or Neighborhood Collective
5253 
5254   Input Parameter:
5255 . mat - the matrix
5256 
5257   Output Parameter:
5258 . v - the vector for storing the sum of rows
5259 
5260   Level: intermediate
5261 
5262   Note:
5263   This code is slow since it is not currently specialized for different formats
5264 
5265 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5266 @*/
5267 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5268 {
5269   Vec ones;
5270 
5271   PetscFunctionBegin;
5272   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5273   PetscValidType(mat, 1);
5274   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5275   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5276   MatCheckPreallocated(mat, 1);
5277   PetscCall(MatCreateVecs(mat, &ones, NULL));
5278   PetscCall(VecSet(ones, 1.));
5279   PetscCall(MatMult(mat, ones, v));
5280   PetscCall(VecDestroy(&ones));
5281   PetscFunctionReturn(PETSC_SUCCESS);
5282 }
5283 
5284 /*@
5285   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5286   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5287 
5288   Collective
5289 
5290   Input Parameter:
5291 . mat - the matrix to provide the transpose
5292 
5293   Output Parameter:
5294 . 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
5295 
5296   Level: advanced
5297 
5298   Note:
5299   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
5300   routine allows bypassing that call.
5301 
5302 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5303 @*/
5304 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5305 {
5306   MatParentState *rb = NULL;
5307 
5308   PetscFunctionBegin;
5309   PetscCall(PetscNew(&rb));
5310   rb->id    = ((PetscObject)mat)->id;
5311   rb->state = 0;
5312   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5313   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscContainerUserDestroyDefault));
5314   PetscFunctionReturn(PETSC_SUCCESS);
5315 }
5316 
5317 /*@
5318   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5319 
5320   Collective
5321 
5322   Input Parameters:
5323 + mat   - the matrix to transpose
5324 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5325 
5326   Output Parameter:
5327 . B - the transpose of the matrix
5328 
5329   Level: intermediate
5330 
5331   Notes:
5332   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5333 
5334   `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the
5335   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5336 
5337   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.
5338 
5339   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5340   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5341 
5342   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5343 
5344   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5345 
5346 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5347           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5348 @*/
5349 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5350 {
5351   PetscContainer  rB = NULL;
5352   MatParentState *rb = NULL;
5353 
5354   PetscFunctionBegin;
5355   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5356   PetscValidType(mat, 1);
5357   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5358   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5359   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5360   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5361   MatCheckPreallocated(mat, 1);
5362   if (reuse == MAT_REUSE_MATRIX) {
5363     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5364     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5365     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5366     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5367     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5368   }
5369 
5370   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5371   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5372     PetscUseTypeMethod(mat, transpose, reuse, B);
5373     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5374   }
5375   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5376 
5377   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5378   if (reuse != MAT_INPLACE_MATRIX) {
5379     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5380     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5381     rb->state        = ((PetscObject)mat)->state;
5382     rb->nonzerostate = mat->nonzerostate;
5383   }
5384   PetscFunctionReturn(PETSC_SUCCESS);
5385 }
5386 
5387 /*@
5388   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5389 
5390   Collective
5391 
5392   Input Parameter:
5393 . A - the matrix to transpose
5394 
5395   Output Parameter:
5396 . 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
5397       numerical portion.
5398 
5399   Level: intermediate
5400 
5401   Note:
5402   This is not supported for many matrix types, use `MatTranspose()` in those cases
5403 
5404 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5405 @*/
5406 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5407 {
5408   PetscFunctionBegin;
5409   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5410   PetscValidType(A, 1);
5411   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5412   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5413   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5414   PetscUseTypeMethod(A, transposesymbolic, B);
5415   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5416 
5417   PetscCall(MatTransposeSetPrecursor(A, *B));
5418   PetscFunctionReturn(PETSC_SUCCESS);
5419 }
5420 
5421 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5422 {
5423   PetscContainer  rB;
5424   MatParentState *rb;
5425 
5426   PetscFunctionBegin;
5427   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5428   PetscValidType(A, 1);
5429   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5430   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5431   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5432   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5433   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5434   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5435   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5436   PetscFunctionReturn(PETSC_SUCCESS);
5437 }
5438 
5439 /*@
5440   MatIsTranspose - Test whether a matrix is another one's transpose,
5441   or its own, in which case it tests symmetry.
5442 
5443   Collective
5444 
5445   Input Parameters:
5446 + A   - the matrix to test
5447 . B   - the matrix to test against, this can equal the first parameter
5448 - tol - tolerance, differences between entries smaller than this are counted as zero
5449 
5450   Output Parameter:
5451 . flg - the result
5452 
5453   Level: intermediate
5454 
5455   Notes:
5456   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5457   test involves parallel copies of the block off-diagonal parts of the matrix.
5458 
5459 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5460 @*/
5461 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5462 {
5463   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5464 
5465   PetscFunctionBegin;
5466   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5467   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5468   PetscAssertPointer(flg, 4);
5469   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5470   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5471   *flg = PETSC_FALSE;
5472   if (f && g) {
5473     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5474     PetscCall((*f)(A, B, tol, flg));
5475   } else {
5476     MatType mattype;
5477 
5478     PetscCall(MatGetType(f ? B : A, &mattype));
5479     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5480   }
5481   PetscFunctionReturn(PETSC_SUCCESS);
5482 }
5483 
5484 /*@
5485   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5486 
5487   Collective
5488 
5489   Input Parameters:
5490 + mat   - the matrix to transpose and complex conjugate
5491 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5492 
5493   Output Parameter:
5494 . B - the Hermitian transpose
5495 
5496   Level: intermediate
5497 
5498 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5499 @*/
5500 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5501 {
5502   PetscFunctionBegin;
5503   PetscCall(MatTranspose(mat, reuse, B));
5504 #if defined(PETSC_USE_COMPLEX)
5505   PetscCall(MatConjugate(*B));
5506 #endif
5507   PetscFunctionReturn(PETSC_SUCCESS);
5508 }
5509 
5510 /*@
5511   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5512 
5513   Collective
5514 
5515   Input Parameters:
5516 + A   - the matrix to test
5517 . B   - the matrix to test against, this can equal the first parameter
5518 - tol - tolerance, differences between entries smaller than this are counted as zero
5519 
5520   Output Parameter:
5521 . flg - the result
5522 
5523   Level: intermediate
5524 
5525   Notes:
5526   Only available for `MATAIJ` matrices.
5527 
5528   The sequential algorithm
5529   has a running time of the order of the number of nonzeros; the parallel
5530   test involves parallel copies of the block off-diagonal parts of the matrix.
5531 
5532 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5533 @*/
5534 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5535 {
5536   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5537 
5538   PetscFunctionBegin;
5539   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5540   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5541   PetscAssertPointer(flg, 4);
5542   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5543   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5544   if (f && g) {
5545     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5546     PetscCall((*f)(A, B, tol, flg));
5547   }
5548   PetscFunctionReturn(PETSC_SUCCESS);
5549 }
5550 
5551 /*@
5552   MatPermute - Creates a new matrix with rows and columns permuted from the
5553   original.
5554 
5555   Collective
5556 
5557   Input Parameters:
5558 + mat - the matrix to permute
5559 . row - row permutation, each processor supplies only the permutation for its rows
5560 - col - column permutation, each processor supplies only the permutation for its columns
5561 
5562   Output Parameter:
5563 . B - the permuted matrix
5564 
5565   Level: advanced
5566 
5567   Note:
5568   The index sets map from row/col of permuted matrix to row/col of original matrix.
5569   The index sets should be on the same communicator as mat and have the same local sizes.
5570 
5571   Developer Note:
5572   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5573   exploit the fact that row and col are permutations, consider implementing the
5574   more general `MatCreateSubMatrix()` instead.
5575 
5576 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5577 @*/
5578 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5579 {
5580   PetscFunctionBegin;
5581   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5582   PetscValidType(mat, 1);
5583   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5584   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5585   PetscAssertPointer(B, 4);
5586   PetscCheckSameComm(mat, 1, row, 2);
5587   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5588   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5589   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5590   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5591   MatCheckPreallocated(mat, 1);
5592 
5593   if (mat->ops->permute) {
5594     PetscUseTypeMethod(mat, permute, row, col, B);
5595     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5596   } else {
5597     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5598   }
5599   PetscFunctionReturn(PETSC_SUCCESS);
5600 }
5601 
5602 /*@
5603   MatEqual - Compares two matrices.
5604 
5605   Collective
5606 
5607   Input Parameters:
5608 + A - the first matrix
5609 - B - the second matrix
5610 
5611   Output Parameter:
5612 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5613 
5614   Level: intermediate
5615 
5616   Note:
5617   If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product
5618   using several randomly created vectors, see `MatMultEqual()`.
5619 
5620 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5621 @*/
5622 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5623 {
5624   PetscFunctionBegin;
5625   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5626   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5627   PetscValidType(A, 1);
5628   PetscValidType(B, 2);
5629   PetscAssertPointer(flg, 3);
5630   PetscCheckSameComm(A, 1, B, 2);
5631   MatCheckPreallocated(A, 1);
5632   MatCheckPreallocated(B, 2);
5633   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5634   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5635   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,
5636              B->cmap->N);
5637   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5638     PetscUseTypeMethod(A, equal, B, flg);
5639   } else {
5640     PetscCall(MatMultEqual(A, B, 10, flg));
5641   }
5642   PetscFunctionReturn(PETSC_SUCCESS);
5643 }
5644 
5645 /*@
5646   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5647   matrices that are stored as vectors.  Either of the two scaling
5648   matrices can be `NULL`.
5649 
5650   Collective
5651 
5652   Input Parameters:
5653 + mat - the matrix to be scaled
5654 . l   - the left scaling vector (or `NULL`)
5655 - r   - the right scaling vector (or `NULL`)
5656 
5657   Level: intermediate
5658 
5659   Note:
5660   `MatDiagonalScale()` computes $A = LAR$, where
5661   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5662   The L scales the rows of the matrix, the R scales the columns of the matrix.
5663 
5664 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5665 @*/
5666 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5667 {
5668   PetscFunctionBegin;
5669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5670   PetscValidType(mat, 1);
5671   if (l) {
5672     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5673     PetscCheckSameComm(mat, 1, l, 2);
5674   }
5675   if (r) {
5676     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5677     PetscCheckSameComm(mat, 1, r, 3);
5678   }
5679   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5680   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5681   MatCheckPreallocated(mat, 1);
5682   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5683 
5684   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5685   PetscUseTypeMethod(mat, diagonalscale, l, r);
5686   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5687   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5688   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5689   PetscFunctionReturn(PETSC_SUCCESS);
5690 }
5691 
5692 /*@
5693   MatScale - Scales all elements of a matrix by a given number.
5694 
5695   Logically Collective
5696 
5697   Input Parameters:
5698 + mat - the matrix to be scaled
5699 - a   - the scaling value
5700 
5701   Level: intermediate
5702 
5703 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5704 @*/
5705 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5706 {
5707   PetscFunctionBegin;
5708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5709   PetscValidType(mat, 1);
5710   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5711   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5712   PetscValidLogicalCollectiveScalar(mat, a, 2);
5713   MatCheckPreallocated(mat, 1);
5714 
5715   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5716   if (a != (PetscScalar)1.0) {
5717     PetscUseTypeMethod(mat, scale, a);
5718     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5719   }
5720   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5721   PetscFunctionReturn(PETSC_SUCCESS);
5722 }
5723 
5724 /*@
5725   MatNorm - Calculates various norms of a matrix.
5726 
5727   Collective
5728 
5729   Input Parameters:
5730 + mat  - the matrix
5731 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5732 
5733   Output Parameter:
5734 . nrm - the resulting norm
5735 
5736   Level: intermediate
5737 
5738 .seealso: [](ch_matrices), `Mat`
5739 @*/
5740 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5741 {
5742   PetscFunctionBegin;
5743   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5744   PetscValidType(mat, 1);
5745   PetscAssertPointer(nrm, 3);
5746 
5747   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5748   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5749   MatCheckPreallocated(mat, 1);
5750 
5751   PetscUseTypeMethod(mat, norm, type, nrm);
5752   PetscFunctionReturn(PETSC_SUCCESS);
5753 }
5754 
5755 /*
5756      This variable is used to prevent counting of MatAssemblyBegin() that
5757    are called from within a MatAssemblyEnd().
5758 */
5759 static PetscInt MatAssemblyEnd_InUse = 0;
5760 /*@
5761   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5762   be called after completing all calls to `MatSetValues()`.
5763 
5764   Collective
5765 
5766   Input Parameters:
5767 + mat  - the matrix
5768 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5769 
5770   Level: beginner
5771 
5772   Notes:
5773   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5774   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5775 
5776   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5777   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5778   using the matrix.
5779 
5780   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5781   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
5782   a global collective operation requiring all processes that share the matrix.
5783 
5784   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5785   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5786   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5787 
5788 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5789 @*/
5790 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5791 {
5792   PetscFunctionBegin;
5793   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5794   PetscValidType(mat, 1);
5795   MatCheckPreallocated(mat, 1);
5796   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5797   if (mat->assembled) {
5798     mat->was_assembled = PETSC_TRUE;
5799     mat->assembled     = PETSC_FALSE;
5800   }
5801 
5802   if (!MatAssemblyEnd_InUse) {
5803     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5804     PetscTryTypeMethod(mat, assemblybegin, type);
5805     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5806   } else PetscTryTypeMethod(mat, assemblybegin, type);
5807   PetscFunctionReturn(PETSC_SUCCESS);
5808 }
5809 
5810 /*@
5811   MatAssembled - Indicates if a matrix has been assembled and is ready for
5812   use; for example, in matrix-vector product.
5813 
5814   Not Collective
5815 
5816   Input Parameter:
5817 . mat - the matrix
5818 
5819   Output Parameter:
5820 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5821 
5822   Level: advanced
5823 
5824 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5825 @*/
5826 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5827 {
5828   PetscFunctionBegin;
5829   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5830   PetscAssertPointer(assembled, 2);
5831   *assembled = mat->assembled;
5832   PetscFunctionReturn(PETSC_SUCCESS);
5833 }
5834 
5835 /*@
5836   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5837   be called after `MatAssemblyBegin()`.
5838 
5839   Collective
5840 
5841   Input Parameters:
5842 + mat  - the matrix
5843 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5844 
5845   Options Database Keys:
5846 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5847 . -mat_view ::ascii_info_detail      - Prints more detailed info
5848 . -mat_view                          - Prints matrix in ASCII format
5849 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5850 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5851 . -display <name>                    - Sets display name (default is host)
5852 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5853 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5854 . -viewer_socket_machine <machine>   - Machine to use for socket
5855 . -viewer_socket_port <port>         - Port number to use for socket
5856 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5857 
5858   Level: beginner
5859 
5860 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5861 @*/
5862 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5863 {
5864   static PetscInt inassm = 0;
5865   PetscBool       flg    = PETSC_FALSE;
5866 
5867   PetscFunctionBegin;
5868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5869   PetscValidType(mat, 1);
5870 
5871   inassm++;
5872   MatAssemblyEnd_InUse++;
5873   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5874     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5875     PetscTryTypeMethod(mat, assemblyend, type);
5876     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5877   } else PetscTryTypeMethod(mat, assemblyend, type);
5878 
5879   /* Flush assembly is not a true assembly */
5880   if (type != MAT_FLUSH_ASSEMBLY) {
5881     if (mat->num_ass) {
5882       if (!mat->symmetry_eternal) {
5883         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5884         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5885       }
5886       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5887       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5888     }
5889     mat->num_ass++;
5890     mat->assembled        = PETSC_TRUE;
5891     mat->ass_nonzerostate = mat->nonzerostate;
5892   }
5893 
5894   mat->insertmode = NOT_SET_VALUES;
5895   MatAssemblyEnd_InUse--;
5896   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5897   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5898     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5899 
5900     if (mat->checksymmetryonassembly) {
5901       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5902       if (flg) {
5903         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5904       } else {
5905         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5906       }
5907     }
5908     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5909   }
5910   inassm--;
5911   PetscFunctionReturn(PETSC_SUCCESS);
5912 }
5913 
5914 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5915 /*@
5916   MatSetOption - Sets a parameter option for a matrix. Some options
5917   may be specific to certain storage formats.  Some options
5918   determine how values will be inserted (or added). Sorted,
5919   row-oriented input will generally assemble the fastest. The default
5920   is row-oriented.
5921 
5922   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5923 
5924   Input Parameters:
5925 + mat - the matrix
5926 . op  - the option, one of those listed below (and possibly others),
5927 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5928 
5929   Options Describing Matrix Structure:
5930 + `MAT_SPD`                         - symmetric positive definite
5931 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5932 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5933 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5934 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5935 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5936 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5937 
5938    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5939    do not need to be computed (usually at a high cost)
5940 
5941    Options For Use with `MatSetValues()`:
5942    Insert a logically dense subblock, which can be
5943 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5944 
5945    These options reflect the data you pass in with `MatSetValues()`; it has
5946    nothing to do with how the data is stored internally in the matrix
5947    data structure.
5948 
5949    When (re)assembling a matrix, we can restrict the input for
5950    efficiency/debugging purposes.  These options include
5951 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5952 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5953 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5954 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5955 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5956 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5957         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5958         performance for very large process counts.
5959 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5960         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5961         functions, instead sending only neighbor messages.
5962 
5963   Level: intermediate
5964 
5965   Notes:
5966   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5967 
5968   Some options are relevant only for particular matrix types and
5969   are thus ignored by others.  Other options are not supported by
5970   certain matrix types and will generate an error message if set.
5971 
5972   If using Fortran to compute a matrix, one may need to
5973   use the column-oriented option (or convert to the row-oriented
5974   format).
5975 
5976   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5977   that would generate a new entry in the nonzero structure is instead
5978   ignored.  Thus, if memory has not already been allocated for this particular
5979   data, then the insertion is ignored. For dense matrices, in which
5980   the entire array is allocated, no entries are ever ignored.
5981   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5982 
5983   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5984   that would generate a new entry in the nonzero structure instead produces
5985   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
5986 
5987   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5988   that would generate a new entry that has not been preallocated will
5989   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5990   only.) This is a useful flag when debugging matrix memory preallocation.
5991   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5992 
5993   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5994   other processors should be dropped, rather than stashed.
5995   This is useful if you know that the "owning" processor is also
5996   always generating the correct matrix entries, so that PETSc need
5997   not transfer duplicate entries generated on another processor.
5998 
5999   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6000   searches during matrix assembly. When this flag is set, the hash table
6001   is created during the first matrix assembly. This hash table is
6002   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6003   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6004   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6005   supported by `MATMPIBAIJ` format only.
6006 
6007   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6008   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6009 
6010   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6011   a zero location in the matrix
6012 
6013   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6014 
6015   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6016   zero row routines and thus improves performance for very large process counts.
6017 
6018   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6019   part of the matrix (since they should match the upper triangular part).
6020 
6021   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6022   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6023   with finite difference schemes with non-periodic boundary conditions.
6024 
6025   Developer Note:
6026   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6027   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6028   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6029   not changed.
6030 
6031 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6032 @*/
6033 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6034 {
6035   PetscFunctionBegin;
6036   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6037   if (op > 0) {
6038     PetscValidLogicalCollectiveEnum(mat, op, 2);
6039     PetscValidLogicalCollectiveBool(mat, flg, 3);
6040   }
6041 
6042   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);
6043 
6044   switch (op) {
6045   case MAT_FORCE_DIAGONAL_ENTRIES:
6046     mat->force_diagonals = flg;
6047     PetscFunctionReturn(PETSC_SUCCESS);
6048   case MAT_NO_OFF_PROC_ENTRIES:
6049     mat->nooffprocentries = flg;
6050     PetscFunctionReturn(PETSC_SUCCESS);
6051   case MAT_SUBSET_OFF_PROC_ENTRIES:
6052     mat->assembly_subset = flg;
6053     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6054 #if !defined(PETSC_HAVE_MPIUNI)
6055       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6056 #endif
6057       mat->stash.first_assembly_done = PETSC_FALSE;
6058     }
6059     PetscFunctionReturn(PETSC_SUCCESS);
6060   case MAT_NO_OFF_PROC_ZERO_ROWS:
6061     mat->nooffproczerorows = flg;
6062     PetscFunctionReturn(PETSC_SUCCESS);
6063   case MAT_SPD:
6064     if (flg) {
6065       mat->spd                    = PETSC_BOOL3_TRUE;
6066       mat->symmetric              = PETSC_BOOL3_TRUE;
6067       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6068     } else {
6069       mat->spd = PETSC_BOOL3_FALSE;
6070     }
6071     break;
6072   case MAT_SYMMETRIC:
6073     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6074     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6075 #if !defined(PETSC_USE_COMPLEX)
6076     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6077 #endif
6078     break;
6079   case MAT_HERMITIAN:
6080     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6081     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6082 #if !defined(PETSC_USE_COMPLEX)
6083     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6084 #endif
6085     break;
6086   case MAT_STRUCTURALLY_SYMMETRIC:
6087     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6088     break;
6089   case MAT_SYMMETRY_ETERNAL:
6090     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");
6091     mat->symmetry_eternal = flg;
6092     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6093     break;
6094   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6095     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");
6096     mat->structural_symmetry_eternal = flg;
6097     break;
6098   case MAT_SPD_ETERNAL:
6099     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");
6100     mat->spd_eternal = flg;
6101     if (flg) {
6102       mat->structural_symmetry_eternal = PETSC_TRUE;
6103       mat->symmetry_eternal            = PETSC_TRUE;
6104     }
6105     break;
6106   case MAT_STRUCTURE_ONLY:
6107     mat->structure_only = flg;
6108     break;
6109   case MAT_SORTED_FULL:
6110     mat->sortedfull = flg;
6111     break;
6112   default:
6113     break;
6114   }
6115   PetscTryTypeMethod(mat, setoption, op, flg);
6116   PetscFunctionReturn(PETSC_SUCCESS);
6117 }
6118 
6119 /*@
6120   MatGetOption - Gets a parameter option that has been set for a matrix.
6121 
6122   Logically Collective
6123 
6124   Input Parameters:
6125 + mat - the matrix
6126 - op  - the option, this only responds to certain options, check the code for which ones
6127 
6128   Output Parameter:
6129 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6130 
6131   Level: intermediate
6132 
6133   Notes:
6134   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6135 
6136   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6137   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6138 
6139 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6140     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6141 @*/
6142 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6143 {
6144   PetscFunctionBegin;
6145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6146   PetscValidType(mat, 1);
6147 
6148   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);
6149   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()");
6150 
6151   switch (op) {
6152   case MAT_NO_OFF_PROC_ENTRIES:
6153     *flg = mat->nooffprocentries;
6154     break;
6155   case MAT_NO_OFF_PROC_ZERO_ROWS:
6156     *flg = mat->nooffproczerorows;
6157     break;
6158   case MAT_SYMMETRIC:
6159     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6160     break;
6161   case MAT_HERMITIAN:
6162     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6163     break;
6164   case MAT_STRUCTURALLY_SYMMETRIC:
6165     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6166     break;
6167   case MAT_SPD:
6168     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6169     break;
6170   case MAT_SYMMETRY_ETERNAL:
6171     *flg = mat->symmetry_eternal;
6172     break;
6173   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6174     *flg = mat->symmetry_eternal;
6175     break;
6176   default:
6177     break;
6178   }
6179   PetscFunctionReturn(PETSC_SUCCESS);
6180 }
6181 
6182 /*@
6183   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6184   this routine retains the old nonzero structure.
6185 
6186   Logically Collective
6187 
6188   Input Parameter:
6189 . mat - the matrix
6190 
6191   Level: intermediate
6192 
6193   Note:
6194   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.
6195   See the Performance chapter of the users manual for information on preallocating matrices.
6196 
6197 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6198 @*/
6199 PetscErrorCode MatZeroEntries(Mat mat)
6200 {
6201   PetscFunctionBegin;
6202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6203   PetscValidType(mat, 1);
6204   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6205   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");
6206   MatCheckPreallocated(mat, 1);
6207 
6208   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6209   PetscUseTypeMethod(mat, zeroentries);
6210   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6211   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6212   PetscFunctionReturn(PETSC_SUCCESS);
6213 }
6214 
6215 /*@
6216   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6217   of a set of rows and columns of a matrix.
6218 
6219   Collective
6220 
6221   Input Parameters:
6222 + mat     - the matrix
6223 . numRows - the number of rows/columns to zero
6224 . rows    - the global row indices
6225 . diag    - value put in the diagonal of the eliminated rows
6226 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6227 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6228 
6229   Level: intermediate
6230 
6231   Notes:
6232   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6233 
6234   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6235   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
6236 
6237   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6238   Krylov method to take advantage of the known solution on the zeroed rows.
6239 
6240   For the parallel case, all processes that share the matrix (i.e.,
6241   those in the communicator used for matrix creation) MUST call this
6242   routine, regardless of whether any rows being zeroed are owned by
6243   them.
6244 
6245   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6246   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
6247   missing.
6248 
6249   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6250   list only rows local to itself).
6251 
6252   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6253 
6254 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6255           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6256 @*/
6257 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6258 {
6259   PetscFunctionBegin;
6260   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6261   PetscValidType(mat, 1);
6262   if (numRows) PetscAssertPointer(rows, 3);
6263   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6264   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6265   MatCheckPreallocated(mat, 1);
6266 
6267   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6268   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6269   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6270   PetscFunctionReturn(PETSC_SUCCESS);
6271 }
6272 
6273 /*@
6274   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6275   of a set of rows and columns of a matrix.
6276 
6277   Collective
6278 
6279   Input Parameters:
6280 + mat  - the matrix
6281 . is   - the rows to zero
6282 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6283 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6284 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6285 
6286   Level: intermediate
6287 
6288   Note:
6289   See `MatZeroRowsColumns()` for details on how this routine operates.
6290 
6291 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6292           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6293 @*/
6294 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6295 {
6296   PetscInt        numRows;
6297   const PetscInt *rows;
6298 
6299   PetscFunctionBegin;
6300   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6301   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6302   PetscValidType(mat, 1);
6303   PetscValidType(is, 2);
6304   PetscCall(ISGetLocalSize(is, &numRows));
6305   PetscCall(ISGetIndices(is, &rows));
6306   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6307   PetscCall(ISRestoreIndices(is, &rows));
6308   PetscFunctionReturn(PETSC_SUCCESS);
6309 }
6310 
6311 /*@
6312   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6313   of a set of rows of a matrix.
6314 
6315   Collective
6316 
6317   Input Parameters:
6318 + mat     - the matrix
6319 . numRows - the number of rows to zero
6320 . rows    - the global row indices
6321 . diag    - value put in the diagonal of the zeroed rows
6322 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6323 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6324 
6325   Level: intermediate
6326 
6327   Notes:
6328   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6329 
6330   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6331 
6332   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6333   Krylov method to take advantage of the known solution on the zeroed rows.
6334 
6335   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)
6336   from the matrix.
6337 
6338   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6339   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6340   formats this does not alter the nonzero structure.
6341 
6342   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6343   of the matrix is not changed the values are
6344   merely zeroed.
6345 
6346   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6347   formats can optionally remove the main diagonal entry from the
6348   nonzero structure as well, by passing 0.0 as the final argument).
6349 
6350   For the parallel case, all processes that share the matrix (i.e.,
6351   those in the communicator used for matrix creation) MUST call this
6352   routine, regardless of whether any rows being zeroed are owned by
6353   them.
6354 
6355   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6356   list only rows local to itself).
6357 
6358   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6359   owns that are to be zeroed. This saves a global synchronization in the implementation.
6360 
6361 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6362           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6363 @*/
6364 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6365 {
6366   PetscFunctionBegin;
6367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6368   PetscValidType(mat, 1);
6369   if (numRows) PetscAssertPointer(rows, 3);
6370   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6371   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6372   MatCheckPreallocated(mat, 1);
6373 
6374   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6375   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6376   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6377   PetscFunctionReturn(PETSC_SUCCESS);
6378 }
6379 
6380 /*@
6381   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6382   of a set of rows of a matrix indicated by an `IS`
6383 
6384   Collective
6385 
6386   Input Parameters:
6387 + mat  - the matrix
6388 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6389 . diag - value put in all diagonals of eliminated rows
6390 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6391 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6392 
6393   Level: intermediate
6394 
6395   Note:
6396   See `MatZeroRows()` for details on how this routine operates.
6397 
6398 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6399           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6400 @*/
6401 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6402 {
6403   PetscInt        numRows = 0;
6404   const PetscInt *rows    = NULL;
6405 
6406   PetscFunctionBegin;
6407   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6408   PetscValidType(mat, 1);
6409   if (is) {
6410     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6411     PetscCall(ISGetLocalSize(is, &numRows));
6412     PetscCall(ISGetIndices(is, &rows));
6413   }
6414   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6415   if (is) PetscCall(ISRestoreIndices(is, &rows));
6416   PetscFunctionReturn(PETSC_SUCCESS);
6417 }
6418 
6419 /*@
6420   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6421   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6422 
6423   Collective
6424 
6425   Input Parameters:
6426 + mat     - the matrix
6427 . numRows - the number of rows to remove
6428 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6429 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6430 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6431 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6432 
6433   Level: intermediate
6434 
6435   Notes:
6436   See `MatZeroRows()` for details on how this routine operates.
6437 
6438   The grid coordinates are across the entire grid, not just the local portion
6439 
6440   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6441   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6442   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6443   `DM_BOUNDARY_PERIODIC` boundary type.
6444 
6445   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
6446   a single value per point) you can skip filling those indices.
6447 
6448   Fortran Note:
6449   `idxm` and `idxn` should be declared as
6450 $     MatStencil idxm(4, m)
6451   and the values inserted using
6452 .vb
6453     idxm(MatStencil_i, 1) = i
6454     idxm(MatStencil_j, 1) = j
6455     idxm(MatStencil_k, 1) = k
6456     idxm(MatStencil_c, 1) = c
6457    etc
6458 .ve
6459 
6460 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6461           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6462 @*/
6463 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6464 {
6465   PetscInt  dim    = mat->stencil.dim;
6466   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6467   PetscInt *dims   = mat->stencil.dims + 1;
6468   PetscInt *starts = mat->stencil.starts;
6469   PetscInt *dxm    = (PetscInt *)rows;
6470   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6471 
6472   PetscFunctionBegin;
6473   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6474   PetscValidType(mat, 1);
6475   if (numRows) PetscAssertPointer(rows, 3);
6476 
6477   PetscCall(PetscMalloc1(numRows, &jdxm));
6478   for (i = 0; i < numRows; ++i) {
6479     /* Skip unused dimensions (they are ordered k, j, i, c) */
6480     for (j = 0; j < 3 - sdim; ++j) dxm++;
6481     /* Local index in X dir */
6482     tmp = *dxm++ - starts[0];
6483     /* Loop over remaining dimensions */
6484     for (j = 0; j < dim - 1; ++j) {
6485       /* If nonlocal, set index to be negative */
6486       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6487       /* Update local index */
6488       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6489     }
6490     /* Skip component slot if necessary */
6491     if (mat->stencil.noc) dxm++;
6492     /* Local row number */
6493     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6494   }
6495   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6496   PetscCall(PetscFree(jdxm));
6497   PetscFunctionReturn(PETSC_SUCCESS);
6498 }
6499 
6500 /*@
6501   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6502   of a set of rows and columns of a matrix.
6503 
6504   Collective
6505 
6506   Input Parameters:
6507 + mat     - the matrix
6508 . numRows - the number of rows/columns to remove
6509 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6510 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6511 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6512 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6513 
6514   Level: intermediate
6515 
6516   Notes:
6517   See `MatZeroRowsColumns()` for details on how this routine operates.
6518 
6519   The grid coordinates are across the entire grid, not just the local portion
6520 
6521   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6522   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6523   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6524   `DM_BOUNDARY_PERIODIC` boundary type.
6525 
6526   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
6527   a single value per point) you can skip filling those indices.
6528 
6529   Fortran Note:
6530   `idxm` and `idxn` should be declared as
6531 $     MatStencil idxm(4, m)
6532   and the values inserted using
6533 .vb
6534     idxm(MatStencil_i, 1) = i
6535     idxm(MatStencil_j, 1) = j
6536     idxm(MatStencil_k, 1) = k
6537     idxm(MatStencil_c, 1) = c
6538     etc
6539 .ve
6540 
6541 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6542           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6543 @*/
6544 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6545 {
6546   PetscInt  dim    = mat->stencil.dim;
6547   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6548   PetscInt *dims   = mat->stencil.dims + 1;
6549   PetscInt *starts = mat->stencil.starts;
6550   PetscInt *dxm    = (PetscInt *)rows;
6551   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6552 
6553   PetscFunctionBegin;
6554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6555   PetscValidType(mat, 1);
6556   if (numRows) PetscAssertPointer(rows, 3);
6557 
6558   PetscCall(PetscMalloc1(numRows, &jdxm));
6559   for (i = 0; i < numRows; ++i) {
6560     /* Skip unused dimensions (they are ordered k, j, i, c) */
6561     for (j = 0; j < 3 - sdim; ++j) dxm++;
6562     /* Local index in X dir */
6563     tmp = *dxm++ - starts[0];
6564     /* Loop over remaining dimensions */
6565     for (j = 0; j < dim - 1; ++j) {
6566       /* If nonlocal, set index to be negative */
6567       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6568       /* Update local index */
6569       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6570     }
6571     /* Skip component slot if necessary */
6572     if (mat->stencil.noc) dxm++;
6573     /* Local row number */
6574     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6575   }
6576   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6577   PetscCall(PetscFree(jdxm));
6578   PetscFunctionReturn(PETSC_SUCCESS);
6579 }
6580 
6581 /*@
6582   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6583   of a set of rows of a matrix; using local numbering of rows.
6584 
6585   Collective
6586 
6587   Input Parameters:
6588 + mat     - the matrix
6589 . numRows - the number of rows to remove
6590 . rows    - the local row indices
6591 . diag    - value put in all diagonals of eliminated rows
6592 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6593 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6594 
6595   Level: intermediate
6596 
6597   Notes:
6598   Before calling `MatZeroRowsLocal()`, the user must first set the
6599   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6600 
6601   See `MatZeroRows()` for details on how this routine operates.
6602 
6603 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6604           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6605 @*/
6606 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6607 {
6608   PetscFunctionBegin;
6609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6610   PetscValidType(mat, 1);
6611   if (numRows) PetscAssertPointer(rows, 3);
6612   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6613   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6614   MatCheckPreallocated(mat, 1);
6615 
6616   if (mat->ops->zerorowslocal) {
6617     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6618   } else {
6619     IS              is, newis;
6620     const PetscInt *newRows;
6621 
6622     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6623     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6624     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6625     PetscCall(ISGetIndices(newis, &newRows));
6626     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6627     PetscCall(ISRestoreIndices(newis, &newRows));
6628     PetscCall(ISDestroy(&newis));
6629     PetscCall(ISDestroy(&is));
6630   }
6631   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6632   PetscFunctionReturn(PETSC_SUCCESS);
6633 }
6634 
6635 /*@
6636   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6637   of a set of rows of a matrix; using local numbering of rows.
6638 
6639   Collective
6640 
6641   Input Parameters:
6642 + mat  - the matrix
6643 . is   - index set of rows to remove
6644 . diag - value put in all diagonals of eliminated rows
6645 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6646 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6647 
6648   Level: intermediate
6649 
6650   Notes:
6651   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6652   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6653 
6654   See `MatZeroRows()` for details on how this routine operates.
6655 
6656 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6657           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6658 @*/
6659 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6660 {
6661   PetscInt        numRows;
6662   const PetscInt *rows;
6663 
6664   PetscFunctionBegin;
6665   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6666   PetscValidType(mat, 1);
6667   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6668   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6669   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6670   MatCheckPreallocated(mat, 1);
6671 
6672   PetscCall(ISGetLocalSize(is, &numRows));
6673   PetscCall(ISGetIndices(is, &rows));
6674   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6675   PetscCall(ISRestoreIndices(is, &rows));
6676   PetscFunctionReturn(PETSC_SUCCESS);
6677 }
6678 
6679 /*@
6680   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6681   of a set of rows and columns of a matrix; using local numbering of rows.
6682 
6683   Collective
6684 
6685   Input Parameters:
6686 + mat     - the matrix
6687 . numRows - the number of rows to remove
6688 . rows    - the global row indices
6689 . diag    - value put in all diagonals of eliminated rows
6690 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6691 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6692 
6693   Level: intermediate
6694 
6695   Notes:
6696   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6697   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6698 
6699   See `MatZeroRowsColumns()` for details on how this routine operates.
6700 
6701 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6702           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6703 @*/
6704 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6705 {
6706   IS              is, newis;
6707   const PetscInt *newRows;
6708 
6709   PetscFunctionBegin;
6710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6711   PetscValidType(mat, 1);
6712   if (numRows) PetscAssertPointer(rows, 3);
6713   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6714   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6715   MatCheckPreallocated(mat, 1);
6716 
6717   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6718   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6719   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6720   PetscCall(ISGetIndices(newis, &newRows));
6721   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6722   PetscCall(ISRestoreIndices(newis, &newRows));
6723   PetscCall(ISDestroy(&newis));
6724   PetscCall(ISDestroy(&is));
6725   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6726   PetscFunctionReturn(PETSC_SUCCESS);
6727 }
6728 
6729 /*@
6730   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6731   of a set of rows and columns of a matrix; using local numbering of rows.
6732 
6733   Collective
6734 
6735   Input Parameters:
6736 + mat  - the matrix
6737 . is   - index set of rows to remove
6738 . diag - value put in all diagonals of eliminated rows
6739 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6740 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6741 
6742   Level: intermediate
6743 
6744   Notes:
6745   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6746   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6747 
6748   See `MatZeroRowsColumns()` for details on how this routine operates.
6749 
6750 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6751           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6752 @*/
6753 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6754 {
6755   PetscInt        numRows;
6756   const PetscInt *rows;
6757 
6758   PetscFunctionBegin;
6759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6760   PetscValidType(mat, 1);
6761   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6762   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6763   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6764   MatCheckPreallocated(mat, 1);
6765 
6766   PetscCall(ISGetLocalSize(is, &numRows));
6767   PetscCall(ISGetIndices(is, &rows));
6768   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6769   PetscCall(ISRestoreIndices(is, &rows));
6770   PetscFunctionReturn(PETSC_SUCCESS);
6771 }
6772 
6773 /*@
6774   MatGetSize - Returns the numbers of rows and columns in a matrix.
6775 
6776   Not Collective
6777 
6778   Input Parameter:
6779 . mat - the matrix
6780 
6781   Output Parameters:
6782 + m - the number of global rows
6783 - n - the number of global columns
6784 
6785   Level: beginner
6786 
6787   Note:
6788   Both output parameters can be `NULL` on input.
6789 
6790 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6791 @*/
6792 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6793 {
6794   PetscFunctionBegin;
6795   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6796   if (m) *m = mat->rmap->N;
6797   if (n) *n = mat->cmap->N;
6798   PetscFunctionReturn(PETSC_SUCCESS);
6799 }
6800 
6801 /*@
6802   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6803   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6804 
6805   Not Collective
6806 
6807   Input Parameter:
6808 . mat - the matrix
6809 
6810   Output Parameters:
6811 + m - the number of local rows, use `NULL` to not obtain this value
6812 - n - the number of local columns, use `NULL` to not obtain this value
6813 
6814   Level: beginner
6815 
6816 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6817 @*/
6818 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6819 {
6820   PetscFunctionBegin;
6821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6822   if (m) PetscAssertPointer(m, 2);
6823   if (n) PetscAssertPointer(n, 3);
6824   if (m) *m = mat->rmap->n;
6825   if (n) *n = mat->cmap->n;
6826   PetscFunctionReturn(PETSC_SUCCESS);
6827 }
6828 
6829 /*@
6830   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6831   vector one multiplies this matrix by that are owned by this processor.
6832 
6833   Not Collective, unless matrix has not been allocated, then collective
6834 
6835   Input Parameter:
6836 . mat - the matrix
6837 
6838   Output Parameters:
6839 + m - the global index of the first local column, use `NULL` to not obtain this value
6840 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6841 
6842   Level: developer
6843 
6844   Notes:
6845   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6846 
6847   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6848   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6849 
6850   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6851   the local values in the matrix.
6852 
6853   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6854   Layouts](sec_matlayout) for details on matrix layouts.
6855 
6856 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6857           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6858 @*/
6859 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6860 {
6861   PetscFunctionBegin;
6862   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6863   PetscValidType(mat, 1);
6864   if (m) PetscAssertPointer(m, 2);
6865   if (n) PetscAssertPointer(n, 3);
6866   MatCheckPreallocated(mat, 1);
6867   if (m) *m = mat->cmap->rstart;
6868   if (n) *n = mat->cmap->rend;
6869   PetscFunctionReturn(PETSC_SUCCESS);
6870 }
6871 
6872 /*@
6873   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6874   this MPI process.
6875 
6876   Not Collective
6877 
6878   Input Parameter:
6879 . mat - the matrix
6880 
6881   Output Parameters:
6882 + m - the global index of the first local row, use `NULL` to not obtain this value
6883 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6884 
6885   Level: beginner
6886 
6887   Notes:
6888   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6889 
6890   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6891   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6892 
6893   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6894   the local values in the matrix.
6895 
6896   The high argument is one more than the last element stored locally.
6897 
6898   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6899   would contain the result of a matrix vector product with this matrix. See [Matrix
6900   Layouts](sec_matlayout) for details on matrix layouts.
6901 
6902 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6903           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6904 @*/
6905 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6906 {
6907   PetscFunctionBegin;
6908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6909   PetscValidType(mat, 1);
6910   if (m) PetscAssertPointer(m, 2);
6911   if (n) PetscAssertPointer(n, 3);
6912   MatCheckPreallocated(mat, 1);
6913   if (m) *m = mat->rmap->rstart;
6914   if (n) *n = mat->rmap->rend;
6915   PetscFunctionReturn(PETSC_SUCCESS);
6916 }
6917 
6918 /*@C
6919   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6920   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6921 
6922   Not Collective, unless matrix has not been allocated
6923 
6924   Input Parameter:
6925 . mat - the matrix
6926 
6927   Output Parameter:
6928 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6929            where `size` is the number of MPI processes used by `mat`
6930 
6931   Level: beginner
6932 
6933   Notes:
6934   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6935 
6936   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6937   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6938 
6939   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6940   the local values in the matrix.
6941 
6942   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6943   would contain the result of a matrix vector product with this matrix. See [Matrix
6944   Layouts](sec_matlayout) for details on matrix layouts.
6945 
6946 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6947           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6948           `DMDAGetGhostCorners()`, `DM`
6949 @*/
6950 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6951 {
6952   PetscFunctionBegin;
6953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6954   PetscValidType(mat, 1);
6955   MatCheckPreallocated(mat, 1);
6956   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6957   PetscFunctionReturn(PETSC_SUCCESS);
6958 }
6959 
6960 /*@C
6961   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6962   vector one multiplies this vector by that are owned by each processor.
6963 
6964   Not Collective, unless matrix has not been allocated
6965 
6966   Input Parameter:
6967 . mat - the matrix
6968 
6969   Output Parameter:
6970 . ranges - start of each processors portion plus one more than the total length at the end
6971 
6972   Level: beginner
6973 
6974   Notes:
6975   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6976 
6977   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6978   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6979 
6980   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6981   the local values in the matrix.
6982 
6983   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6984   Layouts](sec_matlayout) for details on matrix layouts.
6985 
6986 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6987           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6988           `DMDAGetGhostCorners()`, `DM`
6989 @*/
6990 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6991 {
6992   PetscFunctionBegin;
6993   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6994   PetscValidType(mat, 1);
6995   MatCheckPreallocated(mat, 1);
6996   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6997   PetscFunctionReturn(PETSC_SUCCESS);
6998 }
6999 
7000 /*@
7001   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7002 
7003   Not Collective
7004 
7005   Input Parameter:
7006 . A - matrix
7007 
7008   Output Parameters:
7009 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7010 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7011 
7012   Level: intermediate
7013 
7014   Note:
7015   You should call `ISDestroy()` on the returned `IS`
7016 
7017   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7018   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7019   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7020   details on matrix layouts.
7021 
7022 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7023 @*/
7024 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7025 {
7026   PetscErrorCode (*f)(Mat, IS *, IS *);
7027 
7028   PetscFunctionBegin;
7029   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7030   PetscValidType(A, 1);
7031   MatCheckPreallocated(A, 1);
7032   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7033   if (f) {
7034     PetscCall((*f)(A, rows, cols));
7035   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7036     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7037     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7038   }
7039   PetscFunctionReturn(PETSC_SUCCESS);
7040 }
7041 
7042 /*@
7043   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7044   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7045   to complete the factorization.
7046 
7047   Collective
7048 
7049   Input Parameters:
7050 + fact - the factorized matrix obtained with `MatGetFactor()`
7051 . mat  - the matrix
7052 . row  - row permutation
7053 . col  - column permutation
7054 - info - structure containing
7055 .vb
7056       levels - number of levels of fill.
7057       expected fill - as ratio of original fill.
7058       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7059                 missing diagonal entries)
7060 .ve
7061 
7062   Level: developer
7063 
7064   Notes:
7065   See [Matrix Factorization](sec_matfactor) for additional information.
7066 
7067   Most users should employ the `KSP` interface for linear solvers
7068   instead of working directly with matrix algebra routines such as this.
7069   See, e.g., `KSPCreate()`.
7070 
7071   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7072 
7073   Developer Note:
7074   The Fortran interface is not autogenerated as the
7075   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7076 
7077 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7078           `MatGetOrdering()`, `MatFactorInfo`
7079 @*/
7080 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7081 {
7082   PetscFunctionBegin;
7083   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7084   PetscValidType(mat, 2);
7085   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7086   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7087   PetscAssertPointer(info, 5);
7088   PetscAssertPointer(fact, 1);
7089   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7090   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7091   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7092   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7093   MatCheckPreallocated(mat, 2);
7094 
7095   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7096   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7097   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7098   PetscFunctionReturn(PETSC_SUCCESS);
7099 }
7100 
7101 /*@
7102   MatICCFactorSymbolic - Performs symbolic incomplete
7103   Cholesky factorization for a symmetric matrix.  Use
7104   `MatCholeskyFactorNumeric()` to complete the factorization.
7105 
7106   Collective
7107 
7108   Input Parameters:
7109 + fact - the factorized matrix obtained with `MatGetFactor()`
7110 . mat  - the matrix to be factored
7111 . perm - row and column permutation
7112 - info - structure containing
7113 .vb
7114       levels - number of levels of fill.
7115       expected fill - as ratio of original fill.
7116 .ve
7117 
7118   Level: developer
7119 
7120   Notes:
7121   Most users should employ the `KSP` interface for linear solvers
7122   instead of working directly with matrix algebra routines such as this.
7123   See, e.g., `KSPCreate()`.
7124 
7125   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7126 
7127   Developer Note:
7128   The Fortran interface is not autogenerated as the
7129   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7130 
7131 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7132 @*/
7133 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7134 {
7135   PetscFunctionBegin;
7136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7137   PetscValidType(mat, 2);
7138   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7139   PetscAssertPointer(info, 4);
7140   PetscAssertPointer(fact, 1);
7141   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7142   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7143   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7144   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7145   MatCheckPreallocated(mat, 2);
7146 
7147   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7148   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7149   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7150   PetscFunctionReturn(PETSC_SUCCESS);
7151 }
7152 
7153 /*@C
7154   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7155   points to an array of valid matrices, they may be reused to store the new
7156   submatrices.
7157 
7158   Collective
7159 
7160   Input Parameters:
7161 + mat   - the matrix
7162 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7163 . irow  - index set of rows to extract
7164 . icol  - index set of columns to extract
7165 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7166 
7167   Output Parameter:
7168 . submat - the array of submatrices
7169 
7170   Level: advanced
7171 
7172   Notes:
7173   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7174   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7175   to extract a parallel submatrix.
7176 
7177   Some matrix types place restrictions on the row and column
7178   indices, such as that they be sorted or that they be equal to each other.
7179 
7180   The index sets may not have duplicate entries.
7181 
7182   When extracting submatrices from a parallel matrix, each processor can
7183   form a different submatrix by setting the rows and columns of its
7184   individual index sets according to the local submatrix desired.
7185 
7186   When finished using the submatrices, the user should destroy
7187   them with `MatDestroySubMatrices()`.
7188 
7189   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7190   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7191 
7192   This routine creates the matrices in submat; you should NOT create them before
7193   calling it. It also allocates the array of matrix pointers submat.
7194 
7195   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7196   request one row/column in a block, they must request all rows/columns that are in
7197   that block. For example, if the block size is 2 you cannot request just row 0 and
7198   column 0.
7199 
7200   Fortran Note:
7201   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7202 
7203 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7204 @*/
7205 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7206 {
7207   PetscInt  i;
7208   PetscBool eq;
7209 
7210   PetscFunctionBegin;
7211   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7212   PetscValidType(mat, 1);
7213   if (n) {
7214     PetscAssertPointer(irow, 3);
7215     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7216     PetscAssertPointer(icol, 4);
7217     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7218   }
7219   PetscAssertPointer(submat, 6);
7220   if (n && scall == MAT_REUSE_MATRIX) {
7221     PetscAssertPointer(*submat, 6);
7222     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7223   }
7224   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7225   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7226   MatCheckPreallocated(mat, 1);
7227   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7228   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7229   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7230   for (i = 0; i < n; i++) {
7231     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7232     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7233     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7234 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7235     if (mat->boundtocpu && mat->bindingpropagates) {
7236       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7237       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7238     }
7239 #endif
7240   }
7241   PetscFunctionReturn(PETSC_SUCCESS);
7242 }
7243 
7244 /*@C
7245   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7246 
7247   Collective
7248 
7249   Input Parameters:
7250 + mat   - the matrix
7251 . n     - the number of submatrixes to be extracted
7252 . irow  - index set of rows to extract
7253 . icol  - index set of columns to extract
7254 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7255 
7256   Output Parameter:
7257 . submat - the array of submatrices
7258 
7259   Level: advanced
7260 
7261   Note:
7262   This is used by `PCGASM`
7263 
7264 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7265 @*/
7266 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7267 {
7268   PetscInt  i;
7269   PetscBool eq;
7270 
7271   PetscFunctionBegin;
7272   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7273   PetscValidType(mat, 1);
7274   if (n) {
7275     PetscAssertPointer(irow, 3);
7276     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7277     PetscAssertPointer(icol, 4);
7278     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7279   }
7280   PetscAssertPointer(submat, 6);
7281   if (n && scall == MAT_REUSE_MATRIX) {
7282     PetscAssertPointer(*submat, 6);
7283     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7284   }
7285   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7286   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7287   MatCheckPreallocated(mat, 1);
7288 
7289   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7290   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7291   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7292   for (i = 0; i < n; i++) {
7293     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7294     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7295   }
7296   PetscFunctionReturn(PETSC_SUCCESS);
7297 }
7298 
7299 /*@C
7300   MatDestroyMatrices - Destroys an array of matrices.
7301 
7302   Collective
7303 
7304   Input Parameters:
7305 + n   - the number of local matrices
7306 - mat - the matrices (this is a pointer to the array of matrices)
7307 
7308   Level: advanced
7309 
7310   Notes:
7311   Frees not only the matrices, but also the array that contains the matrices
7312 
7313   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7314 
7315   Fortran Note:
7316   Does not free the `mat` array.
7317 
7318 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7319 @*/
7320 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7321 {
7322   PetscInt i;
7323 
7324   PetscFunctionBegin;
7325   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7326   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7327   PetscAssertPointer(mat, 2);
7328 
7329   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7330 
7331   /* memory is allocated even if n = 0 */
7332   PetscCall(PetscFree(*mat));
7333   PetscFunctionReturn(PETSC_SUCCESS);
7334 }
7335 
7336 /*@C
7337   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7338 
7339   Collective
7340 
7341   Input Parameters:
7342 + n   - the number of local matrices
7343 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7344                        sequence of `MatCreateSubMatrices()`)
7345 
7346   Level: advanced
7347 
7348   Note:
7349   Frees not only the matrices, but also the array that contains the matrices
7350 
7351   Fortran Note:
7352   Does not free the `mat` array.
7353 
7354 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7355 @*/
7356 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7357 {
7358   Mat mat0;
7359 
7360   PetscFunctionBegin;
7361   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7362   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7363   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7364   PetscAssertPointer(mat, 2);
7365 
7366   mat0 = (*mat)[0];
7367   if (mat0 && mat0->ops->destroysubmatrices) {
7368     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7369   } else {
7370     PetscCall(MatDestroyMatrices(n, mat));
7371   }
7372   PetscFunctionReturn(PETSC_SUCCESS);
7373 }
7374 
7375 /*@
7376   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7377 
7378   Collective
7379 
7380   Input Parameter:
7381 . mat - the matrix
7382 
7383   Output Parameter:
7384 . matstruct - the sequential matrix with the nonzero structure of `mat`
7385 
7386   Level: developer
7387 
7388 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7389 @*/
7390 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7391 {
7392   PetscFunctionBegin;
7393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7394   PetscAssertPointer(matstruct, 2);
7395 
7396   PetscValidType(mat, 1);
7397   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7398   MatCheckPreallocated(mat, 1);
7399 
7400   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7401   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7402   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7403   PetscFunctionReturn(PETSC_SUCCESS);
7404 }
7405 
7406 /*@C
7407   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7408 
7409   Collective
7410 
7411   Input Parameter:
7412 . mat - the matrix
7413 
7414   Level: advanced
7415 
7416   Note:
7417   This is not needed, one can just call `MatDestroy()`
7418 
7419 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7420 @*/
7421 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7422 {
7423   PetscFunctionBegin;
7424   PetscAssertPointer(mat, 1);
7425   PetscCall(MatDestroy(mat));
7426   PetscFunctionReturn(PETSC_SUCCESS);
7427 }
7428 
7429 /*@
7430   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7431   replaces the index sets by larger ones that represent submatrices with
7432   additional overlap.
7433 
7434   Collective
7435 
7436   Input Parameters:
7437 + mat - the matrix
7438 . n   - the number of index sets
7439 . is  - the array of index sets (these index sets will changed during the call)
7440 - ov  - the additional overlap requested
7441 
7442   Options Database Key:
7443 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7444 
7445   Level: developer
7446 
7447   Note:
7448   The computed overlap preserves the matrix block sizes when the blocks are square.
7449   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7450   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7451 
7452 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7453 @*/
7454 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7455 {
7456   PetscInt i, bs, cbs;
7457 
7458   PetscFunctionBegin;
7459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7460   PetscValidType(mat, 1);
7461   PetscValidLogicalCollectiveInt(mat, n, 2);
7462   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7463   if (n) {
7464     PetscAssertPointer(is, 3);
7465     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7466   }
7467   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7468   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7469   MatCheckPreallocated(mat, 1);
7470 
7471   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7472   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7473   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7474   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7475   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7476   if (bs == cbs) {
7477     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7478   }
7479   PetscFunctionReturn(PETSC_SUCCESS);
7480 }
7481 
7482 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7483 
7484 /*@
7485   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7486   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7487   additional overlap.
7488 
7489   Collective
7490 
7491   Input Parameters:
7492 + mat - the matrix
7493 . n   - the number of index sets
7494 . is  - the array of index sets (these index sets will changed during the call)
7495 - ov  - the additional overlap requested
7496 
7497   `   Options Database Key:
7498 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7499 
7500   Level: developer
7501 
7502 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7503 @*/
7504 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7505 {
7506   PetscInt i;
7507 
7508   PetscFunctionBegin;
7509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7510   PetscValidType(mat, 1);
7511   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7512   if (n) {
7513     PetscAssertPointer(is, 3);
7514     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7515   }
7516   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7517   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7518   MatCheckPreallocated(mat, 1);
7519   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7520   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7521   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7522   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7523   PetscFunctionReturn(PETSC_SUCCESS);
7524 }
7525 
7526 /*@
7527   MatGetBlockSize - Returns the matrix block size.
7528 
7529   Not Collective
7530 
7531   Input Parameter:
7532 . mat - the matrix
7533 
7534   Output Parameter:
7535 . bs - block size
7536 
7537   Level: intermediate
7538 
7539   Notes:
7540   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7541 
7542   If the block size has not been set yet this routine returns 1.
7543 
7544 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7545 @*/
7546 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7547 {
7548   PetscFunctionBegin;
7549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7550   PetscAssertPointer(bs, 2);
7551   *bs = PetscAbs(mat->rmap->bs);
7552   PetscFunctionReturn(PETSC_SUCCESS);
7553 }
7554 
7555 /*@
7556   MatGetBlockSizes - Returns the matrix block row and column sizes.
7557 
7558   Not Collective
7559 
7560   Input Parameter:
7561 . mat - the matrix
7562 
7563   Output Parameters:
7564 + rbs - row block size
7565 - cbs - column block size
7566 
7567   Level: intermediate
7568 
7569   Notes:
7570   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7571   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7572 
7573   If a block size has not been set yet this routine returns 1.
7574 
7575 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7576 @*/
7577 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7578 {
7579   PetscFunctionBegin;
7580   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7581   if (rbs) PetscAssertPointer(rbs, 2);
7582   if (cbs) PetscAssertPointer(cbs, 3);
7583   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7584   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7585   PetscFunctionReturn(PETSC_SUCCESS);
7586 }
7587 
7588 /*@
7589   MatSetBlockSize - Sets the matrix block size.
7590 
7591   Logically Collective
7592 
7593   Input Parameters:
7594 + mat - the matrix
7595 - bs  - block size
7596 
7597   Level: intermediate
7598 
7599   Notes:
7600   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7601   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7602 
7603   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7604   is compatible with the matrix local sizes.
7605 
7606 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7607 @*/
7608 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7609 {
7610   PetscFunctionBegin;
7611   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7612   PetscValidLogicalCollectiveInt(mat, bs, 2);
7613   PetscCall(MatSetBlockSizes(mat, bs, bs));
7614   PetscFunctionReturn(PETSC_SUCCESS);
7615 }
7616 
7617 typedef struct {
7618   PetscInt         n;
7619   IS              *is;
7620   Mat             *mat;
7621   PetscObjectState nonzerostate;
7622   Mat              C;
7623 } EnvelopeData;
7624 
7625 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7626 {
7627   EnvelopeData *edata = (EnvelopeData *)ptr;
7628 
7629   PetscFunctionBegin;
7630   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7631   PetscCall(PetscFree(edata->is));
7632   PetscCall(PetscFree(edata));
7633   PetscFunctionReturn(PETSC_SUCCESS);
7634 }
7635 
7636 /*@
7637   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7638   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7639 
7640   Collective
7641 
7642   Input Parameter:
7643 . mat - the matrix
7644 
7645   Level: intermediate
7646 
7647   Notes:
7648   There can be zeros within the blocks
7649 
7650   The blocks can overlap between processes, including laying on more than two processes
7651 
7652 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7653 @*/
7654 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7655 {
7656   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7657   PetscInt          *diag, *odiag, sc;
7658   VecScatter         scatter;
7659   PetscScalar       *seqv;
7660   const PetscScalar *parv;
7661   const PetscInt    *ia, *ja;
7662   PetscBool          set, flag, done;
7663   Mat                AA = mat, A;
7664   MPI_Comm           comm;
7665   PetscMPIInt        rank, size, tag;
7666   MPI_Status         status;
7667   PetscContainer     container;
7668   EnvelopeData      *edata;
7669   Vec                seq, par;
7670   IS                 isglobal;
7671 
7672   PetscFunctionBegin;
7673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7674   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7675   if (!set || !flag) {
7676     /* TODO: only needs nonzero structure of transpose */
7677     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7678     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7679   }
7680   PetscCall(MatAIJGetLocalMat(AA, &A));
7681   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7682   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7683 
7684   PetscCall(MatGetLocalSize(mat, &n, NULL));
7685   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7686   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7687   PetscCallMPI(MPI_Comm_size(comm, &size));
7688   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7689 
7690   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7691 
7692   if (rank > 0) {
7693     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7694     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7695   }
7696   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7697   for (i = 0; i < n; i++) {
7698     env = PetscMax(env, ja[ia[i + 1] - 1]);
7699     II  = rstart + i;
7700     if (env == II) {
7701       starts[lblocks]  = tbs;
7702       sizes[lblocks++] = 1 + II - tbs;
7703       tbs              = 1 + II;
7704     }
7705   }
7706   if (rank < size - 1) {
7707     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7708     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7709   }
7710 
7711   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7712   if (!set || !flag) PetscCall(MatDestroy(&AA));
7713   PetscCall(MatDestroy(&A));
7714 
7715   PetscCall(PetscNew(&edata));
7716   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7717   edata->n = lblocks;
7718   /* create IS needed for extracting blocks from the original matrix */
7719   PetscCall(PetscMalloc1(lblocks, &edata->is));
7720   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7721 
7722   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7723   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7724   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7725   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7726   PetscCall(MatSetType(edata->C, MATAIJ));
7727 
7728   /* Communicate the start and end of each row, from each block to the correct rank */
7729   /* TODO: Use PetscSF instead of VecScatter */
7730   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7731   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7732   PetscCall(VecGetArrayWrite(seq, &seqv));
7733   for (PetscInt i = 0; i < lblocks; i++) {
7734     for (PetscInt j = 0; j < sizes[i]; j++) {
7735       seqv[cnt]     = starts[i];
7736       seqv[cnt + 1] = starts[i] + sizes[i];
7737       cnt += 2;
7738     }
7739   }
7740   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7741   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7742   sc -= cnt;
7743   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7744   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7745   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7746   PetscCall(ISDestroy(&isglobal));
7747   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7748   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7749   PetscCall(VecScatterDestroy(&scatter));
7750   PetscCall(VecDestroy(&seq));
7751   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7752   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7753   PetscCall(VecGetArrayRead(par, &parv));
7754   cnt = 0;
7755   PetscCall(MatGetSize(mat, NULL, &n));
7756   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7757     PetscInt start, end, d = 0, od = 0;
7758 
7759     start = (PetscInt)PetscRealPart(parv[cnt]);
7760     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7761     cnt += 2;
7762 
7763     if (start < cstart) {
7764       od += cstart - start + n - cend;
7765       d += cend - cstart;
7766     } else if (start < cend) {
7767       od += n - cend;
7768       d += cend - start;
7769     } else od += n - start;
7770     if (end <= cstart) {
7771       od -= cstart - end + n - cend;
7772       d -= cend - cstart;
7773     } else if (end < cend) {
7774       od -= n - cend;
7775       d -= cend - end;
7776     } else od -= n - end;
7777 
7778     odiag[i] = od;
7779     diag[i]  = d;
7780   }
7781   PetscCall(VecRestoreArrayRead(par, &parv));
7782   PetscCall(VecDestroy(&par));
7783   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7784   PetscCall(PetscFree2(diag, odiag));
7785   PetscCall(PetscFree2(sizes, starts));
7786 
7787   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7788   PetscCall(PetscContainerSetPointer(container, edata));
7789   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode (*)(void *))EnvelopeDataDestroy));
7790   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7791   PetscCall(PetscObjectDereference((PetscObject)container));
7792   PetscFunctionReturn(PETSC_SUCCESS);
7793 }
7794 
7795 /*@
7796   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7797 
7798   Collective
7799 
7800   Input Parameters:
7801 + A     - the matrix
7802 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7803 
7804   Output Parameter:
7805 . C - matrix with inverted block diagonal of `A`
7806 
7807   Level: advanced
7808 
7809   Note:
7810   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7811 
7812 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7813 @*/
7814 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7815 {
7816   PetscContainer   container;
7817   EnvelopeData    *edata;
7818   PetscObjectState nonzerostate;
7819 
7820   PetscFunctionBegin;
7821   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7822   if (!container) {
7823     PetscCall(MatComputeVariableBlockEnvelope(A));
7824     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7825   }
7826   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7827   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7828   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7829   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7830 
7831   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7832   *C = edata->C;
7833 
7834   for (PetscInt i = 0; i < edata->n; i++) {
7835     Mat          D;
7836     PetscScalar *dvalues;
7837 
7838     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7839     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7840     PetscCall(MatSeqDenseInvert(D));
7841     PetscCall(MatDenseGetArray(D, &dvalues));
7842     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7843     PetscCall(MatDestroy(&D));
7844   }
7845   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7846   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7847   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7848   PetscFunctionReturn(PETSC_SUCCESS);
7849 }
7850 
7851 /*@
7852   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7853 
7854   Not Collective
7855 
7856   Input Parameters:
7857 + mat     - the matrix
7858 . nblocks - the number of blocks on this process, each block can only exist on a single process
7859 - bsizes  - the block sizes
7860 
7861   Level: intermediate
7862 
7863   Notes:
7864   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7865 
7866   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.
7867 
7868 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7869           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7870 @*/
7871 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7872 {
7873   PetscInt ncnt = 0, nlocal;
7874 
7875   PetscFunctionBegin;
7876   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7877   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7878   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);
7879   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7880   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);
7881   PetscCall(PetscFree(mat->bsizes));
7882   mat->nblocks = nblocks;
7883   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7884   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7885   PetscFunctionReturn(PETSC_SUCCESS);
7886 }
7887 
7888 /*@C
7889   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7890 
7891   Not Collective; No Fortran Support
7892 
7893   Input Parameter:
7894 . mat - the matrix
7895 
7896   Output Parameters:
7897 + nblocks - the number of blocks on this process
7898 - bsizes  - the block sizes
7899 
7900   Level: intermediate
7901 
7902 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7903 @*/
7904 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7905 {
7906   PetscFunctionBegin;
7907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7908   if (nblocks) *nblocks = mat->nblocks;
7909   if (bsizes) *bsizes = mat->bsizes;
7910   PetscFunctionReturn(PETSC_SUCCESS);
7911 }
7912 
7913 /*@
7914   MatSetBlockSizes - Sets the matrix block row and column sizes.
7915 
7916   Logically Collective
7917 
7918   Input Parameters:
7919 + mat - the matrix
7920 . rbs - row block size
7921 - cbs - column block size
7922 
7923   Level: intermediate
7924 
7925   Notes:
7926   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7927   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7928   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7929 
7930   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7931   are compatible with the matrix local sizes.
7932 
7933   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7934 
7935 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7936 @*/
7937 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7938 {
7939   PetscFunctionBegin;
7940   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7941   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7942   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7943   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7944   if (mat->rmap->refcnt) {
7945     ISLocalToGlobalMapping l2g  = NULL;
7946     PetscLayout            nmap = NULL;
7947 
7948     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7949     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7950     PetscCall(PetscLayoutDestroy(&mat->rmap));
7951     mat->rmap          = nmap;
7952     mat->rmap->mapping = l2g;
7953   }
7954   if (mat->cmap->refcnt) {
7955     ISLocalToGlobalMapping l2g  = NULL;
7956     PetscLayout            nmap = NULL;
7957 
7958     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7959     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7960     PetscCall(PetscLayoutDestroy(&mat->cmap));
7961     mat->cmap          = nmap;
7962     mat->cmap->mapping = l2g;
7963   }
7964   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7965   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7966   PetscFunctionReturn(PETSC_SUCCESS);
7967 }
7968 
7969 /*@
7970   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7971 
7972   Logically Collective
7973 
7974   Input Parameters:
7975 + mat     - the matrix
7976 . fromRow - matrix from which to copy row block size
7977 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7978 
7979   Level: developer
7980 
7981 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7982 @*/
7983 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7984 {
7985   PetscFunctionBegin;
7986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7987   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7988   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7989   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7990   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7991   PetscFunctionReturn(PETSC_SUCCESS);
7992 }
7993 
7994 /*@
7995   MatResidual - Default routine to calculate the residual r = b - Ax
7996 
7997   Collective
7998 
7999   Input Parameters:
8000 + mat - the matrix
8001 . b   - the right-hand-side
8002 - x   - the approximate solution
8003 
8004   Output Parameter:
8005 . r - location to store the residual
8006 
8007   Level: developer
8008 
8009 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8010 @*/
8011 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8012 {
8013   PetscFunctionBegin;
8014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8015   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8016   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8017   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8018   PetscValidType(mat, 1);
8019   MatCheckPreallocated(mat, 1);
8020   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8021   if (!mat->ops->residual) {
8022     PetscCall(MatMult(mat, x, r));
8023     PetscCall(VecAYPX(r, -1.0, b));
8024   } else {
8025     PetscUseTypeMethod(mat, residual, b, x, r);
8026   }
8027   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8028   PetscFunctionReturn(PETSC_SUCCESS);
8029 }
8030 
8031 /*MC
8032     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8033 
8034     Synopsis:
8035     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8036 
8037     Not Collective
8038 
8039     Input Parameters:
8040 +   A - the matrix
8041 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8042 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8043 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8044                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8045                  always used.
8046 
8047     Output Parameters:
8048 +   n - number of local rows in the (possibly compressed) matrix
8049 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8050 .   ja - the column indices
8051 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8052            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8053 
8054     Level: developer
8055 
8056     Note:
8057     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8058 
8059 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8060 M*/
8061 
8062 /*MC
8063     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8064 
8065     Synopsis:
8066     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8067 
8068     Not Collective
8069 
8070     Input Parameters:
8071 +   A - the  matrix
8072 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8073 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8074     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8075                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8076                  always used.
8077 .   n - number of local rows in the (possibly compressed) matrix
8078 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8079 .   ja - the column indices
8080 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8081            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8082 
8083     Level: developer
8084 
8085 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8086 M*/
8087 
8088 /*@C
8089   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8090 
8091   Collective
8092 
8093   Input Parameters:
8094 + mat             - the matrix
8095 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8096 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8097 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8098                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8099                  always used.
8100 
8101   Output Parameters:
8102 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8103 . 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
8104 . ja   - the column indices, use `NULL` if not needed
8105 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8106            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8107 
8108   Level: developer
8109 
8110   Notes:
8111   You CANNOT change any of the ia[] or ja[] values.
8112 
8113   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8114 
8115   Fortran Notes:
8116   Use
8117 .vb
8118     PetscInt, pointer :: ia(:),ja(:)
8119     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8120     ! Access the ith and jth entries via ia(i) and ja(j)
8121 .ve
8122 
8123   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8124 
8125 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8126 @*/
8127 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8128 {
8129   PetscFunctionBegin;
8130   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8131   PetscValidType(mat, 1);
8132   if (n) PetscAssertPointer(n, 5);
8133   if (ia) PetscAssertPointer(ia, 6);
8134   if (ja) PetscAssertPointer(ja, 7);
8135   if (done) PetscAssertPointer(done, 8);
8136   MatCheckPreallocated(mat, 1);
8137   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8138   else {
8139     if (done) *done = PETSC_TRUE;
8140     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8141     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8142     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8143   }
8144   PetscFunctionReturn(PETSC_SUCCESS);
8145 }
8146 
8147 /*@C
8148   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8149 
8150   Collective
8151 
8152   Input Parameters:
8153 + mat             - the matrix
8154 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8155 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8156                 symmetrized
8157 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8158                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8159                  always used.
8160 . n               - number of columns in the (possibly compressed) matrix
8161 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8162 - ja              - the row indices
8163 
8164   Output Parameter:
8165 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8166 
8167   Level: developer
8168 
8169 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8170 @*/
8171 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8172 {
8173   PetscFunctionBegin;
8174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8175   PetscValidType(mat, 1);
8176   PetscAssertPointer(n, 5);
8177   if (ia) PetscAssertPointer(ia, 6);
8178   if (ja) PetscAssertPointer(ja, 7);
8179   PetscAssertPointer(done, 8);
8180   MatCheckPreallocated(mat, 1);
8181   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8182   else {
8183     *done = PETSC_TRUE;
8184     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8185   }
8186   PetscFunctionReturn(PETSC_SUCCESS);
8187 }
8188 
8189 /*@C
8190   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8191 
8192   Collective
8193 
8194   Input Parameters:
8195 + mat             - the matrix
8196 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8197 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8198 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8199                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8200                     always used.
8201 . n               - size of (possibly compressed) matrix
8202 . ia              - the row pointers
8203 - ja              - the column indices
8204 
8205   Output Parameter:
8206 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8207 
8208   Level: developer
8209 
8210   Note:
8211   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8212   us of the array after it has been restored. If you pass `NULL`, it will
8213   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8214 
8215   Fortran Note:
8216   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8217 
8218 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8219 @*/
8220 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8221 {
8222   PetscFunctionBegin;
8223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8224   PetscValidType(mat, 1);
8225   if (ia) PetscAssertPointer(ia, 6);
8226   if (ja) PetscAssertPointer(ja, 7);
8227   if (done) PetscAssertPointer(done, 8);
8228   MatCheckPreallocated(mat, 1);
8229 
8230   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8231   else {
8232     if (done) *done = PETSC_TRUE;
8233     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8234     if (n) *n = 0;
8235     if (ia) *ia = NULL;
8236     if (ja) *ja = NULL;
8237   }
8238   PetscFunctionReturn(PETSC_SUCCESS);
8239 }
8240 
8241 /*@C
8242   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8243 
8244   Collective
8245 
8246   Input Parameters:
8247 + mat             - the matrix
8248 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8249 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8250 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8251                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8252                     always used.
8253 
8254   Output Parameters:
8255 + n    - size of (possibly compressed) matrix
8256 . ia   - the column pointers
8257 . ja   - the row indices
8258 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8259 
8260   Level: developer
8261 
8262 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8263 @*/
8264 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8265 {
8266   PetscFunctionBegin;
8267   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8268   PetscValidType(mat, 1);
8269   if (ia) PetscAssertPointer(ia, 6);
8270   if (ja) PetscAssertPointer(ja, 7);
8271   PetscAssertPointer(done, 8);
8272   MatCheckPreallocated(mat, 1);
8273 
8274   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8275   else {
8276     *done = PETSC_TRUE;
8277     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8278     if (n) *n = 0;
8279     if (ia) *ia = NULL;
8280     if (ja) *ja = NULL;
8281   }
8282   PetscFunctionReturn(PETSC_SUCCESS);
8283 }
8284 
8285 /*@
8286   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8287   `MatGetColumnIJ()`.
8288 
8289   Collective
8290 
8291   Input Parameters:
8292 + mat        - the matrix
8293 . ncolors    - maximum color value
8294 . n          - number of entries in colorarray
8295 - colorarray - array indicating color for each column
8296 
8297   Output Parameter:
8298 . iscoloring - coloring generated using colorarray information
8299 
8300   Level: developer
8301 
8302 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8303 @*/
8304 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8305 {
8306   PetscFunctionBegin;
8307   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8308   PetscValidType(mat, 1);
8309   PetscAssertPointer(colorarray, 4);
8310   PetscAssertPointer(iscoloring, 5);
8311   MatCheckPreallocated(mat, 1);
8312 
8313   if (!mat->ops->coloringpatch) {
8314     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8315   } else {
8316     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8317   }
8318   PetscFunctionReturn(PETSC_SUCCESS);
8319 }
8320 
8321 /*@
8322   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8323 
8324   Logically Collective
8325 
8326   Input Parameter:
8327 . mat - the factored matrix to be reset
8328 
8329   Level: developer
8330 
8331   Notes:
8332   This routine should be used only with factored matrices formed by in-place
8333   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8334   format).  This option can save memory, for example, when solving nonlinear
8335   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8336   ILU(0) preconditioner.
8337 
8338   One can specify in-place ILU(0) factorization by calling
8339 .vb
8340      PCType(pc,PCILU);
8341      PCFactorSeUseInPlace(pc);
8342 .ve
8343   or by using the options -pc_type ilu -pc_factor_in_place
8344 
8345   In-place factorization ILU(0) can also be used as a local
8346   solver for the blocks within the block Jacobi or additive Schwarz
8347   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8348   for details on setting local solver options.
8349 
8350   Most users should employ the `KSP` interface for linear solvers
8351   instead of working directly with matrix algebra routines such as this.
8352   See, e.g., `KSPCreate()`.
8353 
8354 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8355 @*/
8356 PetscErrorCode MatSetUnfactored(Mat mat)
8357 {
8358   PetscFunctionBegin;
8359   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8360   PetscValidType(mat, 1);
8361   MatCheckPreallocated(mat, 1);
8362   mat->factortype = MAT_FACTOR_NONE;
8363   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8364   PetscUseTypeMethod(mat, setunfactored);
8365   PetscFunctionReturn(PETSC_SUCCESS);
8366 }
8367 
8368 /*MC
8369     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8370 
8371     Synopsis:
8372     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8373 
8374     Not Collective
8375 
8376     Input Parameter:
8377 .   x - matrix
8378 
8379     Output Parameters:
8380 +   xx_v - the Fortran pointer to the array
8381 -   ierr - error code
8382 
8383     Example of Usage:
8384 .vb
8385       PetscScalar, pointer xx_v(:,:)
8386       ....
8387       call MatDenseGetArrayF90(x,xx_v,ierr)
8388       a = xx_v(3)
8389       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8390 .ve
8391 
8392     Level: advanced
8393 
8394 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8395 M*/
8396 
8397 /*MC
8398     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8399     accessed with `MatDenseGetArrayF90()`.
8400 
8401     Synopsis:
8402     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8403 
8404     Not Collective
8405 
8406     Input Parameters:
8407 +   x - matrix
8408 -   xx_v - the Fortran90 pointer to the array
8409 
8410     Output Parameter:
8411 .   ierr - error code
8412 
8413     Example of Usage:
8414 .vb
8415        PetscScalar, pointer xx_v(:,:)
8416        ....
8417        call MatDenseGetArrayF90(x,xx_v,ierr)
8418        a = xx_v(3)
8419        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8420 .ve
8421 
8422     Level: advanced
8423 
8424 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8425 M*/
8426 
8427 /*MC
8428     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8429 
8430     Synopsis:
8431     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8432 
8433     Not Collective
8434 
8435     Input Parameter:
8436 .   x - matrix
8437 
8438     Output Parameters:
8439 +   xx_v - the Fortran pointer to the array
8440 -   ierr - error code
8441 
8442     Example of Usage:
8443 .vb
8444       PetscScalar, pointer xx_v(:)
8445       ....
8446       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8447       a = xx_v(3)
8448       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8449 .ve
8450 
8451     Level: advanced
8452 
8453 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8454 M*/
8455 
8456 /*MC
8457     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8458     accessed with `MatSeqAIJGetArrayF90()`.
8459 
8460     Synopsis:
8461     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8462 
8463     Not Collective
8464 
8465     Input Parameters:
8466 +   x - matrix
8467 -   xx_v - the Fortran90 pointer to the array
8468 
8469     Output Parameter:
8470 .   ierr - error code
8471 
8472     Example of Usage:
8473 .vb
8474        PetscScalar, pointer xx_v(:)
8475        ....
8476        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8477        a = xx_v(3)
8478        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8479 .ve
8480 
8481     Level: advanced
8482 
8483 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8484 M*/
8485 
8486 /*@
8487   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8488   as the original matrix.
8489 
8490   Collective
8491 
8492   Input Parameters:
8493 + mat   - the original matrix
8494 . isrow - parallel `IS` containing the rows this processor should obtain
8495 . 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.
8496 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8497 
8498   Output Parameter:
8499 . newmat - the new submatrix, of the same type as the original matrix
8500 
8501   Level: advanced
8502 
8503   Notes:
8504   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8505 
8506   Some matrix types place restrictions on the row and column indices, such
8507   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;
8508   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8509 
8510   The index sets may not have duplicate entries.
8511 
8512   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8513   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8514   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8515   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8516   you are finished using it.
8517 
8518   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8519   the input matrix.
8520 
8521   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8522 
8523   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8524   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8525 
8526   Example usage:
8527   Consider the following 8x8 matrix with 34 non-zero values, that is
8528   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8529   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8530   as follows
8531 .vb
8532             1  2  0  |  0  3  0  |  0  4
8533     Proc0   0  5  6  |  7  0  0  |  8  0
8534             9  0 10  | 11  0  0  | 12  0
8535     -------------------------------------
8536            13  0 14  | 15 16 17  |  0  0
8537     Proc1   0 18  0  | 19 20 21  |  0  0
8538             0  0  0  | 22 23  0  | 24  0
8539     -------------------------------------
8540     Proc2  25 26 27  |  0  0 28  | 29  0
8541            30  0  0  | 31 32 33  |  0 34
8542 .ve
8543 
8544   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8545 
8546 .vb
8547             2  0  |  0  3  0  |  0
8548     Proc0   5  6  |  7  0  0  |  8
8549     -------------------------------
8550     Proc1  18  0  | 19 20 21  |  0
8551     -------------------------------
8552     Proc2  26 27  |  0  0 28  | 29
8553             0  0  | 31 32 33  |  0
8554 .ve
8555 
8556 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8557 @*/
8558 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8559 {
8560   PetscMPIInt size;
8561   Mat        *local;
8562   IS          iscoltmp;
8563   PetscBool   flg;
8564 
8565   PetscFunctionBegin;
8566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8567   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8568   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8569   PetscAssertPointer(newmat, 5);
8570   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8571   PetscValidType(mat, 1);
8572   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8573   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8574 
8575   MatCheckPreallocated(mat, 1);
8576   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8577 
8578   if (!iscol || isrow == iscol) {
8579     PetscBool   stride;
8580     PetscMPIInt grabentirematrix = 0, grab;
8581     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8582     if (stride) {
8583       PetscInt first, step, n, rstart, rend;
8584       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8585       if (step == 1) {
8586         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8587         if (rstart == first) {
8588           PetscCall(ISGetLocalSize(isrow, &n));
8589           if (n == rend - rstart) grabentirematrix = 1;
8590         }
8591       }
8592     }
8593     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8594     if (grab) {
8595       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8596       if (cll == MAT_INITIAL_MATRIX) {
8597         *newmat = mat;
8598         PetscCall(PetscObjectReference((PetscObject)mat));
8599       }
8600       PetscFunctionReturn(PETSC_SUCCESS);
8601     }
8602   }
8603 
8604   if (!iscol) {
8605     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8606   } else {
8607     iscoltmp = iscol;
8608   }
8609 
8610   /* if original matrix is on just one processor then use submatrix generated */
8611   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8612     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8613     goto setproperties;
8614   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8615     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8616     *newmat = *local;
8617     PetscCall(PetscFree(local));
8618     goto setproperties;
8619   } else if (!mat->ops->createsubmatrix) {
8620     /* Create a new matrix type that implements the operation using the full matrix */
8621     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8622     switch (cll) {
8623     case MAT_INITIAL_MATRIX:
8624       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8625       break;
8626     case MAT_REUSE_MATRIX:
8627       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8628       break;
8629     default:
8630       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8631     }
8632     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8633     goto setproperties;
8634   }
8635 
8636   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8637   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8638   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8639 
8640 setproperties:
8641   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8642     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8643     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8644   }
8645   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8646   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8647   PetscFunctionReturn(PETSC_SUCCESS);
8648 }
8649 
8650 /*@
8651   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8652 
8653   Not Collective
8654 
8655   Input Parameters:
8656 + A - the matrix we wish to propagate options from
8657 - B - the matrix we wish to propagate options to
8658 
8659   Level: beginner
8660 
8661   Note:
8662   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8663 
8664 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8665 @*/
8666 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8667 {
8668   PetscFunctionBegin;
8669   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8670   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8671   B->symmetry_eternal            = A->symmetry_eternal;
8672   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8673   B->symmetric                   = A->symmetric;
8674   B->structurally_symmetric      = A->structurally_symmetric;
8675   B->spd                         = A->spd;
8676   B->hermitian                   = A->hermitian;
8677   PetscFunctionReturn(PETSC_SUCCESS);
8678 }
8679 
8680 /*@
8681   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8682   used during the assembly process to store values that belong to
8683   other processors.
8684 
8685   Not Collective
8686 
8687   Input Parameters:
8688 + mat   - the matrix
8689 . size  - the initial size of the stash.
8690 - bsize - the initial size of the block-stash(if used).
8691 
8692   Options Database Keys:
8693 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8694 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8695 
8696   Level: intermediate
8697 
8698   Notes:
8699   The block-stash is used for values set with `MatSetValuesBlocked()` while
8700   the stash is used for values set with `MatSetValues()`
8701 
8702   Run with the option -info and look for output of the form
8703   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8704   to determine the appropriate value, MM, to use for size and
8705   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8706   to determine the value, BMM to use for bsize
8707 
8708 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8709 @*/
8710 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8711 {
8712   PetscFunctionBegin;
8713   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8714   PetscValidType(mat, 1);
8715   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8716   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8717   PetscFunctionReturn(PETSC_SUCCESS);
8718 }
8719 
8720 /*@
8721   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8722   the matrix
8723 
8724   Neighbor-wise Collective
8725 
8726   Input Parameters:
8727 + A - the matrix
8728 . x - the vector to be multiplied by the interpolation operator
8729 - y - the vector to be added to the result
8730 
8731   Output Parameter:
8732 . w - the resulting vector
8733 
8734   Level: intermediate
8735 
8736   Notes:
8737   `w` may be the same vector as `y`.
8738 
8739   This allows one to use either the restriction or interpolation (its transpose)
8740   matrix to do the interpolation
8741 
8742 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8743 @*/
8744 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8745 {
8746   PetscInt M, N, Ny;
8747 
8748   PetscFunctionBegin;
8749   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8750   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8751   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8752   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8753   PetscCall(MatGetSize(A, &M, &N));
8754   PetscCall(VecGetSize(y, &Ny));
8755   if (M == Ny) {
8756     PetscCall(MatMultAdd(A, x, y, w));
8757   } else {
8758     PetscCall(MatMultTransposeAdd(A, x, y, w));
8759   }
8760   PetscFunctionReturn(PETSC_SUCCESS);
8761 }
8762 
8763 /*@
8764   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8765   the matrix
8766 
8767   Neighbor-wise Collective
8768 
8769   Input Parameters:
8770 + A - the matrix
8771 - x - the vector to be interpolated
8772 
8773   Output Parameter:
8774 . y - the resulting vector
8775 
8776   Level: intermediate
8777 
8778   Note:
8779   This allows one to use either the restriction or interpolation (its transpose)
8780   matrix to do the interpolation
8781 
8782 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8783 @*/
8784 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8785 {
8786   PetscInt M, N, Ny;
8787 
8788   PetscFunctionBegin;
8789   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8790   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8791   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8792   PetscCall(MatGetSize(A, &M, &N));
8793   PetscCall(VecGetSize(y, &Ny));
8794   if (M == Ny) {
8795     PetscCall(MatMult(A, x, y));
8796   } else {
8797     PetscCall(MatMultTranspose(A, x, y));
8798   }
8799   PetscFunctionReturn(PETSC_SUCCESS);
8800 }
8801 
8802 /*@
8803   MatRestrict - $y = A*x$ or $A^T*x$
8804 
8805   Neighbor-wise Collective
8806 
8807   Input Parameters:
8808 + A - the matrix
8809 - x - the vector to be restricted
8810 
8811   Output Parameter:
8812 . y - the resulting vector
8813 
8814   Level: intermediate
8815 
8816   Note:
8817   This allows one to use either the restriction or interpolation (its transpose)
8818   matrix to do the restriction
8819 
8820 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8821 @*/
8822 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8823 {
8824   PetscInt M, N, Nx;
8825 
8826   PetscFunctionBegin;
8827   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8828   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8829   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8830   PetscCall(MatGetSize(A, &M, &N));
8831   PetscCall(VecGetSize(x, &Nx));
8832   if (M == Nx) {
8833     PetscCall(MatMultTranspose(A, x, y));
8834   } else {
8835     PetscCall(MatMult(A, x, y));
8836   }
8837   PetscFunctionReturn(PETSC_SUCCESS);
8838 }
8839 
8840 /*@
8841   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8842 
8843   Neighbor-wise Collective
8844 
8845   Input Parameters:
8846 + A - the matrix
8847 . x - the input dense matrix to be multiplied
8848 - w - the input dense matrix to be added to the result
8849 
8850   Output Parameter:
8851 . y - the output dense matrix
8852 
8853   Level: intermediate
8854 
8855   Note:
8856   This allows one to use either the restriction or interpolation (its transpose)
8857   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8858   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8859 
8860 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8861 @*/
8862 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8863 {
8864   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8865   PetscBool trans = PETSC_TRUE;
8866   MatReuse  reuse = MAT_INITIAL_MATRIX;
8867 
8868   PetscFunctionBegin;
8869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8870   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8871   PetscValidType(x, 2);
8872   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8873   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8874   PetscCall(MatGetSize(A, &M, &N));
8875   PetscCall(MatGetSize(x, &Mx, &Nx));
8876   if (N == Mx) trans = PETSC_FALSE;
8877   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);
8878   Mo = trans ? N : M;
8879   if (*y) {
8880     PetscCall(MatGetSize(*y, &My, &Ny));
8881     if (Mo == My && Nx == Ny) {
8882       reuse = MAT_REUSE_MATRIX;
8883     } else {
8884       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);
8885       PetscCall(MatDestroy(y));
8886     }
8887   }
8888 
8889   if (w && *y == w) { /* this is to minimize changes in PCMG */
8890     PetscBool flg;
8891 
8892     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8893     if (w) {
8894       PetscInt My, Ny, Mw, Nw;
8895 
8896       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8897       PetscCall(MatGetSize(*y, &My, &Ny));
8898       PetscCall(MatGetSize(w, &Mw, &Nw));
8899       if (!flg || My != Mw || Ny != Nw) w = NULL;
8900     }
8901     if (!w) {
8902       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8903       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8904       PetscCall(PetscObjectDereference((PetscObject)w));
8905     } else {
8906       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8907     }
8908   }
8909   if (!trans) {
8910     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8911   } else {
8912     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8913   }
8914   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8915   PetscFunctionReturn(PETSC_SUCCESS);
8916 }
8917 
8918 /*@
8919   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8920 
8921   Neighbor-wise Collective
8922 
8923   Input Parameters:
8924 + A - the matrix
8925 - x - the input dense matrix
8926 
8927   Output Parameter:
8928 . y - the output dense matrix
8929 
8930   Level: intermediate
8931 
8932   Note:
8933   This allows one to use either the restriction or interpolation (its transpose)
8934   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8935   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8936 
8937 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8938 @*/
8939 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8940 {
8941   PetscFunctionBegin;
8942   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8943   PetscFunctionReturn(PETSC_SUCCESS);
8944 }
8945 
8946 /*@
8947   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8948 
8949   Neighbor-wise Collective
8950 
8951   Input Parameters:
8952 + A - the matrix
8953 - x - the input dense matrix
8954 
8955   Output Parameter:
8956 . y - the output dense matrix
8957 
8958   Level: intermediate
8959 
8960   Note:
8961   This allows one to use either the restriction or interpolation (its transpose)
8962   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8963   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8964 
8965 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8966 @*/
8967 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8968 {
8969   PetscFunctionBegin;
8970   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8971   PetscFunctionReturn(PETSC_SUCCESS);
8972 }
8973 
8974 /*@
8975   MatGetNullSpace - retrieves the null space of a matrix.
8976 
8977   Logically Collective
8978 
8979   Input Parameters:
8980 + mat    - the matrix
8981 - nullsp - the null space object
8982 
8983   Level: developer
8984 
8985 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8986 @*/
8987 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8988 {
8989   PetscFunctionBegin;
8990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8991   PetscAssertPointer(nullsp, 2);
8992   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8993   PetscFunctionReturn(PETSC_SUCCESS);
8994 }
8995 
8996 /*@C
8997   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8998 
8999   Logically Collective
9000 
9001   Input Parameters:
9002 + n   - the number of matrices
9003 - mat - the array of matrices
9004 
9005   Output Parameters:
9006 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
9007 
9008   Level: developer
9009 
9010   Note:
9011   Call `MatRestoreNullspaces()` to provide these to another array of matrices
9012 
9013 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9014           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
9015 @*/
9016 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9017 {
9018   PetscFunctionBegin;
9019   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9020   PetscAssertPointer(mat, 2);
9021   PetscAssertPointer(nullsp, 3);
9022 
9023   PetscCall(PetscCalloc1(3 * n, nullsp));
9024   for (PetscInt i = 0; i < n; i++) {
9025     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9026     (*nullsp)[i] = mat[i]->nullsp;
9027     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9028     (*nullsp)[n + i] = mat[i]->nearnullsp;
9029     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9030     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9031     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9032   }
9033   PetscFunctionReturn(PETSC_SUCCESS);
9034 }
9035 
9036 /*@C
9037   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9038 
9039   Logically Collective
9040 
9041   Input Parameters:
9042 + n      - the number of matrices
9043 . mat    - the array of matrices
9044 - nullsp - an array of null spaces
9045 
9046   Level: developer
9047 
9048   Note:
9049   Call `MatGetNullSpaces()` to create `nullsp`
9050 
9051 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9052           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9053 @*/
9054 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9055 {
9056   PetscFunctionBegin;
9057   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9058   PetscAssertPointer(mat, 2);
9059   PetscAssertPointer(nullsp, 3);
9060   PetscAssertPointer(*nullsp, 3);
9061 
9062   for (PetscInt i = 0; i < n; i++) {
9063     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9064     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9065     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9066     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9067     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9068     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9069     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9070   }
9071   PetscCall(PetscFree(*nullsp));
9072   PetscFunctionReturn(PETSC_SUCCESS);
9073 }
9074 
9075 /*@
9076   MatSetNullSpace - attaches a null space to a matrix.
9077 
9078   Logically Collective
9079 
9080   Input Parameters:
9081 + mat    - the matrix
9082 - nullsp - the null space object
9083 
9084   Level: advanced
9085 
9086   Notes:
9087   This null space is used by the `KSP` linear solvers to solve singular systems.
9088 
9089   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`
9090 
9091   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
9092   to zero but the linear system will still be solved in a least squares sense.
9093 
9094   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9095   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)$.
9096   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
9097   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
9098   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$).
9099   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9100 
9101   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9102   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9103   routine also automatically calls `MatSetTransposeNullSpace()`.
9104 
9105   The user should call `MatNullSpaceDestroy()`.
9106 
9107 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9108           `KSPSetPCSide()`
9109 @*/
9110 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9111 {
9112   PetscFunctionBegin;
9113   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9114   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9115   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9116   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9117   mat->nullsp = nullsp;
9118   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9119   PetscFunctionReturn(PETSC_SUCCESS);
9120 }
9121 
9122 /*@
9123   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9124 
9125   Logically Collective
9126 
9127   Input Parameters:
9128 + mat    - the matrix
9129 - nullsp - the null space object
9130 
9131   Level: developer
9132 
9133 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9134 @*/
9135 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9136 {
9137   PetscFunctionBegin;
9138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9139   PetscValidType(mat, 1);
9140   PetscAssertPointer(nullsp, 2);
9141   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9142   PetscFunctionReturn(PETSC_SUCCESS);
9143 }
9144 
9145 /*@
9146   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9147 
9148   Logically Collective
9149 
9150   Input Parameters:
9151 + mat    - the matrix
9152 - nullsp - the null space object
9153 
9154   Level: advanced
9155 
9156   Notes:
9157   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9158 
9159   See `MatSetNullSpace()`
9160 
9161 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9162 @*/
9163 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9164 {
9165   PetscFunctionBegin;
9166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9167   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9168   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9169   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9170   mat->transnullsp = nullsp;
9171   PetscFunctionReturn(PETSC_SUCCESS);
9172 }
9173 
9174 /*@
9175   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9176   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9177 
9178   Logically Collective
9179 
9180   Input Parameters:
9181 + mat    - the matrix
9182 - nullsp - the null space object
9183 
9184   Level: advanced
9185 
9186   Notes:
9187   Overwrites any previous near null space that may have been attached
9188 
9189   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9190 
9191 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9192 @*/
9193 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9194 {
9195   PetscFunctionBegin;
9196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9197   PetscValidType(mat, 1);
9198   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9199   MatCheckPreallocated(mat, 1);
9200   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9201   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9202   mat->nearnullsp = nullsp;
9203   PetscFunctionReturn(PETSC_SUCCESS);
9204 }
9205 
9206 /*@
9207   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9208 
9209   Not Collective
9210 
9211   Input Parameter:
9212 . mat - the matrix
9213 
9214   Output Parameter:
9215 . nullsp - the null space object, `NULL` if not set
9216 
9217   Level: advanced
9218 
9219 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9220 @*/
9221 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9222 {
9223   PetscFunctionBegin;
9224   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9225   PetscValidType(mat, 1);
9226   PetscAssertPointer(nullsp, 2);
9227   MatCheckPreallocated(mat, 1);
9228   *nullsp = mat->nearnullsp;
9229   PetscFunctionReturn(PETSC_SUCCESS);
9230 }
9231 
9232 /*@
9233   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9234 
9235   Collective
9236 
9237   Input Parameters:
9238 + mat  - the matrix
9239 . row  - row/column permutation
9240 - info - information on desired factorization process
9241 
9242   Level: developer
9243 
9244   Notes:
9245   Probably really in-place only when level of fill is zero, otherwise allocates
9246   new space to store factored matrix and deletes previous memory.
9247 
9248   Most users should employ the `KSP` interface for linear solvers
9249   instead of working directly with matrix algebra routines such as this.
9250   See, e.g., `KSPCreate()`.
9251 
9252   Developer Note:
9253   The Fortran interface is not autogenerated as the
9254   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9255 
9256 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9257 @*/
9258 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9259 {
9260   PetscFunctionBegin;
9261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9262   PetscValidType(mat, 1);
9263   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9264   PetscAssertPointer(info, 3);
9265   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9268   MatCheckPreallocated(mat, 1);
9269   PetscUseTypeMethod(mat, iccfactor, row, info);
9270   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9271   PetscFunctionReturn(PETSC_SUCCESS);
9272 }
9273 
9274 /*@
9275   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9276   ghosted ones.
9277 
9278   Not Collective
9279 
9280   Input Parameters:
9281 + mat  - the matrix
9282 - diag - the diagonal values, including ghost ones
9283 
9284   Level: developer
9285 
9286   Notes:
9287   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9288 
9289   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9290 
9291 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9292 @*/
9293 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9294 {
9295   PetscMPIInt size;
9296 
9297   PetscFunctionBegin;
9298   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9299   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9300   PetscValidType(mat, 1);
9301 
9302   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9303   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9304   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9305   if (size == 1) {
9306     PetscInt n, m;
9307     PetscCall(VecGetSize(diag, &n));
9308     PetscCall(MatGetSize(mat, NULL, &m));
9309     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9310     PetscCall(MatDiagonalScale(mat, NULL, diag));
9311   } else {
9312     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9313   }
9314   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9315   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9316   PetscFunctionReturn(PETSC_SUCCESS);
9317 }
9318 
9319 /*@
9320   MatGetInertia - Gets the inertia from a factored matrix
9321 
9322   Collective
9323 
9324   Input Parameter:
9325 . mat - the matrix
9326 
9327   Output Parameters:
9328 + nneg  - number of negative eigenvalues
9329 . nzero - number of zero eigenvalues
9330 - npos  - number of positive eigenvalues
9331 
9332   Level: advanced
9333 
9334   Note:
9335   Matrix must have been factored by `MatCholeskyFactor()`
9336 
9337 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9338 @*/
9339 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9340 {
9341   PetscFunctionBegin;
9342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9343   PetscValidType(mat, 1);
9344   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9345   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9346   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9347   PetscFunctionReturn(PETSC_SUCCESS);
9348 }
9349 
9350 /*@C
9351   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9352 
9353   Neighbor-wise Collective
9354 
9355   Input Parameters:
9356 + mat - the factored matrix obtained with `MatGetFactor()`
9357 - b   - the right-hand-side vectors
9358 
9359   Output Parameter:
9360 . x - the result vectors
9361 
9362   Level: developer
9363 
9364   Note:
9365   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9366   call `MatSolves`(A,x,x).
9367 
9368 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9369 @*/
9370 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9371 {
9372   PetscFunctionBegin;
9373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9374   PetscValidType(mat, 1);
9375   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9376   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9377   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9378 
9379   MatCheckPreallocated(mat, 1);
9380   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9381   PetscUseTypeMethod(mat, solves, b, x);
9382   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9383   PetscFunctionReturn(PETSC_SUCCESS);
9384 }
9385 
9386 /*@
9387   MatIsSymmetric - Test whether a matrix is symmetric
9388 
9389   Collective
9390 
9391   Input Parameters:
9392 + A   - the matrix to test
9393 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9394 
9395   Output Parameter:
9396 . flg - the result
9397 
9398   Level: intermediate
9399 
9400   Notes:
9401   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9402 
9403   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9404 
9405   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9406   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9407 
9408 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9409           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9410 @*/
9411 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9412 {
9413   PetscFunctionBegin;
9414   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9415   PetscAssertPointer(flg, 3);
9416   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9417   else {
9418     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9419     else PetscCall(MatIsTranspose(A, A, tol, flg));
9420     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9421   }
9422   PetscFunctionReturn(PETSC_SUCCESS);
9423 }
9424 
9425 /*@
9426   MatIsHermitian - Test whether a matrix is Hermitian
9427 
9428   Collective
9429 
9430   Input Parameters:
9431 + A   - the matrix to test
9432 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9433 
9434   Output Parameter:
9435 . flg - the result
9436 
9437   Level: intermediate
9438 
9439   Notes:
9440   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9441 
9442   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9443 
9444   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9445   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9446 
9447 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9448           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9449 @*/
9450 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9451 {
9452   PetscFunctionBegin;
9453   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9454   PetscAssertPointer(flg, 3);
9455   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9456   else {
9457     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9458     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9459     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9460   }
9461   PetscFunctionReturn(PETSC_SUCCESS);
9462 }
9463 
9464 /*@
9465   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9466 
9467   Not Collective
9468 
9469   Input Parameter:
9470 . A - the matrix to check
9471 
9472   Output Parameters:
9473 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9474 - flg - the result (only valid if set is `PETSC_TRUE`)
9475 
9476   Level: advanced
9477 
9478   Notes:
9479   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9480   if you want it explicitly checked
9481 
9482   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9483   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9484 
9485 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9486 @*/
9487 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9488 {
9489   PetscFunctionBegin;
9490   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9491   PetscAssertPointer(set, 2);
9492   PetscAssertPointer(flg, 3);
9493   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9494     *set = PETSC_TRUE;
9495     *flg = PetscBool3ToBool(A->symmetric);
9496   } else {
9497     *set = PETSC_FALSE;
9498   }
9499   PetscFunctionReturn(PETSC_SUCCESS);
9500 }
9501 
9502 /*@
9503   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9504 
9505   Not Collective
9506 
9507   Input Parameter:
9508 . A - the matrix to check
9509 
9510   Output Parameters:
9511 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9512 - flg - the result (only valid if set is `PETSC_TRUE`)
9513 
9514   Level: advanced
9515 
9516   Notes:
9517   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9518 
9519   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9520   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9521 
9522 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9523 @*/
9524 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9525 {
9526   PetscFunctionBegin;
9527   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9528   PetscAssertPointer(set, 2);
9529   PetscAssertPointer(flg, 3);
9530   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9531     *set = PETSC_TRUE;
9532     *flg = PetscBool3ToBool(A->spd);
9533   } else {
9534     *set = PETSC_FALSE;
9535   }
9536   PetscFunctionReturn(PETSC_SUCCESS);
9537 }
9538 
9539 /*@
9540   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9541 
9542   Not Collective
9543 
9544   Input Parameter:
9545 . A - the matrix to check
9546 
9547   Output Parameters:
9548 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9549 - flg - the result (only valid if set is `PETSC_TRUE`)
9550 
9551   Level: advanced
9552 
9553   Notes:
9554   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9555   if you want it explicitly checked
9556 
9557   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9558   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9559 
9560 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9561 @*/
9562 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9563 {
9564   PetscFunctionBegin;
9565   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9566   PetscAssertPointer(set, 2);
9567   PetscAssertPointer(flg, 3);
9568   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9569     *set = PETSC_TRUE;
9570     *flg = PetscBool3ToBool(A->hermitian);
9571   } else {
9572     *set = PETSC_FALSE;
9573   }
9574   PetscFunctionReturn(PETSC_SUCCESS);
9575 }
9576 
9577 /*@
9578   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9579 
9580   Collective
9581 
9582   Input Parameter:
9583 . A - the matrix to test
9584 
9585   Output Parameter:
9586 . flg - the result
9587 
9588   Level: intermediate
9589 
9590   Notes:
9591   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9592 
9593   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
9594   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9595 
9596 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9597 @*/
9598 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9599 {
9600   PetscFunctionBegin;
9601   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9602   PetscAssertPointer(flg, 2);
9603   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9604     *flg = PetscBool3ToBool(A->structurally_symmetric);
9605   } else {
9606     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9607     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9608   }
9609   PetscFunctionReturn(PETSC_SUCCESS);
9610 }
9611 
9612 /*@
9613   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9614 
9615   Not Collective
9616 
9617   Input Parameter:
9618 . A - the matrix to check
9619 
9620   Output Parameters:
9621 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9622 - flg - the result (only valid if set is PETSC_TRUE)
9623 
9624   Level: advanced
9625 
9626   Notes:
9627   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
9628   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9629 
9630   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9631 
9632 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9633 @*/
9634 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9635 {
9636   PetscFunctionBegin;
9637   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9638   PetscAssertPointer(set, 2);
9639   PetscAssertPointer(flg, 3);
9640   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9641     *set = PETSC_TRUE;
9642     *flg = PetscBool3ToBool(A->structurally_symmetric);
9643   } else {
9644     *set = PETSC_FALSE;
9645   }
9646   PetscFunctionReturn(PETSC_SUCCESS);
9647 }
9648 
9649 /*@
9650   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9651   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9652 
9653   Not Collective
9654 
9655   Input Parameter:
9656 . mat - the matrix
9657 
9658   Output Parameters:
9659 + nstash    - the size of the stash
9660 . reallocs  - the number of additional mallocs incurred.
9661 . bnstash   - the size of the block stash
9662 - breallocs - the number of additional mallocs incurred.in the block stash
9663 
9664   Level: advanced
9665 
9666 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9667 @*/
9668 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9669 {
9670   PetscFunctionBegin;
9671   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9672   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9673   PetscFunctionReturn(PETSC_SUCCESS);
9674 }
9675 
9676 /*@
9677   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9678   parallel layout, `PetscLayout` for rows and columns
9679 
9680   Collective
9681 
9682   Input Parameter:
9683 . mat - the matrix
9684 
9685   Output Parameters:
9686 + right - (optional) vector that the matrix can be multiplied against
9687 - left  - (optional) vector that the matrix vector product can be stored in
9688 
9689   Level: advanced
9690 
9691   Notes:
9692   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()`.
9693 
9694   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9695 
9696 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9697 @*/
9698 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9699 {
9700   PetscFunctionBegin;
9701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9702   PetscValidType(mat, 1);
9703   if (mat->ops->getvecs) {
9704     PetscUseTypeMethod(mat, getvecs, right, left);
9705   } else {
9706     if (right) {
9707       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9708       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9709       PetscCall(VecSetType(*right, mat->defaultvectype));
9710 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9711       if (mat->boundtocpu && mat->bindingpropagates) {
9712         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9713         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9714       }
9715 #endif
9716     }
9717     if (left) {
9718       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9719       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9720       PetscCall(VecSetType(*left, mat->defaultvectype));
9721 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9722       if (mat->boundtocpu && mat->bindingpropagates) {
9723         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9724         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9725       }
9726 #endif
9727     }
9728   }
9729   PetscFunctionReturn(PETSC_SUCCESS);
9730 }
9731 
9732 /*@
9733   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9734   with default values.
9735 
9736   Not Collective
9737 
9738   Input Parameter:
9739 . info - the `MatFactorInfo` data structure
9740 
9741   Level: developer
9742 
9743   Notes:
9744   The solvers are generally used through the `KSP` and `PC` objects, for example
9745   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9746 
9747   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9748 
9749 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9750 @*/
9751 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9752 {
9753   PetscFunctionBegin;
9754   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9755   PetscFunctionReturn(PETSC_SUCCESS);
9756 }
9757 
9758 /*@
9759   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9760 
9761   Collective
9762 
9763   Input Parameters:
9764 + mat - the factored matrix
9765 - is  - the index set defining the Schur indices (0-based)
9766 
9767   Level: advanced
9768 
9769   Notes:
9770   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9771 
9772   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9773 
9774   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9775 
9776 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9777           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9778 @*/
9779 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9780 {
9781   PetscErrorCode (*f)(Mat, IS);
9782 
9783   PetscFunctionBegin;
9784   PetscValidType(mat, 1);
9785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9786   PetscValidType(is, 2);
9787   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9788   PetscCheckSameComm(mat, 1, is, 2);
9789   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9790   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9791   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9792   PetscCall(MatDestroy(&mat->schur));
9793   PetscCall((*f)(mat, is));
9794   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9795   PetscFunctionReturn(PETSC_SUCCESS);
9796 }
9797 
9798 /*@
9799   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9800 
9801   Logically Collective
9802 
9803   Input Parameters:
9804 + F      - the factored matrix obtained by calling `MatGetFactor()`
9805 . S      - location where to return the Schur complement, can be `NULL`
9806 - status - the status of the Schur complement matrix, can be `NULL`
9807 
9808   Level: advanced
9809 
9810   Notes:
9811   You must call `MatFactorSetSchurIS()` before calling this routine.
9812 
9813   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9814 
9815   The routine provides a copy of the Schur matrix stored within the solver data structures.
9816   The caller must destroy the object when it is no longer needed.
9817   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9818 
9819   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)
9820 
9821   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9822 
9823   Developer Note:
9824   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9825   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9826 
9827 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9828 @*/
9829 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9830 {
9831   PetscFunctionBegin;
9832   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9833   if (S) PetscAssertPointer(S, 2);
9834   if (status) PetscAssertPointer(status, 3);
9835   if (S) {
9836     PetscErrorCode (*f)(Mat, Mat *);
9837 
9838     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9839     if (f) {
9840       PetscCall((*f)(F, S));
9841     } else {
9842       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9843     }
9844   }
9845   if (status) *status = F->schur_status;
9846   PetscFunctionReturn(PETSC_SUCCESS);
9847 }
9848 
9849 /*@
9850   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9851 
9852   Logically Collective
9853 
9854   Input Parameters:
9855 + F      - the factored matrix obtained by calling `MatGetFactor()`
9856 . S      - location where to return the Schur complement, can be `NULL`
9857 - status - the status of the Schur complement matrix, can be `NULL`
9858 
9859   Level: advanced
9860 
9861   Notes:
9862   You must call `MatFactorSetSchurIS()` before calling this routine.
9863 
9864   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9865 
9866   The routine returns a the Schur Complement stored within the data structures of the solver.
9867 
9868   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9869 
9870   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9871 
9872   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9873 
9874   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9875 
9876 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9877 @*/
9878 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9879 {
9880   PetscFunctionBegin;
9881   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9882   if (S) {
9883     PetscAssertPointer(S, 2);
9884     *S = F->schur;
9885   }
9886   if (status) {
9887     PetscAssertPointer(status, 3);
9888     *status = F->schur_status;
9889   }
9890   PetscFunctionReturn(PETSC_SUCCESS);
9891 }
9892 
9893 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9894 {
9895   Mat S = F->schur;
9896 
9897   PetscFunctionBegin;
9898   switch (F->schur_status) {
9899   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9900   case MAT_FACTOR_SCHUR_INVERTED:
9901     if (S) {
9902       S->ops->solve             = NULL;
9903       S->ops->matsolve          = NULL;
9904       S->ops->solvetranspose    = NULL;
9905       S->ops->matsolvetranspose = NULL;
9906       S->ops->solveadd          = NULL;
9907       S->ops->solvetransposeadd = NULL;
9908       S->factortype             = MAT_FACTOR_NONE;
9909       PetscCall(PetscFree(S->solvertype));
9910     }
9911   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9912     break;
9913   default:
9914     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9915   }
9916   PetscFunctionReturn(PETSC_SUCCESS);
9917 }
9918 
9919 /*@
9920   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9921 
9922   Logically Collective
9923 
9924   Input Parameters:
9925 + F      - the factored matrix obtained by calling `MatGetFactor()`
9926 . S      - location where the Schur complement is stored
9927 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9928 
9929   Level: advanced
9930 
9931 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9932 @*/
9933 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9934 {
9935   PetscFunctionBegin;
9936   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9937   if (S) {
9938     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9939     *S = NULL;
9940   }
9941   F->schur_status = status;
9942   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9943   PetscFunctionReturn(PETSC_SUCCESS);
9944 }
9945 
9946 /*@
9947   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9948 
9949   Logically Collective
9950 
9951   Input Parameters:
9952 + F   - the factored matrix obtained by calling `MatGetFactor()`
9953 . rhs - location where the right-hand side of the Schur complement system is stored
9954 - sol - location where the solution of the Schur complement system has to be returned
9955 
9956   Level: advanced
9957 
9958   Notes:
9959   The sizes of the vectors should match the size of the Schur complement
9960 
9961   Must be called after `MatFactorSetSchurIS()`
9962 
9963 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9964 @*/
9965 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9966 {
9967   PetscFunctionBegin;
9968   PetscValidType(F, 1);
9969   PetscValidType(rhs, 2);
9970   PetscValidType(sol, 3);
9971   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9972   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9973   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9974   PetscCheckSameComm(F, 1, rhs, 2);
9975   PetscCheckSameComm(F, 1, sol, 3);
9976   PetscCall(MatFactorFactorizeSchurComplement(F));
9977   switch (F->schur_status) {
9978   case MAT_FACTOR_SCHUR_FACTORED:
9979     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9980     break;
9981   case MAT_FACTOR_SCHUR_INVERTED:
9982     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9983     break;
9984   default:
9985     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9986   }
9987   PetscFunctionReturn(PETSC_SUCCESS);
9988 }
9989 
9990 /*@
9991   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9992 
9993   Logically Collective
9994 
9995   Input Parameters:
9996 + F   - the factored matrix obtained by calling `MatGetFactor()`
9997 . rhs - location where the right-hand side of the Schur complement system is stored
9998 - sol - location where the solution of the Schur complement system has to be returned
9999 
10000   Level: advanced
10001 
10002   Notes:
10003   The sizes of the vectors should match the size of the Schur complement
10004 
10005   Must be called after `MatFactorSetSchurIS()`
10006 
10007 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
10008 @*/
10009 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
10010 {
10011   PetscFunctionBegin;
10012   PetscValidType(F, 1);
10013   PetscValidType(rhs, 2);
10014   PetscValidType(sol, 3);
10015   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10016   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10017   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10018   PetscCheckSameComm(F, 1, rhs, 2);
10019   PetscCheckSameComm(F, 1, sol, 3);
10020   PetscCall(MatFactorFactorizeSchurComplement(F));
10021   switch (F->schur_status) {
10022   case MAT_FACTOR_SCHUR_FACTORED:
10023     PetscCall(MatSolve(F->schur, rhs, sol));
10024     break;
10025   case MAT_FACTOR_SCHUR_INVERTED:
10026     PetscCall(MatMult(F->schur, rhs, sol));
10027     break;
10028   default:
10029     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10030   }
10031   PetscFunctionReturn(PETSC_SUCCESS);
10032 }
10033 
10034 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10035 #if PetscDefined(HAVE_CUDA)
10036 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10037 #endif
10038 
10039 /* Schur status updated in the interface */
10040 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10041 {
10042   Mat S = F->schur;
10043 
10044   PetscFunctionBegin;
10045   if (S) {
10046     PetscMPIInt size;
10047     PetscBool   isdense, isdensecuda;
10048 
10049     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10050     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10051     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10052     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10053     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10054     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10055     if (isdense) {
10056       PetscCall(MatSeqDenseInvertFactors_Private(S));
10057     } else if (isdensecuda) {
10058 #if defined(PETSC_HAVE_CUDA)
10059       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10060 #endif
10061     }
10062     // HIP??????????????
10063     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10064   }
10065   PetscFunctionReturn(PETSC_SUCCESS);
10066 }
10067 
10068 /*@
10069   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10070 
10071   Logically Collective
10072 
10073   Input Parameter:
10074 . F - the factored matrix obtained by calling `MatGetFactor()`
10075 
10076   Level: advanced
10077 
10078   Notes:
10079   Must be called after `MatFactorSetSchurIS()`.
10080 
10081   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10082 
10083 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10084 @*/
10085 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10086 {
10087   PetscFunctionBegin;
10088   PetscValidType(F, 1);
10089   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10090   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10091   PetscCall(MatFactorFactorizeSchurComplement(F));
10092   PetscCall(MatFactorInvertSchurComplement_Private(F));
10093   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10094   PetscFunctionReturn(PETSC_SUCCESS);
10095 }
10096 
10097 /*@
10098   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10099 
10100   Logically Collective
10101 
10102   Input Parameter:
10103 . F - the factored matrix obtained by calling `MatGetFactor()`
10104 
10105   Level: advanced
10106 
10107   Note:
10108   Must be called after `MatFactorSetSchurIS()`
10109 
10110 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10111 @*/
10112 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10113 {
10114   MatFactorInfo info;
10115 
10116   PetscFunctionBegin;
10117   PetscValidType(F, 1);
10118   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10119   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10120   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10121   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10122   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10123     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10124   } else {
10125     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10126   }
10127   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10128   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10129   PetscFunctionReturn(PETSC_SUCCESS);
10130 }
10131 
10132 /*@
10133   MatPtAP - Creates the matrix product $C = P^T * A * P$
10134 
10135   Neighbor-wise Collective
10136 
10137   Input Parameters:
10138 + A     - the matrix
10139 . P     - the projection matrix
10140 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10141 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10142           if the result is a dense matrix this is irrelevant
10143 
10144   Output Parameter:
10145 . C - the product matrix
10146 
10147   Level: intermediate
10148 
10149   Notes:
10150   C will be created and must be destroyed by the user with `MatDestroy()`.
10151 
10152   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10153 
10154   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10155 
10156   Developer Note:
10157   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10158 
10159 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10160 @*/
10161 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10162 {
10163   PetscFunctionBegin;
10164   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10165   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10166 
10167   if (scall == MAT_INITIAL_MATRIX) {
10168     PetscCall(MatProductCreate(A, P, NULL, C));
10169     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10170     PetscCall(MatProductSetAlgorithm(*C, "default"));
10171     PetscCall(MatProductSetFill(*C, fill));
10172 
10173     (*C)->product->api_user = PETSC_TRUE;
10174     PetscCall(MatProductSetFromOptions(*C));
10175     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);
10176     PetscCall(MatProductSymbolic(*C));
10177   } else { /* scall == MAT_REUSE_MATRIX */
10178     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10179   }
10180 
10181   PetscCall(MatProductNumeric(*C));
10182   (*C)->symmetric = A->symmetric;
10183   (*C)->spd       = A->spd;
10184   PetscFunctionReturn(PETSC_SUCCESS);
10185 }
10186 
10187 /*@
10188   MatRARt - Creates the matrix product $C = R * A * R^T$
10189 
10190   Neighbor-wise Collective
10191 
10192   Input Parameters:
10193 + A     - the matrix
10194 . R     - the projection matrix
10195 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10196 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10197           if the result is a dense matrix this is irrelevant
10198 
10199   Output Parameter:
10200 . C - the product matrix
10201 
10202   Level: intermediate
10203 
10204   Notes:
10205   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10206 
10207   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10208 
10209   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10210   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10211   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10212   We recommend using `MatPtAP()` when possible.
10213 
10214   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10215 
10216 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10217 @*/
10218 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10219 {
10220   PetscFunctionBegin;
10221   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10222   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10223 
10224   if (scall == MAT_INITIAL_MATRIX) {
10225     PetscCall(MatProductCreate(A, R, NULL, C));
10226     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10227     PetscCall(MatProductSetAlgorithm(*C, "default"));
10228     PetscCall(MatProductSetFill(*C, fill));
10229 
10230     (*C)->product->api_user = PETSC_TRUE;
10231     PetscCall(MatProductSetFromOptions(*C));
10232     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);
10233     PetscCall(MatProductSymbolic(*C));
10234   } else { /* scall == MAT_REUSE_MATRIX */
10235     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10236   }
10237 
10238   PetscCall(MatProductNumeric(*C));
10239   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10240   PetscFunctionReturn(PETSC_SUCCESS);
10241 }
10242 
10243 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10244 {
10245   PetscBool flg = PETSC_TRUE;
10246 
10247   PetscFunctionBegin;
10248   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10249   if (scall == MAT_INITIAL_MATRIX) {
10250     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10251     PetscCall(MatProductCreate(A, B, NULL, C));
10252     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10253     PetscCall(MatProductSetFill(*C, fill));
10254   } else { /* scall == MAT_REUSE_MATRIX */
10255     Mat_Product *product = (*C)->product;
10256 
10257     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10258     if (flg && product && product->type != ptype) {
10259       PetscCall(MatProductClear(*C));
10260       product = NULL;
10261     }
10262     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10263     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10264       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10265       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10266       product        = (*C)->product;
10267       product->fill  = fill;
10268       product->clear = PETSC_TRUE;
10269     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10270       flg = PETSC_FALSE;
10271       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10272     }
10273   }
10274   if (flg) {
10275     (*C)->product->api_user = PETSC_TRUE;
10276     PetscCall(MatProductSetType(*C, ptype));
10277     PetscCall(MatProductSetFromOptions(*C));
10278     PetscCall(MatProductSymbolic(*C));
10279   }
10280   PetscCall(MatProductNumeric(*C));
10281   PetscFunctionReturn(PETSC_SUCCESS);
10282 }
10283 
10284 /*@
10285   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10286 
10287   Neighbor-wise Collective
10288 
10289   Input Parameters:
10290 + A     - the left matrix
10291 . B     - the right matrix
10292 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10293 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10294           if the result is a dense matrix this is irrelevant
10295 
10296   Output Parameter:
10297 . C - the product matrix
10298 
10299   Notes:
10300   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10301 
10302   `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
10303   call to this function with `MAT_INITIAL_MATRIX`.
10304 
10305   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10306 
10307   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`,
10308   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10309 
10310   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10311 
10312   Example of Usage:
10313 .vb
10314      MatProductCreate(A,B,NULL,&C);
10315      MatProductSetType(C,MATPRODUCT_AB);
10316      MatProductSymbolic(C);
10317      MatProductNumeric(C); // compute C=A * B
10318      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10319      MatProductNumeric(C);
10320      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10321      MatProductNumeric(C);
10322 .ve
10323 
10324   Level: intermediate
10325 
10326 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10327 @*/
10328 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10329 {
10330   PetscFunctionBegin;
10331   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10332   PetscFunctionReturn(PETSC_SUCCESS);
10333 }
10334 
10335 /*@
10336   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10337 
10338   Neighbor-wise Collective
10339 
10340   Input Parameters:
10341 + A     - the left matrix
10342 . B     - the right matrix
10343 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10344 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10345 
10346   Output Parameter:
10347 . C - the product matrix
10348 
10349   Options Database Key:
10350 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10351               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10352               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10353 
10354   Level: intermediate
10355 
10356   Notes:
10357   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10358 
10359   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10360 
10361   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10362   actually needed.
10363 
10364   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10365   and for pairs of `MATMPIDENSE` matrices.
10366 
10367   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10368 
10369   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10370 
10371 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10372 @*/
10373 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10374 {
10375   PetscFunctionBegin;
10376   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10377   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10378   PetscFunctionReturn(PETSC_SUCCESS);
10379 }
10380 
10381 /*@
10382   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10383 
10384   Neighbor-wise Collective
10385 
10386   Input Parameters:
10387 + A     - the left matrix
10388 . B     - the right matrix
10389 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10390 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10391 
10392   Output Parameter:
10393 . C - the product matrix
10394 
10395   Level: intermediate
10396 
10397   Notes:
10398   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10399 
10400   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10401 
10402   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10403 
10404   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10405   actually needed.
10406 
10407   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10408   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10409 
10410   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10411 
10412 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10413 @*/
10414 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10415 {
10416   PetscFunctionBegin;
10417   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10418   PetscFunctionReturn(PETSC_SUCCESS);
10419 }
10420 
10421 /*@
10422   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10423 
10424   Neighbor-wise Collective
10425 
10426   Input Parameters:
10427 + A     - the left matrix
10428 . B     - the middle matrix
10429 . C     - the right matrix
10430 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10431 - fill  - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10432           if the result is a dense matrix this is irrelevant
10433 
10434   Output Parameter:
10435 . D - the product matrix
10436 
10437   Level: intermediate
10438 
10439   Notes:
10440   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10441 
10442   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10443 
10444   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10445 
10446   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10447   actually needed.
10448 
10449   If you have many matrices with the same non-zero structure to multiply, you
10450   should use `MAT_REUSE_MATRIX` in all calls but the first
10451 
10452   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10453 
10454 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10455 @*/
10456 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10457 {
10458   PetscFunctionBegin;
10459   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10460   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10461 
10462   if (scall == MAT_INITIAL_MATRIX) {
10463     PetscCall(MatProductCreate(A, B, C, D));
10464     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10465     PetscCall(MatProductSetAlgorithm(*D, "default"));
10466     PetscCall(MatProductSetFill(*D, fill));
10467 
10468     (*D)->product->api_user = PETSC_TRUE;
10469     PetscCall(MatProductSetFromOptions(*D));
10470     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,
10471                ((PetscObject)C)->type_name);
10472     PetscCall(MatProductSymbolic(*D));
10473   } else { /* user may change input matrices when REUSE */
10474     PetscCall(MatProductReplaceMats(A, B, C, *D));
10475   }
10476   PetscCall(MatProductNumeric(*D));
10477   PetscFunctionReturn(PETSC_SUCCESS);
10478 }
10479 
10480 /*@
10481   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10482 
10483   Collective
10484 
10485   Input Parameters:
10486 + mat      - the matrix
10487 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10488 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10489 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10490 
10491   Output Parameter:
10492 . matredundant - redundant matrix
10493 
10494   Level: advanced
10495 
10496   Notes:
10497   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10498   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10499 
10500   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10501   calling it.
10502 
10503   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10504 
10505 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10506 @*/
10507 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10508 {
10509   MPI_Comm       comm;
10510   PetscMPIInt    size;
10511   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10512   Mat_Redundant *redund     = NULL;
10513   PetscSubcomm   psubcomm   = NULL;
10514   MPI_Comm       subcomm_in = subcomm;
10515   Mat           *matseq;
10516   IS             isrow, iscol;
10517   PetscBool      newsubcomm = PETSC_FALSE;
10518 
10519   PetscFunctionBegin;
10520   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10521   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10522     PetscAssertPointer(*matredundant, 5);
10523     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10524   }
10525 
10526   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10527   if (size == 1 || nsubcomm == 1) {
10528     if (reuse == MAT_INITIAL_MATRIX) {
10529       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10530     } else {
10531       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");
10532       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10533     }
10534     PetscFunctionReturn(PETSC_SUCCESS);
10535   }
10536 
10537   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10538   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10539   MatCheckPreallocated(mat, 1);
10540 
10541   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10542   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10543     /* create psubcomm, then get subcomm */
10544     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10545     PetscCallMPI(MPI_Comm_size(comm, &size));
10546     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10547 
10548     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10549     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10550     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10551     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10552     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10553     newsubcomm = PETSC_TRUE;
10554     PetscCall(PetscSubcommDestroy(&psubcomm));
10555   }
10556 
10557   /* get isrow, iscol and a local sequential matrix matseq[0] */
10558   if (reuse == MAT_INITIAL_MATRIX) {
10559     mloc_sub = PETSC_DECIDE;
10560     nloc_sub = PETSC_DECIDE;
10561     if (bs < 1) {
10562       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10563       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10564     } else {
10565       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10566       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10567     }
10568     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10569     rstart = rend - mloc_sub;
10570     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10571     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10572     PetscCall(ISSetIdentity(iscol));
10573   } else { /* reuse == MAT_REUSE_MATRIX */
10574     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");
10575     /* retrieve subcomm */
10576     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10577     redund = (*matredundant)->redundant;
10578     isrow  = redund->isrow;
10579     iscol  = redund->iscol;
10580     matseq = redund->matseq;
10581   }
10582   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10583 
10584   /* get matredundant over subcomm */
10585   if (reuse == MAT_INITIAL_MATRIX) {
10586     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10587 
10588     /* create a supporting struct and attach it to C for reuse */
10589     PetscCall(PetscNew(&redund));
10590     (*matredundant)->redundant = redund;
10591     redund->isrow              = isrow;
10592     redund->iscol              = iscol;
10593     redund->matseq             = matseq;
10594     if (newsubcomm) {
10595       redund->subcomm = subcomm;
10596     } else {
10597       redund->subcomm = MPI_COMM_NULL;
10598     }
10599   } else {
10600     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10601   }
10602 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10603   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10604     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10605     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10606   }
10607 #endif
10608   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10609   PetscFunctionReturn(PETSC_SUCCESS);
10610 }
10611 
10612 /*@C
10613   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10614   a given `Mat`. Each submatrix can span multiple procs.
10615 
10616   Collective
10617 
10618   Input Parameters:
10619 + mat     - the matrix
10620 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10621 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10622 
10623   Output Parameter:
10624 . subMat - parallel sub-matrices each spanning a given `subcomm`
10625 
10626   Level: advanced
10627 
10628   Notes:
10629   The submatrix partition across processors is dictated by `subComm` a
10630   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10631   is not restricted to be grouped with consecutive original MPI processes.
10632 
10633   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10634   map directly to the layout of the original matrix [wrt the local
10635   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10636   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10637   the `subMat`. However the offDiagMat looses some columns - and this is
10638   reconstructed with `MatSetValues()`
10639 
10640   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10641 
10642 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10643 @*/
10644 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10645 {
10646   PetscMPIInt commsize, subCommSize;
10647 
10648   PetscFunctionBegin;
10649   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10650   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10651   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10652 
10653   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");
10654   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10655   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10656   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10657   PetscFunctionReturn(PETSC_SUCCESS);
10658 }
10659 
10660 /*@
10661   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10662 
10663   Not Collective
10664 
10665   Input Parameters:
10666 + mat   - matrix to extract local submatrix from
10667 . isrow - local row indices for submatrix
10668 - iscol - local column indices for submatrix
10669 
10670   Output Parameter:
10671 . submat - the submatrix
10672 
10673   Level: intermediate
10674 
10675   Notes:
10676   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10677 
10678   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10679   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10680 
10681   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10682   `MatSetValuesBlockedLocal()` will also be implemented.
10683 
10684   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10685   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10686 
10687 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10688 @*/
10689 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10690 {
10691   PetscFunctionBegin;
10692   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10693   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10694   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10695   PetscCheckSameComm(isrow, 2, iscol, 3);
10696   PetscAssertPointer(submat, 4);
10697   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10698 
10699   if (mat->ops->getlocalsubmatrix) {
10700     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10701   } else {
10702     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10703   }
10704   PetscFunctionReturn(PETSC_SUCCESS);
10705 }
10706 
10707 /*@
10708   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10709 
10710   Not Collective
10711 
10712   Input Parameters:
10713 + mat    - matrix to extract local submatrix from
10714 . isrow  - local row indices for submatrix
10715 . iscol  - local column indices for submatrix
10716 - submat - the submatrix
10717 
10718   Level: intermediate
10719 
10720 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10721 @*/
10722 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10723 {
10724   PetscFunctionBegin;
10725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10726   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10727   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10728   PetscCheckSameComm(isrow, 2, iscol, 3);
10729   PetscAssertPointer(submat, 4);
10730   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10731 
10732   if (mat->ops->restorelocalsubmatrix) {
10733     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10734   } else {
10735     PetscCall(MatDestroy(submat));
10736   }
10737   *submat = NULL;
10738   PetscFunctionReturn(PETSC_SUCCESS);
10739 }
10740 
10741 /*@
10742   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10743 
10744   Collective
10745 
10746   Input Parameter:
10747 . mat - the matrix
10748 
10749   Output Parameter:
10750 . is - if any rows have zero diagonals this contains the list of them
10751 
10752   Level: developer
10753 
10754 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10755 @*/
10756 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10757 {
10758   PetscFunctionBegin;
10759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10760   PetscValidType(mat, 1);
10761   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10762   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10763 
10764   if (!mat->ops->findzerodiagonals) {
10765     Vec                diag;
10766     const PetscScalar *a;
10767     PetscInt          *rows;
10768     PetscInt           rStart, rEnd, r, nrow = 0;
10769 
10770     PetscCall(MatCreateVecs(mat, &diag, NULL));
10771     PetscCall(MatGetDiagonal(mat, diag));
10772     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10773     PetscCall(VecGetArrayRead(diag, &a));
10774     for (r = 0; r < rEnd - rStart; ++r)
10775       if (a[r] == 0.0) ++nrow;
10776     PetscCall(PetscMalloc1(nrow, &rows));
10777     nrow = 0;
10778     for (r = 0; r < rEnd - rStart; ++r)
10779       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10780     PetscCall(VecRestoreArrayRead(diag, &a));
10781     PetscCall(VecDestroy(&diag));
10782     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10783   } else {
10784     PetscUseTypeMethod(mat, findzerodiagonals, is);
10785   }
10786   PetscFunctionReturn(PETSC_SUCCESS);
10787 }
10788 
10789 /*@
10790   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10791 
10792   Collective
10793 
10794   Input Parameter:
10795 . mat - the matrix
10796 
10797   Output Parameter:
10798 . is - contains the list of rows with off block diagonal entries
10799 
10800   Level: developer
10801 
10802 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10803 @*/
10804 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10805 {
10806   PetscFunctionBegin;
10807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10808   PetscValidType(mat, 1);
10809   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10810   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10811 
10812   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10813   PetscFunctionReturn(PETSC_SUCCESS);
10814 }
10815 
10816 /*@C
10817   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10818 
10819   Collective; No Fortran Support
10820 
10821   Input Parameter:
10822 . mat - the matrix
10823 
10824   Output Parameter:
10825 . values - the block inverses in column major order (FORTRAN-like)
10826 
10827   Level: advanced
10828 
10829   Notes:
10830   The size of the blocks is determined by the block size of the matrix.
10831 
10832   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10833 
10834   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10835 
10836 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10837 @*/
10838 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10839 {
10840   PetscFunctionBegin;
10841   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10842   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10843   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10844   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10845   PetscFunctionReturn(PETSC_SUCCESS);
10846 }
10847 
10848 /*@
10849   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10850 
10851   Collective; No Fortran Support
10852 
10853   Input Parameters:
10854 + mat     - the matrix
10855 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10856 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10857 
10858   Output Parameter:
10859 . values - the block inverses in column major order (FORTRAN-like)
10860 
10861   Level: advanced
10862 
10863   Notes:
10864   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10865 
10866   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10867 
10868 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10869 @*/
10870 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10871 {
10872   PetscFunctionBegin;
10873   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10874   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10875   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10876   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10877   PetscFunctionReturn(PETSC_SUCCESS);
10878 }
10879 
10880 /*@
10881   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10882 
10883   Collective
10884 
10885   Input Parameters:
10886 + A - the matrix
10887 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10888 
10889   Level: advanced
10890 
10891   Note:
10892   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10893 
10894 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10895 @*/
10896 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10897 {
10898   const PetscScalar *vals;
10899   PetscInt          *dnnz;
10900   PetscInt           m, rstart, rend, bs, i, j;
10901 
10902   PetscFunctionBegin;
10903   PetscCall(MatInvertBlockDiagonal(A, &vals));
10904   PetscCall(MatGetBlockSize(A, &bs));
10905   PetscCall(MatGetLocalSize(A, &m, NULL));
10906   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10907   PetscCall(PetscMalloc1(m / bs, &dnnz));
10908   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10909   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10910   PetscCall(PetscFree(dnnz));
10911   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10912   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10913   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10914   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10915   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10916   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10917   PetscFunctionReturn(PETSC_SUCCESS);
10918 }
10919 
10920 /*@
10921   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10922   via `MatTransposeColoringCreate()`.
10923 
10924   Collective
10925 
10926   Input Parameter:
10927 . c - coloring context
10928 
10929   Level: intermediate
10930 
10931 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10932 @*/
10933 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10934 {
10935   MatTransposeColoring matcolor = *c;
10936 
10937   PetscFunctionBegin;
10938   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10939   if (--((PetscObject)matcolor)->refct > 0) {
10940     matcolor = NULL;
10941     PetscFunctionReturn(PETSC_SUCCESS);
10942   }
10943 
10944   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10945   PetscCall(PetscFree(matcolor->rows));
10946   PetscCall(PetscFree(matcolor->den2sp));
10947   PetscCall(PetscFree(matcolor->colorforcol));
10948   PetscCall(PetscFree(matcolor->columns));
10949   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10950   PetscCall(PetscHeaderDestroy(c));
10951   PetscFunctionReturn(PETSC_SUCCESS);
10952 }
10953 
10954 /*@
10955   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10956   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10957   `MatTransposeColoring` to sparse `B`.
10958 
10959   Collective
10960 
10961   Input Parameters:
10962 + coloring - coloring context created with `MatTransposeColoringCreate()`
10963 - B        - sparse matrix
10964 
10965   Output Parameter:
10966 . Btdense - dense matrix $B^T$
10967 
10968   Level: developer
10969 
10970   Note:
10971   These are used internally for some implementations of `MatRARt()`
10972 
10973 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10974 @*/
10975 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10976 {
10977   PetscFunctionBegin;
10978   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10979   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10980   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10981 
10982   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10983   PetscFunctionReturn(PETSC_SUCCESS);
10984 }
10985 
10986 /*@
10987   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10988   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10989   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10990   $C_{sp}$ from $C_{den}$.
10991 
10992   Collective
10993 
10994   Input Parameters:
10995 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10996 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10997 
10998   Output Parameter:
10999 . Csp - sparse matrix
11000 
11001   Level: developer
11002 
11003   Note:
11004   These are used internally for some implementations of `MatRARt()`
11005 
11006 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
11007 @*/
11008 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
11009 {
11010   PetscFunctionBegin;
11011   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11012   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
11013   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
11014 
11015   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
11016   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
11017   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
11018   PetscFunctionReturn(PETSC_SUCCESS);
11019 }
11020 
11021 /*@
11022   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
11023 
11024   Collective
11025 
11026   Input Parameters:
11027 + mat        - the matrix product C
11028 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
11029 
11030   Output Parameter:
11031 . color - the new coloring context
11032 
11033   Level: intermediate
11034 
11035 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11036           `MatTransColoringApplyDenToSp()`
11037 @*/
11038 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11039 {
11040   MatTransposeColoring c;
11041   MPI_Comm             comm;
11042 
11043   PetscFunctionBegin;
11044   PetscAssertPointer(color, 3);
11045 
11046   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11047   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11048   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11049   c->ctype = iscoloring->ctype;
11050   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11051   *color = c;
11052   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11053   PetscFunctionReturn(PETSC_SUCCESS);
11054 }
11055 
11056 /*@
11057   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11058   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11059 
11060   Not Collective
11061 
11062   Input Parameter:
11063 . mat - the matrix
11064 
11065   Output Parameter:
11066 . state - the current state
11067 
11068   Level: intermediate
11069 
11070   Notes:
11071   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11072   different matrices
11073 
11074   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11075 
11076   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11077 
11078 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11079 @*/
11080 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11081 {
11082   PetscFunctionBegin;
11083   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11084   *state = mat->nonzerostate;
11085   PetscFunctionReturn(PETSC_SUCCESS);
11086 }
11087 
11088 /*@
11089   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11090   matrices from each processor
11091 
11092   Collective
11093 
11094   Input Parameters:
11095 + comm   - the communicators the parallel matrix will live on
11096 . seqmat - the input sequential matrices
11097 . n      - number of local columns (or `PETSC_DECIDE`)
11098 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11099 
11100   Output Parameter:
11101 . mpimat - the parallel matrix generated
11102 
11103   Level: developer
11104 
11105   Note:
11106   The number of columns of the matrix in EACH processor MUST be the same.
11107 
11108 .seealso: [](ch_matrices), `Mat`
11109 @*/
11110 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11111 {
11112   PetscMPIInt size;
11113 
11114   PetscFunctionBegin;
11115   PetscCallMPI(MPI_Comm_size(comm, &size));
11116   if (size == 1) {
11117     if (reuse == MAT_INITIAL_MATRIX) {
11118       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11119     } else {
11120       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11121     }
11122     PetscFunctionReturn(PETSC_SUCCESS);
11123   }
11124 
11125   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");
11126 
11127   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11128   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11129   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11130   PetscFunctionReturn(PETSC_SUCCESS);
11131 }
11132 
11133 /*@
11134   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11135 
11136   Collective
11137 
11138   Input Parameters:
11139 + A - the matrix to create subdomains from
11140 - N - requested number of subdomains
11141 
11142   Output Parameters:
11143 + n   - number of subdomains resulting on this MPI process
11144 - iss - `IS` list with indices of subdomains on this MPI process
11145 
11146   Level: advanced
11147 
11148   Note:
11149   The number of subdomains must be smaller than the communicator size
11150 
11151 .seealso: [](ch_matrices), `Mat`, `IS`
11152 @*/
11153 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11154 {
11155   MPI_Comm    comm, subcomm;
11156   PetscMPIInt size, rank, color;
11157   PetscInt    rstart, rend, k;
11158 
11159   PetscFunctionBegin;
11160   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11161   PetscCallMPI(MPI_Comm_size(comm, &size));
11162   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11163   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);
11164   *n    = 1;
11165   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11166   color = rank / k;
11167   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11168   PetscCall(PetscMalloc1(1, iss));
11169   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11170   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11171   PetscCallMPI(MPI_Comm_free(&subcomm));
11172   PetscFunctionReturn(PETSC_SUCCESS);
11173 }
11174 
11175 /*@
11176   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11177 
11178   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11179   If they are not the same, uses `MatMatMatMult()`.
11180 
11181   Once the coarse grid problem is constructed, correct for interpolation operators
11182   that are not of full rank, which can legitimately happen in the case of non-nested
11183   geometric multigrid.
11184 
11185   Input Parameters:
11186 + restrct     - restriction operator
11187 . dA          - fine grid matrix
11188 . interpolate - interpolation operator
11189 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11190 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11191 
11192   Output Parameter:
11193 . A - the Galerkin coarse matrix
11194 
11195   Options Database Key:
11196 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11197 
11198   Level: developer
11199 
11200   Note:
11201   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11202 
11203 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11204 @*/
11205 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11206 {
11207   IS  zerorows;
11208   Vec diag;
11209 
11210   PetscFunctionBegin;
11211   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11212   /* Construct the coarse grid matrix */
11213   if (interpolate == restrct) {
11214     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11215   } else {
11216     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11217   }
11218 
11219   /* If the interpolation matrix is not of full rank, A will have zero rows.
11220      This can legitimately happen in the case of non-nested geometric multigrid.
11221      In that event, we set the rows of the matrix to the rows of the identity,
11222      ignoring the equations (as the RHS will also be zero). */
11223 
11224   PetscCall(MatFindZeroRows(*A, &zerorows));
11225 
11226   if (zerorows != NULL) { /* if there are any zero rows */
11227     PetscCall(MatCreateVecs(*A, &diag, NULL));
11228     PetscCall(MatGetDiagonal(*A, diag));
11229     PetscCall(VecISSet(diag, zerorows, 1.0));
11230     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11231     PetscCall(VecDestroy(&diag));
11232     PetscCall(ISDestroy(&zerorows));
11233   }
11234   PetscFunctionReturn(PETSC_SUCCESS);
11235 }
11236 
11237 /*@C
11238   MatSetOperation - Allows user to set a matrix operation for any matrix type
11239 
11240   Logically Collective
11241 
11242   Input Parameters:
11243 + mat - the matrix
11244 . op  - the name of the operation
11245 - f   - the function that provides the operation
11246 
11247   Level: developer
11248 
11249   Example Usage:
11250 .vb
11251   extern PetscErrorCode usermult(Mat, Vec, Vec);
11252 
11253   PetscCall(MatCreateXXX(comm, ..., &A));
11254   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11255 .ve
11256 
11257   Notes:
11258   See the file `include/petscmat.h` for a complete list of matrix
11259   operations, which all have the form MATOP_<OPERATION>, where
11260   <OPERATION> is the name (in all capital letters) of the
11261   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11262 
11263   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11264   sequence as the usual matrix interface routines, since they
11265   are intended to be accessed via the usual matrix interface
11266   routines, e.g.,
11267 .vb
11268   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11269 .ve
11270 
11271   In particular each function MUST return `PETSC_SUCCESS` on success and
11272   nonzero on failure.
11273 
11274   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11275 
11276 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11277 @*/
11278 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11279 {
11280   PetscFunctionBegin;
11281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11282   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11283   (((void (**)(void))mat->ops)[op]) = f;
11284   PetscFunctionReturn(PETSC_SUCCESS);
11285 }
11286 
11287 /*@C
11288   MatGetOperation - Gets a matrix operation for any matrix type.
11289 
11290   Not Collective
11291 
11292   Input Parameters:
11293 + mat - the matrix
11294 - op  - the name of the operation
11295 
11296   Output Parameter:
11297 . f - the function that provides the operation
11298 
11299   Level: developer
11300 
11301   Example Usage:
11302 .vb
11303   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11304 
11305   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11306 .ve
11307 
11308   Notes:
11309   See the file include/petscmat.h for a complete list of matrix
11310   operations, which all have the form MATOP_<OPERATION>, where
11311   <OPERATION> is the name (in all capital letters) of the
11312   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11313 
11314   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11315 
11316 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11317 @*/
11318 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11319 {
11320   PetscFunctionBegin;
11321   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11322   *f = (((void (**)(void))mat->ops)[op]);
11323   PetscFunctionReturn(PETSC_SUCCESS);
11324 }
11325 
11326 /*@
11327   MatHasOperation - Determines whether the given matrix supports the particular operation.
11328 
11329   Not Collective
11330 
11331   Input Parameters:
11332 + mat - the matrix
11333 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11334 
11335   Output Parameter:
11336 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11337 
11338   Level: advanced
11339 
11340   Note:
11341   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11342 
11343 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11344 @*/
11345 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11346 {
11347   PetscFunctionBegin;
11348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11349   PetscAssertPointer(has, 3);
11350   if (mat->ops->hasoperation) {
11351     PetscUseTypeMethod(mat, hasoperation, op, has);
11352   } else {
11353     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11354     else {
11355       *has = PETSC_FALSE;
11356       if (op == MATOP_CREATE_SUBMATRIX) {
11357         PetscMPIInt size;
11358 
11359         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11360         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11361       }
11362     }
11363   }
11364   PetscFunctionReturn(PETSC_SUCCESS);
11365 }
11366 
11367 /*@
11368   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11369 
11370   Collective
11371 
11372   Input Parameter:
11373 . mat - the matrix
11374 
11375   Output Parameter:
11376 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11377 
11378   Level: beginner
11379 
11380 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11381 @*/
11382 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11383 {
11384   PetscFunctionBegin;
11385   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11386   PetscValidType(mat, 1);
11387   PetscAssertPointer(cong, 2);
11388   if (!mat->rmap || !mat->cmap) {
11389     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11390     PetscFunctionReturn(PETSC_SUCCESS);
11391   }
11392   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11393     PetscCall(PetscLayoutSetUp(mat->rmap));
11394     PetscCall(PetscLayoutSetUp(mat->cmap));
11395     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11396     if (*cong) mat->congruentlayouts = 1;
11397     else mat->congruentlayouts = 0;
11398   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11399   PetscFunctionReturn(PETSC_SUCCESS);
11400 }
11401 
11402 PetscErrorCode MatSetInf(Mat A)
11403 {
11404   PetscFunctionBegin;
11405   PetscUseTypeMethod(A, setinf);
11406   PetscFunctionReturn(PETSC_SUCCESS);
11407 }
11408 
11409 /*@
11410   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
11411   and possibly removes small values from the graph structure.
11412 
11413   Collective
11414 
11415   Input Parameters:
11416 + A       - the matrix
11417 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11418 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11419 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11420 . num_idx - size of 'index' array
11421 - index   - array of block indices to use for graph strength of connection weight
11422 
11423   Output Parameter:
11424 . graph - the resulting graph
11425 
11426   Level: advanced
11427 
11428 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11429 @*/
11430 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11431 {
11432   PetscFunctionBegin;
11433   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11434   PetscValidType(A, 1);
11435   PetscValidLogicalCollectiveBool(A, scale, 3);
11436   PetscAssertPointer(graph, 7);
11437   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11438   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11439   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11440   PetscFunctionReturn(PETSC_SUCCESS);
11441 }
11442 
11443 /*@
11444   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11445   meaning the same memory is used for the matrix, and no new memory is allocated.
11446 
11447   Collective
11448 
11449   Input Parameters:
11450 + A    - the matrix
11451 - 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
11452 
11453   Level: intermediate
11454 
11455   Developer Note:
11456   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11457   of the arrays in the data structure are unneeded.
11458 
11459 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11460 @*/
11461 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11462 {
11463   PetscFunctionBegin;
11464   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11465   PetscUseTypeMethod(A, eliminatezeros, keep);
11466   PetscFunctionReturn(PETSC_SUCCESS);
11467 }
11468